From 21c4b65610027ce5e8e717866e0d778d96b83093 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 26 Feb 2004 22:00:04 +0000 Subject: [PATCH] * src/msgs/ru.msg: Updated (thanks to Sergei Golovan) * src/mod_muc/mod_muc_room.erl: Updated error codes, removed trailing "-" in history. updated subject sending, added in configuration form (thanks to Sergei Golovan) * src/mod_irc/mod_irc.erl: Added vCard, ejabberd:configure replaced with jabber:iq:register (thanks to Sergei Golovan) * src/mod_configure.erl: Updated "xml:lang" usage, updated some messages (thanks to Sergei Golovan) * src/mod_configure2.erl: Likewise * src/mod_disco.erl: Likewise * src/mod_register.erl: Likewise * src/mod_vcard.erl: Likewise * src/mod_irc/mod_irc.erl: Likewise * src/mod_muc/mod_muc.erl: Likewise * src/mod_muc/mod_muc_room.erl: Likewise * src/mod_pubsub/mod_pubsub.erl: Likewise * src/jlib.hrl: Added "lang" field in "iq" record (thanks to Sergei Golovan) * src/jlib.erl: Likewise * src/ejabberd_c2s.erl: Updated to latest JEP-0078 (thanks to Sergei Golovan) * src/ejabberd_sm.erl: Bugfix SVN Revision: 205 --- ChangeLog | 33 +++++++++++ src/ejabberd_c2s.erl | 3 +- src/ejabberd_sm.erl | 11 +++- src/jlib.erl | 6 +- src/jlib.hrl | 3 + src/mod_configure.erl | 37 ++++++------ src/mod_configure2.erl | 30 +++++----- src/mod_disco.erl | 11 ++-- src/mod_irc/mod_irc.erl | 55 ++++++++++++------ src/mod_muc/mod_muc.erl | 18 +++--- src/mod_muc/mod_muc_room.erl | 65 +++++++++++---------- src/mod_pubsub/mod_pubsub.erl | 36 ++++++------ src/mod_register.erl | 5 +- src/mod_vcard.erl | 52 ++++++++++++----- src/msgs/ru.msg | 103 ++++++++++++++++++++++++---------- 15 files changed, 302 insertions(+), 166 deletions(-) diff --git a/ChangeLog b/ChangeLog index ae8dce874..906dd7a9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2004-02-26 Alexey Shchepin <alexey@sevcom.net> + + * src/msgs/ru.msg: Updated (thanks to Sergei Golovan) + + * src/mod_muc/mod_muc_room.erl: Updated error codes, removed + trailing "-" in history. updated subject sending, added <title/> + in configuration form (thanks to Sergei Golovan) + + * src/mod_irc/mod_irc.erl: Added vCard, ejabberd:configure + replaced with jabber:iq:register (thanks to Sergei Golovan) + + * src/mod_configure.erl: Updated "xml:lang" usage, updated some + messages (thanks to Sergei Golovan) + * src/mod_configure2.erl: Likewise + * src/mod_disco.erl: Likewise + * src/mod_register.erl: Likewise + * src/mod_vcard.erl: Likewise + * src/mod_irc/mod_irc.erl: Likewise + * src/mod_muc/mod_muc.erl: Likewise + * src/mod_muc/mod_muc_room.erl: Likewise + * src/mod_pubsub/mod_pubsub.erl: Likewise + + * src/jlib.hrl: Added "lang" field in "iq" record (thanks to + Sergei Golovan) + * src/jlib.erl: Likewise + + * src/ejabberd_c2s.erl: Updated to latest JEP-0078 (thanks to + Sergei Golovan) + +2004-02-18 Alexey Shchepin <alexey@sevcom.net> + + * src/ejabberd_sm.erl: Bugfix + 2004-02-15 Alexey Shchepin <alexey@sevcom.net> * src/mod_muc/mod_muc_room.erl: Support for history management diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 8dc3b58b4..93ac7d41b 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -221,7 +221,8 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> {xmlelement, Name, Attrs, [{xmlelement, "query", [{"xmlns", ?NS_AUTH}], [{xmlelement, "username", [], [{xmlcdata, U}]}, - {xmlelement, "password", [], []} + {xmlelement, "password", [], []}, + {xmlelement, "resource", [], []} ]}]} end, send_element(StateData, Res), diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 628aa6bde..ef495d544 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -196,8 +196,15 @@ do_route(From, To, Packet) -> true -> if Subsc -> - catch mod_offline:store_packet( - From, To, Packet); + case ejabberd_auth:is_user_exists(LUser) of + true -> + catch mod_offline:store_packet( + From, To, Packet); + _ -> + Err = jlib:make_error_reply( + Packet, ?ERR_SERVICE_UNAVAILABLE), + ejabberd_router:route(To, From, Err) + end; true -> ok end diff --git a/src/jlib.erl b/src/jlib.erl index e10d5cf07..07ad93332 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -329,6 +329,7 @@ get_iq_namespace(_) -> iq_query_info({xmlelement, Name, Attrs, Els}) when Name == "iq" -> ID = xml:get_attr_s("id", Attrs), Type = xml:get_attr_s("type", Attrs), + Lang = xml:get_attr_s("xml:lang", Attrs), Type1 = case Type of "set" -> set; "get" -> get; @@ -343,7 +344,10 @@ iq_query_info({xmlelement, Name, Attrs, Els}) when Name == "iq" -> XMLNS = xml:get_attr_s("xmlns", Attrs2), if XMLNS /= "" -> - #iq{id = ID, type = Type1, xmlns = XMLNS, + #iq{id = ID, + type = Type1, + xmlns = XMLNS, + lang = Lang, sub_el = {xmlelement, Name2, Attrs2, Els2}}; true -> invalid diff --git a/src/jlib.hrl b/src/jlib.hrl index 6c9631c5a..045207cb2 100644 --- a/src/jlib.hrl +++ b/src/jlib.hrl @@ -44,6 +44,8 @@ -define(NS_SESSION, "urn:ietf:params:xml:ns:xmpp-session"). -define(NS_BIND, "urn:ietf:params:xml:ns:xmpp-bind"). +-define(NS_FEATURE_IQAUTH, "http://jabber.org/features/iq-auth"). + % TODO: remove "code" attribute (currently it used for backward-compatibility) -define(STANZA_ERROR(Code, Type, Condition), {xmlelement, "error", @@ -174,5 +176,6 @@ -record(iq, {id = "", type, xmlns = "", + lang = "", sub_el}). diff --git a/src/mod_configure.erl b/src/mod_configure.erl index fba0b31de..caf7f79b5 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -34,13 +34,12 @@ stop() -> gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_EJABBERD_CONFIG). -process_local_iq(From, _To, #iq{id = ID, type = Type, - xmlns = XMLNS, sub_el = SubEl} = IQ) -> +process_local_iq(From, _To, #iq{id = ID, type = Type, xmlns = XMLNS, + lang = Lang, sub_el = SubEl} = IQ) -> case acl:match_rule(configure, From) of deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; allow -> - Lang = xml:get_tag_attr_s("xml:lang", SubEl), case Type of set -> XDataEl = find_xdata_el(SubEl), @@ -147,7 +146,8 @@ get_form(["running nodes", ENode, "DB"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "DB Tables Configuration")}]}, + Lang, "DB Tables Configuration at ") ++ + ENode}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( @@ -182,7 +182,7 @@ get_form(["running nodes", ENode, "modules", "stop"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Stop Modules")}]}, + Lang, "Stop Modules at ") ++ ENode}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( @@ -200,7 +200,7 @@ get_form(["running nodes", ENode, "modules", "start"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Start Modules")}]}, + Lang, "Start Modules at ") ++ ENode}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( @@ -219,7 +219,7 @@ get_form(["running nodes", ENode, "backup", "backup"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Backup to File")}]}, + Lang, "Backup to File at ") ++ ENode}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( @@ -238,7 +238,7 @@ get_form(["running nodes", ENode, "backup", "restore"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Restore Backup from File")}]}, + Lang, "Restore Backup from File at ") ++ ENode}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( @@ -257,7 +257,7 @@ get_form(["running nodes", ENode, "backup", "textfile"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Dump Backup to Text File")}]}, + Lang, "Dump Backup to Text File at ") ++ ENode}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( @@ -276,7 +276,7 @@ get_form(["running nodes", ENode, "import", "file"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Import User from File")}]}, + Lang, "Import User from File at ") ++ ENode}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( @@ -295,7 +295,7 @@ get_form(["running nodes", ENode, "import", "dir"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Import User from Dir")}]}, + Lang, "Import Users from Dir at ") ++ ENode}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( @@ -321,7 +321,8 @@ get_form(["config", "hostname"], Lang) -> Lang, "Choose host name")}]}, {xmlelement, "field", [{"type", "text-single"}, {"label", - translate:translate(Lang, "Host name")}, + translate:translate(Lang, + "Host name")}, {"var", "hostname"}], [{xmlelement, "value", [], [{xmlcdata, ?MYNAME}]}]} ]}]}; @@ -331,14 +332,15 @@ get_form(["config", "acls"], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "ACLs Configuration")}]}, + Lang, "Access Control List Configuration")}]}, %{xmlelement, "instructions", [], % [{xmlcdata, % translate:translate( % Lang, "")}]}, {xmlelement, "field", [{"type", "text-multi"}, {"label", - translate:translate(Lang, "ACLs")}, + translate:translate( + Lang, "Access control lists")}, {"var", "acls"}], lists:map(fun(S) -> {xmlelement, "value", [], [{xmlcdata, S}]} @@ -363,7 +365,7 @@ get_form(["config", "access"], Lang) -> {xmlelement, "field", [{"type", "text-multi"}, {"label", translate:translate( - Lang, "Access Rules")}, + Lang, "Access rules")}, {"var", "access"}], lists:map(fun(S) -> {xmlelement, "value", [], [{xmlcdata, S}]} @@ -721,13 +723,12 @@ search_running_node(SNode, [Node | Nodes]) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% process_sm_iq(From, To, - #iq{type = Type, xmlns = XMLNS, sub_el = SubEl} = IQ) -> + #iq{type = Type, xmlns = XMLNS, lang = Lang, sub_el = SubEl} = IQ) -> case acl:match_rule(configure, From) of deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; allow -> #jid{user = User} = To, - Lang = xml:get_tag_attr_s("xml:lang", SubEl), case Type of set -> XDataEl = find_xdata_el(SubEl), @@ -792,7 +793,7 @@ get_sm_form(User, [], Lang) -> [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Administration of " ++ User)}]}, + Lang, "Administration of ") ++ User}]}, %{xmlelement, "instructions", [], % [{xmlcdata, % translate:translate( diff --git a/src/mod_configure2.erl b/src/mod_configure2.erl index 6878c061f..78366400f 100644 --- a/src/mod_configure2.erl +++ b/src/mod_configure2.erl @@ -32,26 +32,26 @@ stop() -> gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_IQDATA). -process_local_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> +process_local_iq(From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case acl:match_rule(configure, From) of deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; allow -> - %Lang = xml:get_tag_attr_s("xml:lang", SubEl), case Type of set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}; %case xml:get_tag_attr_s("type", SubEl) of % "cancel" -> - % {iq, ID, result, XMLNS, - % [{xmlelement, "query", [{"xmlns", XMLNS}], []}]}; + % IQ#iq{type = result, + % sub_el = [{xmlelement, "query", + % [{"xmlns", XMLNS}], []}]}; % "submit" -> % XData = jlib:parse_xdata_submit(SubEl), % case XData of % invalid -> - % {iq, ID, error, XMLNS, - % [SubEl, ?ERR_BAD_REQUEST]}; + % IQ#iq{type = error, + % sub_el = [SubEl, ?ERR_BAD_REQUEST]}; % _ -> % Node = % string:tokens( @@ -59,19 +59,19 @@ process_local_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> % "/"), % case set_form(Node, Lang, XData) of % {result, Res} -> - % {iq, ID, result, XMLNS, - % [{xmlelement, "query", - % [{"xmlns", XMLNS}], - % Res - % }]}; + % IQ#iq{type = result, + % sub_el = [{xmlelement, "query", + % [{"xmlns", XMLNS}], + % Res + % }]}; % {error, Error} -> - % {iq, ID, error, XMLNS, - % [SubEl, Error]} + % IQ#iq{type = error, + % sub_el = [SubEl, Error]} % end % end; % _ -> - % {iq, ID, error, XMLNS, - % [SubEl, ?ERR_NOT_ALLOWED]} + % IQ#iq{type = error, + % sub_el = [SubEl, ?ERR_NOT_ALLOWED]} %end; get -> case process_get(SubEl) of diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 0dbf759e8..e4063f13a 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -73,8 +73,7 @@ unregister_extra_domain(Domain) -> catch ets:new(disco_extra_domains, [named_table, ordered_set, public]), ets:delete(disco_extra_domains, Domain). -process_local_iq_items(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> - Lang = xml:get_tag_attr_s("xml:lang", SubEl), +process_local_iq_items(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; @@ -231,10 +230,10 @@ get_local_items([], Server, Lang) -> get_local_items(["config"], Server, Lang) -> {result, - [?NODE("Host Name", "config/hostname"), - ?NODE("ACLs", "config/acls"), - ?NODE("Access Rules", "config/access"), - ?NODE("Remove Users", "config/remusers") + [?NODE("Host Name", "config/hostname"), + ?NODE("Access Control Lists", "config/acls"), + ?NODE("Access Rules", "config/access"), + ?NODE("Remove Users", "config/remusers") ]}; get_local_items(["config", _], Server, Lang) -> diff --git a/src/mod_irc/mod_irc.erl b/src/mod_irc/mod_irc.erl index cd8616b8e..1bb712575 100644 --- a/src/mod_irc/mod_irc.erl +++ b/src/mod_irc/mod_irc.erl @@ -58,6 +58,7 @@ loop(Host) -> do_route(Host, From, To, Packet) -> #jid{user = ChanServ, resource = Resource} = To, + {xmlelement, _Name, Attrs, _Els} = Packet, case ChanServ of "" -> case Resource of @@ -72,9 +73,18 @@ do_route(Host, From, To, Packet) -> ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); - #iq{type = Type, xmlns = ?NS_EJABBERD_CONFIG, - sub_el = SubEl} = IQ -> - ejabberd_config(From, To, IQ); + #iq{xmlns = ?NS_REGISTER} = IQ -> + process_register(From, To, IQ); + #iq{type = get, xmlns = ?NS_VCARD = XMLNS, + lang = Lang} = IQ -> + Res = IQ#iq{type = result, + sub_el = + [{xmlelement, "query", + [{"xmlns", XMLNS}], + iq_get_vcard(Lang)}]}, + ejabberd_router:route(To, + From, + jlib:iq_to_xml(Res)); #iq{} = IQ -> Err = jlib:make_error_reply( Packet, ?ERR_FEATURE_NOT_IMPLEMENTED), @@ -155,12 +165,22 @@ iq_disco() -> {xmlelement, "feature", [{"var", ?NS_MUC}], []}, {xmlelement, "feature", - [{"var", ?NS_EJABBERD_CONFIG}], []}]. + [{"var", ?NS_REGISTER}], []}, + {xmlelement, "feature", + [{"var", ?NS_VCARD}], []}]. +iq_get_vcard(Lang) -> + [{xmlelement, "FN", [], + [{xmlcdata, "ejabberd/mod_irc"}]}, + {xmlelement, "URL", [], + [{xmlcdata, + "http://ejabberd.jabberstudio.org/"}]}, + {xmlelement, "DESC", [], + [{xmlcdata, translate:translate(Lang, "ejabberd IRC module\n" + "Copyright (c) 2003-2004 Alexey Shchepin")}]}]. - -ejabberd_config(From, To, #iq{type = Type} = IQ) -> - case catch process_ejabberd_config(From, To, IQ) of +process_register(From, To, #iq{} = IQ) -> + case catch process_irc_register(From, To, IQ) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); ResIQ -> @@ -190,9 +210,9 @@ find_xdata_el1([{xmlelement, Name, Attrs, SubEls} | Els]) -> find_xdata_el1([_ | Els]) -> find_xdata_el1(Els). -process_ejabberd_config(From, To, - #iq{type = Type, xmlns = XMLNS, sub_el = SubEl} = IQ) -> - Lang = xml:get_tag_attr_s("xml:lang", SubEl), +process_irc_register(From, To, + #iq{type = Type, xmlns = XMLNS, + lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> XDataEl = find_xdata_el(SubEl), @@ -277,12 +297,15 @@ get_form(From, [], Lang) -> {xmlelement, "x", [{"xmlns", ?NS_XDATA}], [{xmlelement, "title", [], [{xmlcdata, - translate:translate(Lang, "mod_irc configuration for") ++ - " " ++ User ++ "@" ++ Server}]}, - %{xmlelement, "instructions", [], - % [{xmlcdata, - % translate:translate( - % Lang, "")}]}, + translate:translate( + Lang, + "Registration in mod_irc for ") ++ User ++ "@" ++ Server}]}, + {xmlelement, "instructions", [], + [{xmlcdata, + translate:translate( + Lang, + "Enter username and encodings you wish to use for " + "connecting to IRC servers")}]}, {xmlelement, "field", [{"type", "text-single"}, {"label", translate:translate( diff --git a/src/mod_muc/mod_muc.erl b/src/mod_muc/mod_muc.erl index cda26eb67..8fee7a291 100644 --- a/src/mod_muc/mod_muc.erl +++ b/src/mod_muc/mod_muc.erl @@ -100,15 +100,14 @@ do_route(Host, From, To, Packet) -> [Host, From, To, IQ]); #iq{type = get, xmlns = ?NS_REGISTER = XMLNS, + lang = Lang, sub_el = SubEl} = IQ -> - Lang = xml:get_tag_attr_s( - "xml:lang", SubEl), Res = IQ#iq{type = result, sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}], iq_get_register_info( - From, Lang)}]}, + From, Host, Lang)}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); @@ -132,9 +131,8 @@ do_route(Host, From, To, Packet) -> end; #iq{type = get, xmlns = ?NS_VCARD = XMLNS, + lang = Lang, sub_el = SubEl} = IQ -> - Lang = xml:get_tag_attr_s( - "xml:lang", SubEl), Res = IQ#iq{type = result, sub_el = [{xmlelement, "query", @@ -306,7 +304,7 @@ iq_disco_items(Host, From) -> {"var", Var}], [{xmlelement, "value", [], [{xmlcdata, Val}]}]}). -iq_get_register_info(From, Lang) -> +iq_get_register_info(From, Host, Lang) -> {LUser, LServer, _} = jlib:jid_tolower(From), LUS = {LUser, LServer}, {Nick, Registered} = case catch mnesia:dirty_read(muc_registered, LUS) of @@ -321,17 +319,17 @@ iq_get_register_info(From, Lang) -> [{xmlelement, "instructions", [], [{xmlcdata, translate:translate( - Lang, "You need a x:data capable client to register.")}]}, + Lang, "You need an x:data capable client to register nickname")}]}, {xmlelement, "x", [{"xmlns", ?NS_XDATA}], [{xmlelement, "title", [], [{xmlcdata, translate:translate( - Lang, "Nickname Registration")}]}, + Lang, "Nickname Registration at ") ++ Host}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate( - Lang, "Enter nickname you want to register.")}]}, + Lang, "Enter nickname you want to register")}]}, ?XFIELD("text-single", "Nickname", "nick", Nick)]}]. iq_set_register_info(From, XData) -> @@ -408,7 +406,7 @@ iq_get_vcard(Lang) -> "http://ejabberd.jabberstudio.org/"}]}, {xmlelement, "DESC", [], [{xmlcdata, translate:translate(Lang, "ejabberd MUC module\n" - "Copyright (c) 2003 Alexey Shchepin")}]}]. + "Copyright (c) 2003-2004 Alexey Shchepin")}]}]. broadcast_service_message(Msg) -> diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index 7f7b89574..312938287 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -173,7 +173,7 @@ normal_state({route, From, "", {next_state, normal_state, NewStateData2}; _ -> Err = jlib:make_error_reply( - Packet, ?ERR_NOT_ALLOWED), + Packet, ?ERR_FORBIDDEN), ejabberd_router:route( StateData#state.jid, From, Err), @@ -181,7 +181,7 @@ normal_state({route, From, "", end; true -> Err = jlib:make_error_reply( - Packet, ?ERR_NOT_ALLOWED), + Packet, ?ERR_FORBIDDEN), ejabberd_router:route( StateData#state.jid, From, Err), @@ -244,7 +244,7 @@ normal_state({route, From, "", ok; _ -> Err = jlib:make_error_reply( - Packet, ?ERR_NOT_ALLOWED), + Packet, ?ERR_NOT_ACCEPTABLE), ejabberd_router:route(StateData#state.jid, From, Err) end, {next_state, normal_state, StateData} @@ -254,20 +254,20 @@ normal_state({route, From, "", {xmlelement, "iq", Attrs, Els} = Packet}, StateData) -> case jlib:iq_query_info(Packet) of - #iq{type = Type, xmlns = XMLNS, sub_el = SubEl} = IQ when + #iq{type = Type, xmlns = XMLNS, lang = Lang, sub_el = SubEl} = IQ when (XMLNS == ?NS_MUC_ADMIN) or (XMLNS == ?NS_MUC_OWNER) or (XMLNS == ?NS_DISCO_INFO) or (XMLNS == ?NS_DISCO_ITEMS) -> Res1 = case XMLNS of ?NS_MUC_ADMIN -> - process_iq_admin(From, Type, SubEl, StateData); + process_iq_admin(From, Type, Lang, SubEl, StateData); ?NS_MUC_OWNER -> - process_iq_owner(From, Type, SubEl, StateData); + process_iq_owner(From, Type, Lang, SubEl, StateData); ?NS_DISCO_INFO -> - process_iq_disco_info(From, Type, StateData); + process_iq_disco_info(From, Type, Lang, StateData); ?NS_DISCO_ITEMS -> - process_iq_disco_items(From, Type, StateData) + process_iq_disco_items(From, Type, Lang, StateData) end, {IQRes, NewStateData} = case Res1 of @@ -836,9 +836,9 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) -> true -> ok; _ -> - send_subject(From, StateData) + Lang = xml:get_attr_s("xml:lang", Attrs), + send_subject(From, Lang, StateData) end, - send_join_messages_end(From, StateData), NewState; _ -> Err = jlib:make_error_reply( @@ -1364,7 +1364,7 @@ send_history(JID, Shift, StateData) -> end, false, lists:nthtail(Shift, lqueue_to_list(StateData#state.history))). -send_subject(JID, StateData) -> +send_subject(JID, Lang, StateData) -> case StateData#state.subject_author of "" -> ok; @@ -1374,7 +1374,10 @@ send_subject(JID, StateData) -> [{xmlelement, "subject", [], [{xmlcdata, Subject}]}, {xmlelement, "body", [], [{xmlcdata, - Nick ++ " has set the topic to: " ++ Subject}]}]}, + Nick ++ + translate:translate(Lang, + " has set the subject to: ") ++ + Subject}]}]}, ejabberd_router:route( StateData#state.jid, JID, @@ -1389,15 +1392,6 @@ check_subject(Packet) -> xml:get_tag_cdata(SubjEl) end. -send_join_messages_end(JID, StateData) -> - Packet = {xmlelement, "message", [{"type", "groupchat"}], - [{xmlelement, "body", [], - [{xmlcdata, "-"}]}]}, - ejabberd_router:route( - StateData#state.jid, - JID, - Packet). - can_change_subject(Role, StateData) -> case (StateData#state.config)#config.allow_change_subj of true -> @@ -1409,11 +1403,11 @@ can_change_subject(Role, StateData) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Admin stuff -process_iq_admin(From, set, SubEl, StateData) -> +process_iq_admin(From, set, Lang, SubEl, StateData) -> {xmlelement, _, _, Items} = SubEl, process_admin_items_set(From, Items, StateData); -process_iq_admin(From, get, SubEl, StateData) -> +process_iq_admin(From, get, Lang, SubEl, StateData) -> case xml:get_subtag(SubEl, "item") of false -> {error, ?ERR_BAD_REQUEST}; @@ -1838,12 +1832,11 @@ send_kickban_presence1(UJID, Reason, Code, StateData) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Owner stuff -process_iq_owner(From, set, SubEl, StateData) -> +process_iq_owner(From, set, Lang, SubEl, StateData) -> FAffiliation = get_affiliation(From, StateData), case FAffiliation of owner -> {xmlelement, Name, Attrs, Els} = SubEl, - Lang = xml:get_tag_attr_s("xml:lang", SubEl), case xml:remove_cdata(Els) of [{xmlelement, "x", Attrs1, Els1} = XEl] -> case {xml:get_tag_attr_s("xmlns", XEl), @@ -1864,12 +1857,11 @@ process_iq_owner(From, set, SubEl, StateData) -> {error, ?ERR_FORBIDDEN} end; -process_iq_owner(From, get, SubEl, StateData) -> +process_iq_owner(From, get, Lang, SubEl, StateData) -> FAffiliation = get_affiliation(From, StateData), case FAffiliation of owner -> {xmlelement, Name, Attrs, Els} = SubEl, - Lang = xml:get_tag_attr_s("xml:lang", SubEl), case xml:remove_cdata(Els) of [] -> get_config(Lang, StateData); @@ -1919,7 +1911,10 @@ process_iq_owner(From, get, SubEl, StateData) -> get_config(Lang, StateData) -> Config = StateData#state.config, Res = - [?STRINGXFIELD("Room title", + [{xmlelement, "title", [], + [{xmlcdata, translate:translate(Lang, "Configuration for ") ++ + jlib:jid_to_string(StateData#state.jid)}]}, + ?STRINGXFIELD("Room title", "title", Config#config.title), ?BOOLXFIELD("Allow users to change subject?", @@ -1968,7 +1963,11 @@ get_config(Lang, StateData) -> "logging", Config#config.logging) ], - {result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}], Res}], StateData}. + {result, [{xmlelement, "instructions", [], + [{xmlcdata, + translate:translate( + Lang, "You need an x:data capable client to configure room")}]}, + {xmlelement, "x", [{"xmlns", ?NS_XDATA}], Res}], StateData}. @@ -2141,10 +2140,10 @@ destroy_room(DEls, StateData) -> ?FEATURE(Fiffalse) end). -process_iq_disco_info(From, set, StateData) -> +process_iq_disco_info(From, set, Lang, StateData) -> {error, ?ERR_NOT_ALLOWED}; -process_iq_disco_info(From, get, StateData) -> +process_iq_disco_info(From, get, Lang, StateData) -> Config = StateData#state.config, {result, [{xmlelement, "identity", [{"category", "conference"}, @@ -2167,10 +2166,10 @@ process_iq_disco_info(From, get, StateData) -> ], StateData}. -process_iq_disco_items(From, set, StateData) -> +process_iq_disco_items(From, set, Lang, StateData) -> {error, ?ERR_NOT_ALLOWED}; -process_iq_disco_items(From, get, StateData) -> +process_iq_disco_items(From, get, Lang, StateData) -> FAffiliation = get_affiliation(From, StateData), FRole = get_role(From, StateData), case ((StateData#state.config)#config.public_list == true) orelse diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index 75c6c10da..c56edf948 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -120,24 +120,24 @@ do_route(Host, From, To, Packet) -> Packet, Error) end, ejabberd_router:route(To, From, Res); - %{iq, ID, get, ?NS_REGISTER = XMLNS, SubEl} -> - % Lang = xml:get_tag_attr_s( - % "xml:lang", SubEl), - % Res = {iq, ID, result, XMLNS, - % [{xmlelement, "query", - % [{"xmlns", XMLNS}], - % iq_get_register_info( - % From, Lang)}]}, + %#iq{type = get, xmlns = ?NS_REGISTER = XMLNS, + % lang = Lang, sub_el = SubEl} = IQ -> + % Res = IQ#iq{type = result, + % sub_el = [{xmlelement, "query", + % [{"xmlns", XMLNS}], + % iq_get_register_info( + % From, Lang)}]}, % ejabberd_router:route(To, % From, % jlib:iq_to_xml(Res)); - %{iq, ID, set, ?NS_REGISTER = XMLNS, SubEl} -> + %#iq{type = set, xmlns = ?NS_REGISTER = XMLNS, + % sub_el = SubEl} = IQ -> % case process_iq_register_set(From, SubEl) of % {result, IQRes} -> - % Res = {iq, ID, result, XMLNS, - % [{xmlelement, "query", - % [{"xmlns", XMLNS}], - % IQRes}]}, + % Res = IQ#iq{type = result, + % sub_el = [{xmlelement, "query", + % [{"xmlns", XMLNS}], + % IQRes}]}, % ejabberd_router:route( % To, From, jlib:iq_to_xml(Res)); % {error, Error} -> @@ -160,9 +160,7 @@ do_route(Host, From, To, Packet) -> end, ejabberd_router:route(To, From, Res); #iq{type = get, xmlns = ?NS_VCARD = XMLNS, - sub_el = SubEl} = IQ -> - Lang = xml:get_tag_attr_s( - "xml:lang", SubEl), + lang = Lang, sub_el = SubEl} = IQ -> Res = IQ#iq{type = result, sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}], @@ -389,8 +387,10 @@ iq_get_vcard(Lang) -> [{xmlcdata, "http://ejabberd.jabberstudio.org/"}]}, {xmlelement, "DESC", [], - [{xmlcdata, "ejabberd pub/sub module\n" - "Copyright (c) 2003 Alexey Shchepin"}]}]. + [{xmlcdata, translate:translate( + Lang, + "ejabberd pub/sub module\n" + "Copyright (c) 2003-2004 Alexey Shchepin")}]}]. iq_pubsub(Host, From, Type, SubEl) -> diff --git a/src/mod_register.erl b/src/mod_register.erl index a84c144aa..0727c354e 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -28,7 +28,7 @@ start(Opts) -> init() -> ok. -process_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> +process_iq(From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> UTag = xml:get_subtag(SubEl, "username"), @@ -100,7 +100,6 @@ process_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> sub_el = [SubEl, ?ERR_BAD_REQUEST]} end; get -> - Lang = xml:get_tag_attr_s("xml:lang", SubEl), IQ#iq{type = result, sub_el = [{xmlelement, "query", @@ -110,7 +109,7 @@ process_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> translate:translate( Lang, "Choose a username and password " - "to register with this server.")}]}, + "to register with this server")}]}, {xmlelement, "username", [], []}, {xmlelement, "password", [], []}]}]} end. diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 184d31cf0..c58d97e20 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -86,7 +86,7 @@ loop() -> end. -process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> +process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; @@ -100,8 +100,11 @@ process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> [{xmlcdata, "http://ejabberd.jabberstudio.org/"}]}, {xmlelement, "DESC", [], - [{xmlcdata, "Erlang Jabber Server\n" - "Copyright (c) 2002-2004 Alexey Shchepin"}]}, + [{xmlcdata, + translate:translate( + Lang, + "Erlang Jabber Server\n" + "Copyright (c) 2002-2004 Alexey Shchepin")}]}, {xmlelement, "BDAY", [], [{xmlcdata, "2002-11-16"}]} ]}]} @@ -202,12 +205,13 @@ set_vcard(User, VCARD) -> {"var", Var}], []}). --define(FORM, +-define(FORM(JID), [{xmlelement, "instructions", [], - [{xmlcdata, translate:translate(Lang, "You need a x:data capable client to search")}]}, + [{xmlcdata, translate:translate(Lang, "You need an x:data capable client to search")}]}, {xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}], [{xmlelement, "title", [], - [{xmlcdata, translate:translate(Lang, "Users Search")}]}, + [{xmlcdata, translate:translate(Lang, "Search users in ") ++ + jlib:jid_to_string(JID)}]}, {xmlelement, "instructions", [], [{xmlcdata, translate:translate(Lang, "Fill in fields to search " "for any matching Jabber User")}]}, @@ -237,8 +241,7 @@ do_route(From, To, Packet) -> true -> IQ = jlib:iq_query_info(Packet), case IQ of - #iq{type = Type, xmlns = ?NS_SEARCH, sub_el = SubEl} -> - Lang = xml:get_tag_attr_s("xml:lang", SubEl), + #iq{type = Type, xmlns = ?NS_SEARCH, lang = Lang, sub_el = SubEl} -> case Type of set -> XDataEl = find_xdata_el(SubEl), @@ -267,7 +270,7 @@ do_route(From, To, Packet) -> [{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "result"}], - search_result(Lang, XData) + search_result(Lang, To, XData) }]}]}, ejabberd_router:route( To, From, jlib:iq_to_xml(ResIQ)) @@ -278,7 +281,7 @@ do_route(From, To, Packet) -> sub_el = [{xmlelement, "query", [{"xmlns", ?NS_SEARCH}], - ?FORM + ?FORM(To) }]}, ejabberd_router:route(To, From, @@ -303,7 +306,9 @@ do_route(From, To, Packet) -> "vCard User Search"}], []}, {xmlelement, "feature", - [{"var", ?NS_SEARCH}], []} + [{"var", ?NS_SEARCH}], []}, + {xmlelement, "feature", + [{"var", ?NS_VCARD}], []} ] }]}, ejabberd_router:route(To, @@ -327,6 +332,16 @@ do_route(From, To, Packet) -> From, jlib:iq_to_xml(ResIQ)) end; + #iq{type = get, xmlns = ?NS_VCARD, lang = Lang} -> + ResIQ = + IQ#iq{type = result, + sub_el = [{xmlelement, + "query", + [{"xmlns", ?NS_VCARD}], + iq_get_vcard(Lang)}]}, + ejabberd_router:route(To, + From, + jlib:iq_to_xml(ResIQ)); _ -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), @@ -334,6 +349,16 @@ do_route(From, To, Packet) -> end end. +iq_get_vcard(Lang) -> + [{xmlelement, "FN", [], + [{xmlcdata, "ejabberd/mod_vcard"}]}, + {xmlelement, "URL", [], + [{xmlcdata, + "http://ejabberd.jabberstudio.org/"}]}, + {xmlelement, "DESC", [], + [{xmlcdata, translate:translate(Lang, "ejabberd vCard module\n" + "Copyright (c) 2003-2004 Alexey Shchepin")}]}]. + find_xdata_el({xmlelement, _Name, _Attrs, SubEls}) -> find_xdata_el1(SubEls). @@ -353,9 +378,10 @@ find_xdata_el1([_ | Els]) -> {xmlelement, "field", [{"label", translate:translate(Lang, Label)}, {"var", Var}], []}). -search_result(Lang, Data) -> +search_result(Lang, JID, Data) -> [{xmlelement, "title", [], - [{xmlcdata, translate:translate(Lang, "Users Search Results")}]}, + [{xmlcdata, translate:translate(Lang, "Results of search in ") ++ + jlib:jid_to_string(JID)}]}, {xmlelement, "reported", [], [?LFIELD("JID", "jid"), ?LFIELD("Full Name", "fn"), diff --git a/src/msgs/ru.msg b/src/msgs/ru.msg index dec81d201..2bd4749ff 100644 --- a/src/msgs/ru.msg +++ b/src/msgs/ru.msg @@ -1,24 +1,41 @@ % $Id$ % mod_configure.erl -{"DB Tables Configuration", "Конфигурация таблиц БД"}. +{"DB Tables Configuration at ", "Конфигурация таблиц БД на "}. {"Choose storage type of tables", "Выберите тип хранения таблиц"}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. -{"", ""}. +{"RAM copy", "ОЗУ"}. +{"RAM and disc copy", "ОЗУ и диск"}. +{"Disc only copy", "только диск"}. +{"Remote copy", "не хранится локально"}. +{"Stop Modules at ", "Остановка модулей на "}. +{"Choose modules to stop", "Выберите модули, которые следует остановить"}. +{"Start Modules at ", "Запуск модулей на "}. +{"Enter list of {Module, [Options]}", "Введите список вида {Module, [Options]}"}. +{"List of modules to start", "Список запускаемых модулей"}. +{"Backup to File at ", "Резервное копирование в файл на "}. +{"Enter path to backup file", "Введите путь к резервному файлу"}. +{"Path to File", "Путь к файлу"}. +{"Restore Backup from File at ", "Восстановление из резервной копии на "}. +{"Dump Backup to Text File at ", "Копирование в текстовый файл на "}. +{"Enter path to text file", "Введите путь к текстовому файлу"}. +{"Import User from File at ", "Импорт пользователя из файла на "}. +{"Enter path to jabberd1.4 spool file", "Введите путь к файлу из спула jabberd1.4"}. +{"Import Users from Dir at ", "Импорт пользователей из директории на "}. +{"Enter path to jabberd1.4 spool dir", "Введите путь к директории спула jabberd1.4"}. +{"Path to Dir", "Путь к директории"}. +{"Hostname Configuration", "Конфигурация имени хоста"}. +{"Choose host name", "Выберите имя хоста"}. +{"Host name", "Имя хоста"}. +{"Access Control List Configuration", "Конфигурация списков управления доступом"}. +{"Access control lists", "Списки управления доступом"}. +{"Access Configuration", "Конфигурация доступа"}. +{"Access rules", "Правила доступа"}. +{"Remove Users", "Удаление пользователей"}. +{"Choose users to remove", "Выберите пользователей, которых следует удалить"}. +{"Administration of ", "Администрирование "}. +{"Action on user", "Действие над пользователем"}. +{"Edit Properties", "Изменить параметры"}. +{"Remove User", "Удалить пользователя"}. % mod_disco.erl {"Configuration", "Конфигурация"}. @@ -30,25 +47,36 @@ {"Running Nodes", "Работающие узлы"}. {"Stopped Nodes", "Остановленные узлы"}. {"Host Name", "Имя хоста"}. -{"ACLs", "ACLs"}. +{"Access Control Lists", "Списки управления доступом"}. {"Access Rules", "Правила доступа"}. {"Remove Users", "Удаление пользователей"}. {"DB", "БД"}. {"Modules", "Модули"}. {"Start Modules", "Запуск модулей"}. {"Stop Modules", "Остановка модулей"}. +{"Backup Management", "Управление резервным копированием"}. +{"Import users from jabberd1.4 spool files", "Импорт пользователей из спула jabberd1.4"}. +{"Backup", "Резервное копирование"}. +{"Restore", "Восстановление из резервной копии"}. +{"Dump to Text File", "Копирование в текстовый файл"}. +{"Import File", "Импорт из файла"}. +{"Import Directory", "Импорт из директории"}. % mod_register.erl -{"Choose a username and password to register with this server.", - "Выберите идентификатор пользователя и пароль для регистрации на этом сервере."}. +{"Choose a username and password to register with this server", + "Выберите имя пользователя и пароль для регистрации на этом сервере"}. % mod_vcard.erl -{"You need a x:data capable client to search", - "Чтобы воспользоваться поиском, Вам нужен x:data-совместимый клиент"}. -{"Users Search", "Поиск пользователей"}. +{"Erlang Jabber Server\nCopyright (c) 2002-2004 Alexey Shchepin", + "Erlang Jabber Server\nCopyright (c) 2002-2004 Алексей Щепин"}. +{"ejabberd vCard module\nCopyright (c) 2003-2004 Alexey Shchepin", + "ejabberd vCard модуль\nCopyright (c) 2003-2004 Алексей Щепин"}. +{"You need an x:data capable client to search", + "Чтобы воспользоваться поиском, требуется x:data-совместимый клиент"}. +{"Search users in ", "Поиск пользователей в "}. {"Fill in fields to search for any matching Jabber User", "Заполните поля для поиска пользователя Jabber"}. -{"Users Search Results", "Результат поиска пользователей"}. +{"Results of search in ", "Результаты поиска в "}. {"User", "Пользователь"}. {"Full Name", "Полное имя"}. @@ -63,13 +91,23 @@ {"Organization Name", "Название организации"}. {"Organization Unit", "Отдел организации"}. +% mod_pubsub/mod_pubsub.erl +{"ejabberd pub/sub module\nCopyright (c) 2003-2004 Alexey Shchepin", + "ejabberd pub/sub модуль\nCopyright (c) 2003-2004 Алексей Щепин"}. + % mod_muc/mod_muc.erl -{"Nickname Registration", "Регистрация псевдонима"}. -{"Enter nickname you want to register.", "Введите псевдоним, который вы хотели бы зарегистрировать"}. -{"ejabberd MUC module\nCopyright (c) 2003 Alexey Shchepin", - "ejabberd MUC модуль\nCopyright (c) 2003 Алексей Щепин"}. +{"You need an x:data capable client to register nickname", + "Чтобы зарегистрировать псевдоним, требуется x:data-совместимый клиент"}. +{"Nickname Registration at ", "Регистрация псевдонима на "}. +{"Enter nickname you want to register", "Введите псевдоним, который Вы хотели бы зарегистрировать"}. +{"ejabberd MUC module\nCopyright (c) 2003-2004 Alexey Shchepin", + "ejabberd MUC модуль\nCopyright (c) 2003-2004 Алексей Щепин"}. % mod_muc/mod_muc_room.erl +{" has set the subject to: ", " установил(а) тему: "}. +{"You need an x:data capable client to configure room", + "Чтобы сконфигурировать комнату, требуется x:data-совместимый клиент"}. +{"Configuration for ", "Конфигурация "}. {"Room title", "Название комнаты"}. {"Allow users to change subject?", "Разрешить пользователям изменять тему?"}. {"Allow users to query other users?", @@ -87,13 +125,18 @@ {"Allow users to send invites?", "Разрешить пользователям посылать приглашения?"}. {"Make room password protected?", "Сделать комнату защищённой паролем?"}. +{"Password", "Пароль"}. {"Make room anonymous?", "Сделать комнату анонимной?"}. {"Enable logging?", "Включить журналирование?"}. % mod_irc/mod_irc.erl +{"ejabberd IRC module\nCopyright (c) 2003-2004 Alexey Shchepin", + "ejabberd IRC модуль\nCopyright (c) 2003-2004 Алексей Щепин"}. {"You need an x:data capable client to configure mod_irc settings", - "Чтобы настроить параметры mod_irc, нужен x:data-совместимый клиент"}. -{"mod_irc configuration for", "Конфигурация mod_irc для"}. + "Чтобы настроить параметры mod_irc, требуется x:data-совместимый клиент"}. +{"Registration in mod_irc for ", "Регистрация в mod_irc для "}. +{"Enter username and encodings you wish to use for connecting to IRC servers", + "Введите имя пользователя и кодировки, которые будут использоваться при подключении к IRC-серверам"}. {"IRC Username", "Имя пользователя IRC"}. {"If you want to specify different encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\"}'. By default this service use \"~s\" encoding.", "Чтобы указать различные кодировки для разных серверов IRC, заполните список значениями в формате '{\"irc server\", \"encoding\"}'. По умолчанию эта служба использует кодировку \"~s\"."}. {"Example: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", \"iso8859-1\"}].", "Примеры: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", \"iso8859-1\"}]."}.