ejabberd-16.01/0000755000232200023220000000000012645403255013633 5ustar debalancedebalanceejabberd-16.01/rebar.config0000644000232200023220000001276112645157216016127 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov %%% @copyright (C) 2013, Evgeniy Khramtsov %%% @doc %%% %%% @end %%% 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"}}}}, {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, {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"}}}}]}. {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'}}, {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"]}]}. ejabberd-16.01/mix.lock0000644000232200023220000000051312645157216015304 0ustar debalancedebalance%{"bbmustache": {:hex, :bbmustache, "1.0.4"}, "erlware_commons": {:hex, :erlware_commons, "0.18.0"}, "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"}} ejabberd-16.01/ejabberd.service.template0000644000232200023220000000052512645157216020572 0ustar debalancedebalance[Unit] Description=XMPP Server After=network.target [Service] User=ejabberd Group=ejabberd LimitNOFILE=16000 RestartSec=5 ExecStart=/bin/sh @ctlscriptpath@/ejabberdctl start ExecStop=@ctlscriptpath@/ejabberdctl stop ExecReload=@ctlscriptpath@/ejabberdctl reload_config Type=oneshot RemainAfterExit=yes [Install] WantedBy=multi-user.target ejabberd-16.01/tools/0000755000232200023220000000000012645157216014776 5ustar debalancedebalanceejabberd-16.01/tools/jhbtest.pl0000755000232200023220000002755212645157216017014 0ustar debalancedebalance#!/usr/bin/perl -w use strict; # har har use constant ERR => 0; use constant WARN => 1; use constant INFO => 2; use constant DEBUG => 3; use constant RID => 31974; ### ### ### conf ### ### ### my $BASE_ADDRESS = "http://localhost:5280/http-bind/"; my $JABBER_SERVER = "localhost"; my $RID = RID; my $WAIT = 60; my $USER = "tester"; my $UPW = "mysecret"; my $DEBUG = INFO; ### ### ### END conf ### ### ### # create an agent we can use for our requests use LWP::UserAgent; my $ua = new LWP::UserAgent(); # create a tree parser to parse response content use XML::Parser; my $p = new XML::Parser(Style => 'Tree'); ### ### ### subs ### ### ### sub doSend() { my $content = shift; # create a request my $req = new HTTP::Request(POST => $BASE_ADDRESS); $req->content_type('text/xml; charset=utf-8'); $req->content($content); debug(DEBUG,"<< Request\n".$req->as_string."<< END Request"); # send request my $res = $ua->request($req); debug(DEBUG,">> Response\n" . $res->as_string .">> END Response"); return $res; } # getChildEls # used to strip enclosing body element # PARAMS: @tree - tree style array from XML::Parser # RETURN: @children - child elements of top level element sub getChildEls { my $t = $_[0]; shift @{$t->[1]}; return @{$t->[1]}; } sub debug { my $lvl = shift; my $msg = shift; return if ($DEBUG < $lvl); my $prefix = "["; $prefix .= "ERROR" if ($lvl == ERR); $prefix .= "WARNING" if ($lvl == WARN); $prefix .= "INFO" if ($lvl == INFO); $prefix .= "DEBUG" if ($lvl == DEBUG); $prefix .= "] "; $msg =~ s/\n/\n$prefix/g; print STDERR $prefix . $msg . "\n"; } ### ### ### main ### ### ### $| = 1; # set streaming output # no body print "Sending some 'foo': "; my $res = &doSend("foo"); if ($res->code == 400) { print "OK.\n"; } else { print "Failed!\n"; print $res->as_string, "\n"; } # no body print "Sending some '': "; $res = &doSend(""); if ($res->code == 400) { print "OK.\n"; } else { print "Failed!\n"; print $res->as_string, "\n"; } # empty body print "Sending empty body: "; $res = &doSend(""); if ($res->code == 400) { print "OK.\n"; } else { print "Failed!\n"; print $res->as_string, "\n"; } # fake a sid print "Sending wrong sid: "; $res = &doSend(""); if ($res->code == 404) { print "OK.\n"; } else { print "Failed!\n"; print $res->as_string, "\n"; } # forget to send 'to' print "Missing 'to' attribute at session creation request: "; $res = &doSend(""); if ($res->is_success && $res->content =~ /content =~/as_string, "\n"; } # sending empty 'to' attribute print "Empty 'to' attribute at session creation request: "; $res = &doSend(""); if ($res->is_success && $res->content =~ /content =~/as_string, "\n"; } # forget to send a rid print "Missing 'rid' attribute at session creation request: "; $res = &doSend(""); if ($res->code == 404) { print "OK.\n"; } else { print "Failed!\n"; print $res->as_string, "\n"; } # trying to connect to non-existent domain print "Connecting to non-existent domain: "; $res = &doSend(""); if ($res->is_success && $res->content =~ /content =~/as_string, "\n"; } # trying to connect to non-existent jabber server print "Connecting to non-existent jabber server: "; $res = &doSend(""); if ($res->is_success && $res->content =~ /content =~/content =~/as_string, "\n"; } # connection to foreign server #print "Connecting to foreign jabber server: "; #$res = &doSend(""); #if ($res->is_success && $res->content =~ /content =~/as_string, "\n"; #} my %sess; sub getSess { $sess{rid} = RID; # a rid to start $res = &doSend(""); if ($res->is_success) { my $t = $p->parse($res->content); %sess = %{$t->[1]->[0]}; $sess{rid} = RID; # a rid to start if (defined($sess{sid}) && $sess{sid} ne "" && defined($sess{wait}) && $sess{wait} ne '' && $sess{wait} <= $WAIT) { debug(INFO,"sid: $sess{sid}"); debug(INFO, "authid: $sess{authid}") if (defined($sess{authid})); debug(INFO, "wait: $sess{wait}"); debug(INFO, "inactivity: $sess{inactivity}") if (defined($sess{inactivity})); debug(INFO, "polling: $sess{polling}") if (defined($sess{polling})); debug(INFO, "requests: $sess{requests}") if (defined($sess{requests})); debug(INFO, "accept: $sess{accept}") if (defined($sess{accept})); debug(INFO, "charsets: $sess{charsets}") if (defined($sess{charsets})); debug (WARN, "authid missing") unless (defined($sess{authid}) && $sess{authid} ne ''); debug (WARN, "server indicates polling mode") if (defined($sess{requests}) && $sess{requests} == 1); return 1; } } debug(ERR, "sid missing") unless (defined($sess{sid}) && $sess{sid} ne ""); debug(ERR, "wait missing") unless (defined($sess{wait}) && $sess{wait} ne ''); debug(ERR, "wait bigger then requested") unless (defined($sess{wait}) && $sess{wait} ne '' && $sess{wait} <= $WAIT); debug(DEBUG, $res->as_string); return 0; } # try to get a real sid print "Create a new session: "; if (&getSess()) { print "OK.\n"; } else { debug(ERR, "Aborting."); exit(1); } # checking wait attribute print "Creating another session with smaller 'wait' then before: "; $WAIT = $sess{wait} - 1; if (&getSess()) { print "OK.\n"; } else { print "FAILED!\n"; debug(ERR, "Aborting."); exit(1); } sub doAuth { # query auth $sess{rid}++; $res = &doSend("$USER"); my @els = (&getChildEls($p->parse($res->content))); unless ($els[0] eq 'iq' && $els[1]->[0]->{'type'} eq 'result') { debug(ERR, $res->content); return 0; } # send auth $sess{rid}++; $res = &doSend("$USERtest$UPW"); @els = (&getChildEls($p->parse($res->content))); unless ($els[0] eq 'iq' && $els[1]->[0]->{'type'} eq 'result') { debug(ERR, $res->content); return 0; } return 1; } print "Authenticating: "; if (&doAuth()) { print "OK.\n"; } else { print "FAILED!\n"; debug(ERR, "Aborting."); exit(1); } sub doPoll { $sess{rid}++; return &doSend(""); } print "Polling with wrong 'rid': "; $sess{rid}--; $res = &doPoll(); if ($res->code != 404) { print "FAILED!\n"; debug(ERR, "Aborting."); # exit(1); } print "OK.\n"; print "Checking if session terminated: "; $res = &doPoll(); if ($res->code != 404) { print "FAILED!\n"; debug(ERR, "Aborting."); # exit(1); } print "OK.\n"; print "Create a new session: "; if (&getSess()) { print "OK.\n"; } else { debug(ERR, "Aborting."); exit(1); } print "Authenticating: "; if (&doAuth()) { print "OK.\n"; } else { print "FAILED!\n"; debug(ERR, "Aborting."); # exit(1); } print "Polling too frequently: "; $res = &doPoll(); if ($res->code != 200) { print "First poll failed unexpectedly!\n"; debug(ERR, "Aborting."); #exit(1); } $res = &doPoll(); if ($res->code != 403) { print "FAILED!\n"; debug(ERR, "Aborting."); #exit(1); } print "OK.\n"; print "Checking if session terminated: "; $res = &doPoll(); if ($res->code != 404) { print "FAILED!\n"; debug(ERR, "Aborting."); #exit(1); } print "OK.\n"; print "Create a new session: "; if (&getSess()) { print "OK.\n"; } else { debug(ERR, "Aborting."); exit(1); } print "Authenticating: "; if (&doAuth()) { print "OK.\n"; } else { print "FAILED!\n"; debug(ERR, "Aborting."); exit(1); } print "Test if proper polling is allowed: "; $res = &doPoll(); if ($res->code != 200) { print "FAILED!\n"; debug(ERR, "Aborting."); exit(1); } sleep $sess{polling}; $res = &doPoll(); if ($res->code != 200) { print "FAILED!\n"; debug(ERR, "Aborting."); exit(1); } print "OK.\n"; print "Waiting for session to timeout: "; my $STEP=10; for (my $i=0; $i<$sess{inactivity}; $i+=$STEP) { print "."; sleep $STEP; } sleep 1; # take another nap $res = &doPoll(); if ($res->code != 404) { print "FAILED!\n"; debug(ERR, "Aborting."); exit(1); } print "OK.\n"; print "Create a new session: "; if (&getSess()) { print "OK.\n"; } else { debug(ERR, "Aborting."); exit(1); } print "Authenticating: "; if (&doAuth()) { print "OK.\n"; } else { print "FAILED!\n"; debug(ERR, "Aborting."); exit(1); } # [TODO] # Check for # * KEY Sequence Algorithm Compliance # * Too Many Simultaneous Connections (probably hard to achieve for polling mode) # * request custom content-type/-encoding # get roster print "getting roster\n"; $sess{rid}++; $res = &doSend(""); debug(INFO, $res->content); # send presence print "sending presence\n"; $sess{rid}++; $res = &doSend(""); debug(INFO, $res->content); # sending bullshit print "sending bullshit\n"; $sess{rid}++; $res = &doSend("sending bullshit"); debug(INFO, $res->content); # send presence print "sending xa presence\n"; $sess{rid}++; $res = &doSend("xa"); debug(INFO, $res->content); # disconnect sleep 3; print "logout\n"; $sess{rid}++; $res = &doSend(""); debug(INFO, $res->content); print "Checking if session terminated: "; $res = &doPoll(); if ($res->code != 404) { print "FAILED!\n"; debug(ERR, "Aborting."); exit(1); } print "OK.\n"; ejabberd-16.01/tools/xmpp_codec.spec0000644000232200023220000032057712645157216020011 0ustar debalancedebalance-xml(last, #elem{name = <<"query">>, xmlns = <<"jabber:iq:last">>, result = {last, '$seconds', '$text'}, attrs = [#attr{name = <<"seconds">>, enc = {enc_int, []}, dec = {dec_int, [0, infinity]}}], cdata = #cdata{label = '$text'}}). -xml(version_name, #elem{name = <<"name">>, xmlns = <<"jabber:iq:version">>, result = '$cdata', cdata = #cdata{label = '$cdata', required = true}}). -xml(version_ver, #elem{name = <<"version">>, xmlns = <<"jabber:iq:version">>, result = '$cdata', cdata = #cdata{label = '$cdata', required = true}}). -xml(version_os, #elem{name = <<"os">>, xmlns = <<"jabber:iq:version">>, result = '$cdata', cdata = #cdata{label = '$cdata', required = true}}). -xml(version, #elem{name = <<"query">>, xmlns = <<"jabber:iq:version">>, result = {version, '$name', '$ver', '$os'}, refs = [#ref{name = version_name, label = '$name', min = 0, max = 1}, #ref{name = version_ver, label = '$ver', min = 0, max = 1}, #ref{name = version_os, label = '$os', min = 0, max = 1}]}). -xml(roster_group, #elem{name = <<"group">>, xmlns = <<"jabber:iq:roster">>, result = '$cdata', cdata = #cdata{required = true, label = '$cdata'}}). -xml(roster_item, #elem{name = <<"item">>, xmlns = <<"jabber:iq:roster">>, result = {roster_item, '$jid', '$name', '$groups', '$subscription', '$ask'}, attrs = [#attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"name">>}, #attr{name = <<"subscription">>, default = none, enc = {enc_enum, []}, dec = {dec_enum, [[none,to,from,both,remove]]}}, #attr{name = <<"ask">>, enc = {enc_enum, []}, dec = {dec_enum, [[subscribe]]}}], refs = [#ref{name = roster_group, label = '$groups'}]}). -xml(roster, #elem{name = <<"query">>, xmlns = <<"jabber:iq:roster">>, result = {roster, '$items', '$ver'}, attrs = [#attr{name = <<"ver">>}], refs = [#ref{name = roster_item, label = '$items'}]}). -xml(privacy_message, #elem{name = <<"message">>, xmlns = <<"jabber:iq:privacy">>, result = message}). -xml(privacy_iq, #elem{name = <<"iq">>, xmlns = <<"jabber:iq:privacy">>, result = iq}). -xml(privacy_presence_in, #elem{name = <<"presence-in">>, xmlns = <<"jabber:iq:privacy">>, result = 'presence-in'}). -xml(privacy_presence_out, #elem{name = <<"presence-out">>, xmlns = <<"jabber:iq:privacy">>, result = 'presence-out'}). -xml(privacy_item, #elem{name = <<"item">>, xmlns = <<"jabber:iq:privacy">>, result = {privacy_item, '$order', '$action', '$type', '$value', '$kinds'}, attrs = [#attr{name = <<"action">>, required = true, dec = {dec_enum, [[allow, deny]]}, enc = {enc_enum, []}}, #attr{name = <<"order">>, required = true, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"type">>, dec = {dec_enum, [[group, jid, subscription]]}, enc = {enc_enum, []}}, #attr{name = <<"value">>}], refs = [#ref{name = privacy_message, label = '$kinds'}, #ref{name = privacy_iq, label = '$kinds'}, #ref{name = privacy_presence_in, label = '$kinds'}, #ref{name = privacy_presence_out, label = '$kinds'}]}). -xml(privacy_list, #elem{name = <<"list">>, xmlns = <<"jabber:iq:privacy">>, result = {privacy_list, '$name', '$items'}, attrs = [#attr{name = <<"name">>, required = true}], refs = [#ref{name = privacy_item, label = '$items'}]}). -xml(privacy_default_list, #elem{name = <<"default">>, xmlns = <<"jabber:iq:privacy">>, result = '$name', attrs = [#attr{name = <<"name">>, default = none}]}). -xml(privacy_active_list, #elem{name = <<"active">>, xmlns = <<"jabber:iq:privacy">>, result = '$name', attrs = [#attr{name = <<"name">>, default = none}]}). -xml(privacy, #elem{name = <<"query">>, xmlns = <<"jabber:iq:privacy">>, result = {privacy, '$lists', '$default', '$active'}, refs = [#ref{name = privacy_list, label = '$lists'}, #ref{name = privacy_default_list, min = 0, max = 1, label = '$default'}, #ref{name = privacy_active_list, min = 0, max = 1, label = '$active'}]}). -xml(block_item, #elem{name = <<"item">>, xmlns = <<"urn:xmpp:blocking">>, result = '$jid', attrs = [#attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}]}). -xml(block, #elem{name = <<"block">>, xmlns = <<"urn:xmpp:blocking">>, result = {block, '$items'}, refs = [#ref{name = block_item, label = '$items'}]}). -xml(unblock, #elem{name = <<"unblock">>, xmlns = <<"urn:xmpp:blocking">>, result = {unblock, '$items'}, refs = [#ref{name = block_item, label = '$items'}]}). -xml(block_list, #elem{name = <<"blocklist">>, xmlns = <<"urn:xmpp:blocking">>, result = {block_list}}). -xml(disco_identity, #elem{name = <<"identity">>, xmlns = <<"http://jabber.org/protocol/disco#info">>, result = {identity, '$category', '$type', '$lang', '$name'}, attrs = [#attr{name = <<"category">>, required = true}, #attr{name = <<"type">>, required = true}, #attr{name = <<"xml:lang">>, label = '$lang'}, #attr{name = <<"name">>}]}). -xml(disco_feature, #elem{name = <<"feature">>, xmlns = <<"http://jabber.org/protocol/disco#info">>, result = '$var', attrs = [#attr{name = <<"var">>, required = true}]}). -xml(disco_info, #elem{name = <<"query">>, xmlns = <<"http://jabber.org/protocol/disco#info">>, result = {disco_info, '$node', '$identities', '$features', '$xdata'}, attrs = [#attr{name = <<"node">>}], refs = [#ref{name = disco_identity, label = '$identities'}, #ref{name = disco_feature, label = '$features'}, #ref{name = xdata, label = '$xdata'}]}). -xml(disco_item, #elem{name = <<"item">>, xmlns = <<"http://jabber.org/protocol/disco#items">>, result = {disco_item, '$jid', '$name', '$node'}, attrs = [#attr{name = <<"jid">>, dec = {dec_jid, []}, enc = {enc_jid, []}, required = true}, #attr{name = <<"name">>}, #attr{name = <<"node">>}]}). -xml(disco_items, #elem{name = <<"query">>, xmlns = <<"http://jabber.org/protocol/disco#items">>, result = {disco_items, '$node', '$items'}, attrs = [#attr{name = <<"node">>}], refs = [#ref{name = disco_item, label = '$items'}]}). -xml(private, #elem{name = <<"query">>, xmlns = <<"jabber:iq:private">>, result = {private, '$_xmls'}}). -xml(conference_nick, #elem{name = <<"nick">>, xmlns = <<"storage:bookmarks">>, result = '$cdata'}). -xml(conference_password, #elem{name = <<"password">>, xmlns = <<"storage:bookmarks">>, result = '$cdata'}). -xml(bookmark_conference, #elem{name = <<"conference">>, xmlns = <<"storage:bookmarks">>, result = {bookmark_conference, '$name', '$jid', '$autojoin', '$nick', '$password'}, attrs = [#attr{name = <<"name">>, required = true}, #attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"autojoin">>, default = false, dec = {dec_bool, []}, enc = {enc_bool, []}}], refs = [#ref{name = conference_nick, label = '$nick', min = 0, max = 1}, #ref{name = conference_password, label = '$password', min = 0, max = 1}]}). -xml(bookmark_url, #elem{name = <<"url">>, xmlns = <<"storage:bookmarks">>, result = {bookmark_url, '$name', '$url'}, attrs = [#attr{name = <<"name">>, required = true}, #attr{name = <<"url">>, required = true}]}). -xml(bookmarks_storage, #elem{name = <<"storage">>, xmlns = <<"storage:bookmarks">>, result = {bookmark_storage, '$conference', '$url'}, refs = [#ref{name = bookmark_conference, label = '$conference'}, #ref{name = bookmark_url, label = '$url'}]}). -xml(stat_error, #elem{name = <<"error">>, xmlns = <<"http://jabber.org/protocol/stats">>, result = {'$code', '$cdata'}, attrs = [#attr{name = <<"code">>, required = true, enc = {enc_int, []}, dec = {dec_int, []}}]}). -xml(stat, #elem{name = <<"stat">>, xmlns = <<"http://jabber.org/protocol/stats">>, result = {stat, '$name', '$units', '$value', '$error'}, attrs = [#attr{name = <<"name">>, required = true}, #attr{name = <<"units">>}, #attr{name = <<"value">>}], refs = [#ref{name = stat_error, label = '$error'}]}). -xml(stats, #elem{name = <<"query">>, xmlns = <<"http://jabber.org/protocol/stats">>, result = {stats, '$stat'}, refs = [#ref{name = stat, label = '$stat'}]}). -xml(iq, #elem{name = <<"iq">>, xmlns = <<"jabber:client">>, result = {iq, '$id', '$type', '$lang', '$from', '$to', '$error', '$_els'}, attrs = [#attr{name = <<"id">>, required = true}, #attr{name = <<"type">>, required = true, enc = {enc_enum, []}, dec = {dec_enum, [[get, set, result, error]]}}, #attr{name = <<"from">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"to">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"xml:lang">>, label = '$lang'}], refs = [#ref{name = error, min = 0, max = 1, label = '$error'}]}). -xml(message_subject, #elem{name = <<"subject">>, xmlns = <<"jabber:client">>, result = {text, '$lang', '$data'}, cdata = #cdata{label = '$data'}, attrs = [#attr{name = <<"xml:lang">>, label = '$lang'}]}). -xml(message_body, #elem{name = <<"body">>, xmlns = <<"jabber:client">>, result = {text, '$lang', '$data'}, cdata = #cdata{label = '$data'}, attrs = [#attr{name = <<"xml:lang">>, label = '$lang'}]}). -xml(message_thread, #elem{name = <<"thread">>, xmlns = <<"jabber:client">>, result = '$cdata'}). -xml(message, #elem{name = <<"message">>, xmlns = <<"jabber:client">>, result = {message, '$id', '$type', '$lang', '$from', '$to', '$subject', '$body', '$thread', '$error', '$_els'}, attrs = [#attr{name = <<"id">>}, #attr{name = <<"type">>, default = normal, enc = {enc_enum, []}, dec = {dec_enum, [[chat, normal, groupchat, headline, error]]}}, #attr{name = <<"from">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"to">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"xml:lang">>, label = '$lang'}], refs = [#ref{name = error, min = 0, max = 1, label = '$error'}, #ref{name = message_subject, label = '$subject'}, #ref{name = message_thread, min = 0, max = 1, label = '$thread'}, #ref{name = message_body, label = '$body'}]}). -xml(presence_show, #elem{name = <<"show">>, xmlns = <<"jabber:client">>, result = '$cdata', cdata = #cdata{enc = {enc_enum, []}, dec = {dec_enum, [[away, chat, dnd, xa]]}}}). -xml(presence_status, #elem{name = <<"status">>, xmlns = <<"jabber:client">>, result = {text, '$lang', '$data'}, cdata = #cdata{label = '$data'}, attrs = [#attr{name = <<"xml:lang">>, label = '$lang'}]}). -xml(presence_priority, #elem{name = <<"priority">>, xmlns = <<"jabber:client">>, result = '$cdata', cdata = #cdata{enc = {enc_int, []}, dec = {dec_int, []}}}). -xml(presence, #elem{name = <<"presence">>, xmlns = <<"jabber:client">>, result = {presence, '$id', '$type', '$lang', '$from', '$to', '$show', '$status', '$priority', '$error', '$_els'}, attrs = [#attr{name = <<"id">>}, #attr{name = <<"type">>, enc = {enc_enum, []}, dec = {dec_enum, [[unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error]]}}, #attr{name = <<"from">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"to">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"xml:lang">>, label = '$lang'}], refs = [#ref{name = error, min = 0, max = 1, label = '$error'}, #ref{name = presence_show, min = 0, max = 1, label = '$show'}, #ref{name = presence_status, label = '$status'}, #ref{name = presence_priority, min = 0, max = 1, label = '$priority'}]}). -xml(error_bad_request, #elem{name = <<"bad-request">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'bad-request'}). -xml(error_conflict, #elem{name = <<"conflict">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'conflict'}). -xml(error_feature_not_implemented, #elem{name = <<"feature-not-implemented">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'feature-not-implemented'}). -xml(error_forbidden, #elem{name = <<"forbidden">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'forbidden'}). -xml(error_gone, #elem{name = <<"gone">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, cdata = #cdata{label = '$uri'}, result = {'gone', '$uri'}}). -xml(error_internal_server_error, #elem{name = <<"internal-server-error">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'internal-server-error'}). -xml(error_item_not_found, #elem{name = <<"item-not-found">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'item-not-found'}). -xml(error_jid_malformed, #elem{name = <<"jid-malformed">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'jid-malformed'}). -xml(error_not_acceptable, #elem{name = <<"not-acceptable">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'not-acceptable'}). -xml(error_not_allowed, #elem{name = <<"not-allowed">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'not-allowed'}). -xml(error_not_authorized, #elem{name = <<"not-authorized">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'not-authorized'}). -xml(error_policy_violation, #elem{name = <<"policy-violation">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'policy-violation'}). -xml(error_recipient_unavailable, #elem{name = <<"recipient-unavailable">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'recipient-unavailable'}). -xml(error_redirect, #elem{name = <<"redirect">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, cdata = #cdata{label = '$uri'}, result = {'redirect', '$uri'}}). -xml(error_registration_required, #elem{name = <<"registration-required">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'registration-required'}). -xml(error_remote_server_not_found, #elem{name = <<"remote-server-not-found">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'remote-server-not-found'}). -xml(error_remote_server_timeout, #elem{name = <<"remote-server-timeout">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'remote-server-timeout'}). -xml(error_resource_constraint, #elem{name = <<"resource-constraint">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'resource-constraint'}). -xml(error_service_unavailable, #elem{name = <<"service-unavailable">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'service-unavailable'}). -xml(error_subscription_required, #elem{name = <<"subscription-required">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'subscription-required'}). -xml(error_undefined_condition, #elem{name = <<"undefined-condition">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'undefined-condition'}). -xml(error_unexpected_request, #elem{name = <<"unexpected-request">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, result = 'unexpected-request'}). -xml(error_text, #elem{name = <<"text">>, result = {text, '$lang', '$data'}, cdata = #cdata{label = '$data'}, xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>, attrs = [#attr{name = <<"xml:lang">>, label = '$lang'}]}). -xml(error, #elem{name = <<"error">>, xmlns = <<"jabber:client">>, result = {error, '$type', '$by', '$reason', '$text'}, attrs = [#attr{name = <<"type">>, label = '$type', required = true, dec = {dec_enum, [[auth, cancel, continue, modify, wait]]}, enc = {enc_enum, []}}, #attr{name = <<"by">>}], refs = [#ref{name = error_text, min = 0, max = 1, label = '$text'}, #ref{name = error_bad_request, min = 0, max = 1, label = '$reason'}, #ref{name = error_conflict, min = 0, max = 1, label = '$reason'}, #ref{name = error_feature_not_implemented, min = 0, max = 1, label = '$reason'}, #ref{name = error_forbidden, min = 0, max = 1, label = '$reason'}, #ref{name = error_gone, min = 0, max = 1, label = '$reason'}, #ref{name = error_internal_server_error, min = 0, max = 1, label = '$reason'}, #ref{name = error_item_not_found, min = 0, max = 1, label = '$reason'}, #ref{name = error_jid_malformed, min = 0, max = 1, label = '$reason'}, #ref{name = error_not_acceptable, min = 0, max = 1, label = '$reason'}, #ref{name = error_not_allowed, min = 0, max = 1, label = '$reason'}, #ref{name = error_not_authorized, min = 0, max = 1, label = '$reason'}, #ref{name = error_policy_violation, min = 0, max = 1, label = '$reason'}, #ref{name = error_recipient_unavailable, min = 0, max = 1, label = '$reason'}, #ref{name = error_redirect, min = 0, max = 1, label = '$reason'}, #ref{name = error_registration_required, min = 0, max = 1, label = '$reason'}, #ref{name = error_remote_server_not_found, min = 0, max = 1, label = '$reason'}, #ref{name = error_remote_server_timeout, min = 0, max = 1, label = '$reason'}, #ref{name = error_resource_constraint, min = 0, max = 1, label = '$reason'}, #ref{name = error_service_unavailable, min = 0, max = 1, label = '$reason'}, #ref{name = error_subscription_required, min = 0, max = 1, label = '$reason'}, #ref{name = error_undefined_condition, min = 0, max = 1, label = '$reason'}, #ref{name = error_unexpected_request, min = 0, max = 1, label = '$reason'}]}). -xml(bind_jid, #elem{name = <<"jid">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-bind">>, result = '$cdata', cdata = #cdata{dec = {dec_jid, []}, enc = {enc_jid, []}}}). -xml(bind_resource, #elem{name = <<"resource">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-bind">>, result = '$cdata', cdata = #cdata{dec = {resourceprep, []}, enc = {resourceprep, []}}}). -xml(bind, #elem{name = <<"bind">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-bind">>, result = {bind, '$jid', '$resource'}, refs = [#ref{name = bind_jid, label = '$jid', min = 0, max = 1}, #ref{name = bind_resource, min = 0, max = 1, label = '$resource'}]}). -xml(sasl_auth, #elem{name = <<"auth">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, cdata = #cdata{label = '$text', dec = {base64, decode, []}, enc = {base64, encode, []}}, result = {sasl_auth, '$mechanism', '$text'}, attrs = [#attr{name = <<"mechanism">>, required = true}]}). -xml(sasl_abort, #elem{name = <<"abort">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, result = {sasl_abort}}). -xml(sasl_challenge, #elem{name = <<"challenge">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, cdata = #cdata{label = '$text', dec = {base64, decode, []}, enc = {base64, encode, []}}, result = {sasl_challenge, '$text'}}). -xml(sasl_response, #elem{name = <<"response">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, cdata = #cdata{label = '$text', dec = {base64, decode, []}, enc = {base64, encode, []}}, result = {sasl_response, '$text'}}). -xml(sasl_success, #elem{name = <<"success">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, cdata = #cdata{label = '$text', dec = {base64, decode, []}, enc = {base64, encode, []}}, result = {sasl_success, '$text'}}). -xml(sasl_failure_text, #elem{name = <<"text">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, result = {text, '$lang', '$data'}, cdata = #cdata{label = '$data'}, attrs = [#attr{name = <<"xml:lang">>, label = '$lang'}]}). -xml(sasl_failure_aborted, #elem{name = <<"aborted">>, result = 'aborted', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_account_disabled, #elem{name = <<"account-disabled">>, result = 'account-disabled', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_credentials_expired, #elem{name = <<"credentials-expired">>, result = 'credentials-expired', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_encryption_required, #elem{name = <<"encryption-required">>, result = 'encryption-required', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_incorrect_encoding, #elem{name = <<"incorrect-encoding">>, result = 'incorrect-encoding', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_invalid_authzid, #elem{name = <<"invalid-authzid">>, result = 'invalid-authzid', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_invalid_mechanism, #elem{name = <<"invalid-mechanism">>, result = 'invalid-mechanism', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_malformed_request, #elem{name = <<"malformed-request">>, result = 'malformed-request', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_mechanism_too_weak, #elem{name = <<"mechanism-too-weak">>, result = 'mechanism-too-weak', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_not_authorized, #elem{name = <<"not-authorized">>, result = 'not-authorized', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure_temporary_auth_failure, #elem{name = <<"temporary-auth-failure">>, result = 'temporary-auth-failure', xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>}). -xml(sasl_failure, #elem{name = <<"failure">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, result = {sasl_failure, '$reason', '$text'}, refs = [#ref{name = sasl_failure_text, label = '$text'}, #ref{name = sasl_failure_aborted, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_account_disabled, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_credentials_expired, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_encryption_required, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_incorrect_encoding, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_invalid_authzid, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_invalid_mechanism, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_malformed_request, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_mechanism_too_weak, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_not_authorized, min = 0, max = 1, label = '$reason'}, #ref{name = sasl_failure_temporary_auth_failure, min = 0, max = 1, label = '$reason'}]}). -xml(sasl_mechanism, #elem{name = <<"mechanism">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, result = '$cdata'}). -xml(sasl_mechanisms, #elem{name = <<"mechanisms">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>, result = {sasl_mechanisms, '$list'}, refs = [#ref{name = sasl_mechanism, label = '$list'}]}). -xml(starttls_required, #elem{name = <<"required">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>, result = true}). -xml(starttls, #elem{name = <<"starttls">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>, result = {starttls, '$required'}, refs = [#ref{name = starttls_required, label = '$required', min = 0, max = 1, default = false}]}). -xml(starttls_proceed, #elem{name = <<"proceed">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>, result = {starttls_proceed}}). -xml(starttls_failure, #elem{name = <<"failure">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>, result = {starttls_failure}}). -xml(compress_failure_setup_failed, #elem{name = <<"setup-failed">>, xmlns = <<"http://jabber.org/protocol/compress">>, result = 'setup-failed'}). -xml(compress_failure_processing_failed, #elem{name = <<"processing-failed">>, xmlns = <<"http://jabber.org/protocol/compress">>, result = 'processing-failed'}). -xml(compress_failure_unsupported_method, #elem{name = <<"unsupported-method">>, xmlns = <<"http://jabber.org/protocol/compress">>, result = 'unsupported-method'}). -xml(compress_failure, #elem{name = <<"failure">>, xmlns = <<"http://jabber.org/protocol/compress">>, result = {compress_failure, '$reason'}, refs = [#ref{name = compress_failure_setup_failed, min = 0, max = 1, label = '$reason'}, #ref{name = compress_failure_processing_failed, min = 0, max = 1, label = '$reason'}, #ref{name = compress_failure_unsupported_method, min = 0, max = 1, label = '$reason'}]}). -xml(compress_method, #elem{name = <<"method">>, xmlns = <<"http://jabber.org/protocol/compress">>, result = '$cdata'}). -xml(compress, #elem{name = <<"compress">>, xmlns = <<"http://jabber.org/protocol/compress">>, result = {compress, '$methods'}, refs = [#ref{name = compress_method, label = '$methods'}]}). -xml(compressed, #elem{name = <<"compressed">>, xmlns = <<"http://jabber.org/protocol/compress">>, result = {compressed}}). -xml(compression_method, #elem{name = <<"method">>, xmlns = <<"http://jabber.org/features/compress">>, result = '$cdata'}). -xml(compression, #elem{name = <<"compression">>, xmlns = <<"http://jabber.org/features/compress">>, result = {compression, '$methods'}, refs = [#ref{name = compression_method, label = '$methods'}]}). -xml(stream_features, #elem{name = <<"stream:features">>, xmlns = <<"http://etherx.jabber.org/streams">>, result = {stream_features, '$_els'}}). -xml(p1_push, #elem{name = <<"push">>, result = {p1_push}, xmlns = <<"p1:push">>}). -xml(p1_rebind, #elem{name = <<"rebind">>, result = {p1_rebind}, xmlns = <<"p1:rebind">>}). -xml(p1_ack, #elem{name = <<"ack">>, result = {p1_ack}, xmlns = <<"p1:ack">>}). -xml(caps, #elem{name = <<"c">>, xmlns = <<"http://jabber.org/protocol/caps">>, result = {caps, '$hash', '$node', '$ver'}, attrs = [#attr{name = <<"hash">>}, #attr{name = <<"node">>}, #attr{name = <<"ver">>, enc = {base64, encode, []}, dec = {base64, decode, []}}]}). -xml(feature_register, #elem{name = <<"register">>, xmlns = <<"http://jabber.org/features/iq-register">>, result = {feature_register}}). -xml(register_registered, #elem{name = <<"registered">>, xmlns = <<"jabber:iq:register">>, result = true}). -xml(register_remove, #elem{name = <<"remove">>, xmlns = <<"jabber:iq:register">>, result = true}). -xml(register_instructions, #elem{name = <<"instructions">>, xmlns = <<"jabber:iq:register">>, result = '$cdata'}). -xml(register_username, #elem{name = <<"username">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_nick, #elem{name = <<"nick">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_password, #elem{name = <<"password">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_name, #elem{name = <<"name">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_first, #elem{name = <<"first">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_last, #elem{name = <<"last">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_email, #elem{name = <<"email">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_address, #elem{name = <<"address">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_city, #elem{name = <<"city">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_state, #elem{name = <<"state">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_zip, #elem{name = <<"zip">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_phone, #elem{name = <<"phone">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_url, #elem{name = <<"url">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_date, #elem{name = <<"date">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_misc, #elem{name = <<"misc">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_text, #elem{name = <<"text">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register_key, #elem{name = <<"key">>, xmlns = <<"jabber:iq:register">>, cdata = #cdata{default = none}, result = '$cdata'}). -xml(register, #elem{name = <<"query">>, xmlns = <<"jabber:iq:register">>, result = {register, '$registered', '$remove', '$instructions', '$username', '$nick', '$password', '$name', '$first', '$last', '$email', '$address', '$city', '$state', '$zip', '$phone', '$url', '$date', '$misc', '$text', '$key', '$xdata'}, refs = [#ref{name = xdata, min = 0, max = 1, label = '$xdata'}, #ref{name = register_registered, min = 0, max = 1, default = false, label = '$registered'}, #ref{name = register_remove, min = 0, max = 1, default = false, label = '$remove'}, #ref{name = register_instructions, min = 0, max = 1, label = '$instructions'}, #ref{name = register_username, min = 0, max = 1, label = '$username'}, #ref{name = register_nick, min = 0, max = 1, label = '$nick'}, #ref{name = register_password, min = 0, max = 1, label = '$password'}, #ref{name = register_name, min = 0, max = 1, label = '$name'}, #ref{name = register_first, min = 0, max = 1, label = '$first'}, #ref{name = register_last, min = 0, max = 1, label = '$last'}, #ref{name = register_email, min = 0, max = 1, label = '$email'}, #ref{name = register_address, min = 0, max = 1, label = '$address'}, #ref{name = register_city, min = 0, max = 1, label = '$city'}, #ref{name = register_state, min = 0, max = 1, label = '$state'}, #ref{name = register_zip, min = 0, max = 1, label = '$zip'}, #ref{name = register_phone, min = 0, max = 1, label = '$phone'}, #ref{name = register_url, min = 0, max = 1, label = '$url'}, #ref{name = register_date, min = 0, max = 1, label = '$date'}, #ref{name = register_misc, min = 0, max = 1, label = '$misc'}, #ref{name = register_text, min = 0, max = 1, label = '$text'}, #ref{name = register_key, min = 0, max = 1, label = '$key'}]}). -xml(session, #elem{name = <<"session">>, xmlns = <<"urn:ietf:params:xml:ns:xmpp-session">>, result = {session}}). -xml(ping, #elem{name = <<"ping">>, xmlns = <<"urn:xmpp:ping">>, result = {ping}}). -xml(time_utc, #elem{name = <<"utc">>, xmlns = <<"urn:xmpp:time">>, result = '$cdata', cdata = #cdata{dec = {dec_utc, []}, enc = {enc_utc, []}}}). -xml(time_tzo, #elem{name = <<"tzo">>, xmlns = <<"urn:xmpp:time">>, result = '$cdata', cdata = #cdata{dec = {dec_tzo, []}, enc = {enc_tzo, []}}}). -xml(time, #elem{name = <<"time">>, xmlns = <<"urn:xmpp:time">>, result = {time, '$tzo', '$utc'}, refs = [#ref{name = time_tzo, label = '$tzo', min = 0, max = 1}, #ref{name = time_utc, label = '$utc', min = 0, max = 1}]}). -xml(stream_error_text, #elem{name = <<"text">>, result = {text, '$lang', '$data'}, cdata = #cdata{label = '$data'}, xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>, attrs = [#attr{name = <<"xml:lang">>, label = '$lang'}]}). -xml(stream_error_bad_format, #elem{name = <<"bad-format">>, result = 'bad-format', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_bad_namespace_prefix, #elem{name = <<"bad-namespace-prefix">>, result = 'bad-namespace-prefix', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_conflict, #elem{name = <<"conflict">>, result = 'conflict', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_connection_timeout, #elem{name = <<"connection-timeout">>, result = 'connection-timeout', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_host_gone, #elem{name = <<"host-gone">>, result = 'host-gone', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_host_unknown, #elem{name = <<"host-unknown">>, result = 'host-unknown', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_improper_addressing, #elem{name = <<"improper-addressing">>, result = 'improper-addressing', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_internal_server_error, #elem{name = <<"internal-server-error">>, result = 'internal-server-error', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_invalid_from, #elem{name = <<"invalid-from">>, result = 'invalid-from', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_invalid_id, #elem{name = <<"invalid-id">>, result = 'invalid-id', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_invalid_namespace, #elem{name = <<"invalid-namespace">>, result = 'invalid-namespace', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_invalid_xml, #elem{name = <<"invalid-xml">>, result = 'invalid-xml', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_not_authorized, #elem{name = <<"not-authorized">>, result = 'not-authorized', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_not_well_formed, #elem{name = <<"not-well-formed">>, result = 'not-well-formed', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_policy_violation, #elem{name = <<"policy-violation">>, result = 'policy-violation', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_remote_connection_failed, #elem{name = <<"remote-connection-failed">>, result = 'remote-connection-failed', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_reset, #elem{name = <<"reset">>, result = 'reset', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_resource_constraint, #elem{name = <<"resource-constraint">>, result = 'resource-constraint', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_restricted_xml, #elem{name = <<"restricted-xml">>, result = 'restricted-xml', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_see_other_host, #elem{name = <<"see-other-host">>, cdata = #cdata{required = true, label = '$host'}, result = {'see-other-host', '$host'}, xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_system_shutdown, #elem{name = <<"system-shutdown">>, result = 'system-shutdown', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_undefined_condition, #elem{name = <<"undefined-condition">>, result = 'undefined-condition', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_unsupported_encoding, #elem{name = <<"unsupported-encoding">>, result = 'unsupported-encoding', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_unsupported_stanza_type, #elem{name = <<"unsupported-stanza-type">>, result = 'unsupported-stanza-type', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error_unsupported_version, #elem{name = <<"unsupported-version">>, result = 'unsupported-version', xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>}). -xml(stream_error, #elem{name = <<"stream:error">>, xmlns = <<"http://etherx.jabber.org/streams">>, result = {stream_error, '$reason', '$text'}, refs = [#ref{name = stream_error_text, label = '$text', min = 0, max = 1}, #ref{name = stream_error_bad_format, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_bad_namespace_prefix, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_conflict, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_connection_timeout, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_host_gone, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_host_unknown, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_improper_addressing, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_internal_server_error, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_invalid_from, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_invalid_id, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_invalid_namespace, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_invalid_xml, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_not_authorized, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_not_well_formed, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_policy_violation, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_remote_connection_failed, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_reset, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_resource_constraint, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_restricted_xml, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_see_other_host, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_system_shutdown, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_undefined_condition, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_unsupported_encoding, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_unsupported_stanza_type, min = 0, max = 1, label = '$reason'}, #ref{name = stream_error_unsupported_version, min = 0, max = 1, label = '$reason'} ]}). -xml(vcard_HOME, #elem{name = <<"HOME">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_WORK, #elem{name = <<"WORK">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_VOICE, #elem{name = <<"VOICE">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_FAX, #elem{name = <<"FAX">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_PAGER, #elem{name = <<"PAGER">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_MSG, #elem{name = <<"MSG">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_CELL, #elem{name = <<"CELL">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_VIDEO, #elem{name = <<"VIDEO">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_BBS, #elem{name = <<"BBS">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_MODEM, #elem{name = <<"MODEM">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_ISDN, #elem{name = <<"ISDN">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_PCS, #elem{name = <<"PCS">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_POSTAL, #elem{name = <<"POSTAL">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_PARCEL, #elem{name = <<"PARCEL">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_DOM, #elem{name = <<"DOM">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_INTL, #elem{name = <<"INTL">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_PREF, #elem{name = <<"PREF">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_INTERNET, #elem{name = <<"INTERNET">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_X400, #elem{name = <<"X400">>, xmlns = <<"vcard-temp">>, result = true}). -xml(vcard_FAMILY, #elem{name = <<"FAMILY">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_GIVEN, #elem{name = <<"GIVEN">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_MIDDLE, #elem{name = <<"MIDDLE">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_PREFIX, #elem{name = <<"PREFIX">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_SUFFIX, #elem{name = <<"SUFFIX">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_POBOX, #elem{name = <<"POBOX">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_EXTADD, #elem{name = <<"EXTADD">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_STREET, #elem{name = <<"STREET">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_LOCALITY, #elem{name = <<"LOCALITY">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_REGION, #elem{name = <<"REGION">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_PCODE, #elem{name = <<"PCODE">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_CTRY, #elem{name = <<"CTRY">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_LINE, #elem{name = <<"LINE">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_NUMBER, #elem{name = <<"NUMBER">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_USERID, #elem{name = <<"USERID">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_LAT, #elem{name = <<"LAT">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_LON, #elem{name = <<"LON">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_ORGNAME, #elem{name = <<"ORGNAME">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_ORGUNIT, #elem{name = <<"ORGUNIT">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_PHONETIC, #elem{name = <<"PHONETIC">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_CRED, #elem{name = <<"CRED">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_VERSION, #elem{name = <<"VERSION">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_FN, #elem{name = <<"FN">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_NICKNAME, #elem{name = <<"NICKNAME">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_BDAY, #elem{name = <<"BDAY">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_JABBERID, #elem{name = <<"JABBERID">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_MAILER, #elem{name = <<"MAILER">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_TZ, #elem{name = <<"TZ">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_TITLE, #elem{name = <<"TITLE">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_ROLE, #elem{name = <<"ROLE">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_KEYWORD, #elem{name = <<"KEYWORD">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_NOTE, #elem{name = <<"NOTE">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_PRODID, #elem{name = <<"PRODID">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_REV, #elem{name = <<"REV">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_SORT_STRING, #elem{name = <<"SORT-STRING">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_UID, #elem{name = <<"UID">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_URL, #elem{name = <<"URL">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_DESC, #elem{name = <<"DESC">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_TYPE, #elem{name = <<"TYPE">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_EXTVAL, #elem{name = <<"EXTVAL">>, xmlns = <<"vcard-temp">>, result = '$cdata'}). -xml(vcard_PUBLIC, #elem{name = <<"PUBLIC">>, xmlns = <<"vcard-temp">>, result = public}). -xml(vcard_PRIVATE, #elem{name = <<"PRIVATE">>, xmlns = <<"vcard-temp">>, result = private}). -xml(vcard_CONFIDENTIAL, #elem{name = <<"CONFIDENTIAL">>, xmlns = <<"vcard-temp">>, result = confidential}). -xml(vcard_N, #elem{name = <<"N">>, xmlns = <<"vcard-temp">>, result = {vcard_name, '$family', '$given', '$middle', '$prefix', '$suffix'}, refs = [#ref{name = vcard_FAMILY, min = 0, max = 1, label = '$family'}, #ref{name = vcard_GIVEN, min = 0, max = 1, label = '$given'}, #ref{name = vcard_MIDDLE, min = 0, max = 1, label = '$middle'}, #ref{name = vcard_PREFIX, min = 0, max = 1, label = '$prefix'}, #ref{name = vcard_SUFFIX, min = 0, max = 1, label = '$suffix'}]}). -xml(vcard_ADR, #elem{name = <<"ADR">>, xmlns = <<"vcard-temp">>, result = {vcard_adr, '$home', '$work', '$postal', '$parcel', '$dom', '$intl', '$pref', '$pobox', '$extadd', '$street', '$locality', '$region', '$pcode', '$ctry'}, refs = [#ref{name = vcard_HOME, default = false, min = 0, max = 1, label = '$home'}, #ref{name = vcard_WORK, default = false, min = 0, max = 1, label = '$work'}, #ref{name = vcard_POSTAL, default = false, min = 0, max = 1, label = '$postal'}, #ref{name = vcard_PARCEL, default = false, min = 0, max = 1, label = '$parcel'}, #ref{name = vcard_DOM, default = false, min = 0, max = 1, label = '$dom'}, #ref{name = vcard_INTL, default = false, min = 0, max = 1, label = '$intl'}, #ref{name = vcard_PREF, default = false, min = 0, max = 1, label = '$pref'}, #ref{name = vcard_POBOX, min = 0, max = 1, label = '$pobox'}, #ref{name = vcard_EXTADD, min = 0, max = 1, label = '$extadd'}, #ref{name = vcard_STREET, min = 0, max = 1, label = '$street'}, #ref{name = vcard_LOCALITY, min = 0, max = 1, label = '$locality'}, #ref{name = vcard_REGION, min = 0, max = 1, label = '$region'}, #ref{name = vcard_PCODE, min = 0, max = 1, label = '$pcode'}, #ref{name = vcard_CTRY, min = 0, max = 1, label = '$ctry'}]}). -xml(vcard_LABEL, #elem{name = <<"LABEL">>, xmlns = <<"vcard-temp">>, result = {vcard_label, '$home', '$work', '$postal', '$parcel', '$dom', '$intl', '$pref', '$line'}, refs = [#ref{name = vcard_HOME, default = false, min = 0, max = 1, label = '$home'}, #ref{name = vcard_WORK, default = false, min = 0, max = 1, label = '$work'}, #ref{name = vcard_POSTAL, default = false, min = 0, max = 1, label = '$postal'}, #ref{name = vcard_PARCEL, default = false, min = 0, max = 1, label = '$parcel'}, #ref{name = vcard_DOM, default = false, min = 0, max = 1, label = '$dom'}, #ref{name = vcard_INTL, default = false, min = 0, max = 1, label = '$intl'}, #ref{name = vcard_PREF, default = false, min = 0, max = 1, label = '$pref'}, #ref{name = vcard_LINE, label = '$line'}]}). -xml(vcard_TEL, #elem{name = <<"TEL">>, xmlns = <<"vcard-temp">>, result = {vcard_tel, '$home', '$work', '$voice', '$fax', '$pager', '$msg', '$cell', '$video', '$bbs', '$modem', '$isdn', '$pcs', '$pref', '$number'}, refs = [#ref{name = vcard_HOME, default = false, min = 0, max = 1, label = '$home'}, #ref{name = vcard_WORK, default = false, min = 0, max = 1, label = '$work'}, #ref{name = vcard_VOICE, default = false, min = 0, max = 1, label = '$voice'}, #ref{name = vcard_FAX, default = false, min = 0, max = 1, label = '$fax'}, #ref{name = vcard_PAGER, default = false, min = 0, max = 1, label = '$pager'}, #ref{name = vcard_MSG, default = false, min = 0, max = 1, label = '$msg'}, #ref{name = vcard_CELL, default = false, min = 0, max = 1, label = '$cell'}, #ref{name = vcard_VIDEO, default = false, min = 0, max = 1, label = '$video'}, #ref{name = vcard_BBS, default = false, min = 0, max = 1, label = '$bbs'}, #ref{name = vcard_MODEM, default = false, min = 0, max = 1, label = '$modem'}, #ref{name = vcard_ISDN, default = false, min = 0, max = 1, label = '$isdn'}, #ref{name = vcard_PCS, default = false, min = 0, max = 1, label = '$pcs'}, #ref{name = vcard_PREF, default = false, min = 0, max = 1, label = '$pref'}, #ref{name = vcard_NUMBER, min = 0, max = 1, label = '$number'}]}). -xml(vcard_EMAIL, #elem{name = <<"EMAIL">>, xmlns = <<"vcard-temp">>, result = {vcard_email, '$home', '$work', '$internet', '$pref', '$x400', '$userid'}, refs = [#ref{name = vcard_HOME, default = false, min = 0, max = 1, label = '$home'}, #ref{name = vcard_WORK, default = false, min = 0, max = 1, label = '$work'}, #ref{name = vcard_INTERNET, default = false, min = 0, max = 1, label = '$internet'}, #ref{name = vcard_PREF, default = false, min = 0, max = 1, label = '$pref'}, #ref{name = vcard_X400, default = false, min = 0, max = 1, label = '$x400'}, #ref{name = vcard_USERID, min = 0, max = 1, label = '$userid'}]}). -xml(vcard_GEO, #elem{name = <<"GEO">>, xmlns = <<"vcard-temp">>, result = {vcard_geo, '$lat', '$lon'}, refs = [#ref{name = vcard_LAT, min = 0, max = 1, label = '$lat'}, #ref{name = vcard_LON, min = 0, max = 1, label = '$lon'}]}). -xml(vcard_BINVAL, #elem{name = <<"BINVAL">>, xmlns = <<"vcard-temp">>, cdata = #cdata{dec = {base64, decode, []}, enc = {base64, encode, []}}, result = '$cdata'}). -xml(vcard_LOGO, #elem{name = <<"LOGO">>, xmlns = <<"vcard-temp">>, result = {vcard_logo, '$type', '$binval', '$extval'}, refs = [#ref{name = vcard_TYPE, min = 0, max = 1, label = '$type'}, #ref{name = vcard_BINVAL, min = 0, max = 1, label = '$binval'}, #ref{name = vcard_EXTVAL, min = 0, max = 1, label = '$extval'}]}). -xml(vcard_PHOTO, #elem{name = <<"PHOTO">>, xmlns = <<"vcard-temp">>, result = {vcard_photo, '$type', '$binval', '$extval'}, refs = [#ref{name = vcard_TYPE, min = 0, max = 1, label = '$type'}, #ref{name = vcard_BINVAL, min = 0, max = 1, label = '$binval'}, #ref{name = vcard_EXTVAL, min = 0, max = 1, label = '$extval'}]}). -xml(vcard_ORG, #elem{name = <<"ORG">>, xmlns = <<"vcard-temp">>, result = {vcard_org, '$name', '$units'}, refs = [#ref{name = vcard_ORGNAME, label = '$name', min = 0, max = 1}, #ref{name = vcard_ORGUNIT, label = '$units'}]}). -xml(vcard_SOUND, #elem{name = <<"SOUND">>, xmlns = <<"vcard-temp">>, result = {vcard_sound, '$phonetic', '$binval', '$extval'}, refs = [#ref{name = vcard_BINVAL, min = 0, max = 1, label = '$binval'}, #ref{name = vcard_EXTVAL, min = 0, max = 1, label = '$extval'}, #ref{name = vcard_PHONETIC, min = 0, max = 1, label = '$phonetic'}]}). -xml(vcard_KEY, #elem{name = <<"KEY">>, xmlns = <<"vcard-temp">>, result = {vcard_key, '$type', '$cred'}, refs = [#ref{name = vcard_TYPE, min = 0, max = 1, label = '$type'}, #ref{name = vcard_CRED, min = 0, max = 1, label = '$cred'}]}). -xml(vcard_CATEGORIES, #elem{name = <<"CATEGORIES">>, xmlns = <<"vcard-temp">>, result = '$keywords', refs = [#ref{name = vcard_KEYWORD, label = '$keywords'}]}). -xml(vcard_CLASS, #elem{name = <<"CLASS">>, xmlns = <<"vcard-temp">>, result = '$class', refs = [#ref{name = vcard_PUBLIC, min = 0, max = 1, label = '$class'}, #ref{name = vcard_PRIVATE, min = 0, max = 1, label = '$class'}, #ref{name = vcard_CONFIDENTIAL, min = 0, max = 1, label = '$class'}]}). %% {vcard_AGENT, %% #elem{name = <<"AGENT">>, %% xmlns = <<"vcard-temp">>, %% result = {vcard_agent, '$vcard', '$extval'}, %% refs = [#ref{name = vcard, min = 0, max = 1, label = '$vcard'}, %% #ref{name = vcard_EXTVAL, min = 0, max = 1, label = '$extval'}]}). -xml(vcard, #elem{name = <<"vCard">>, xmlns = <<"vcard-temp">>, result = {vcard, '$version', '$fn', '$n', '$nickname', '$photo', '$bday', '$adr', '$label', '$tel', '$email', '$jabberid', '$mailer', '$tz', '$geo', '$title', '$role', '$logo', '$org', '$categories', '$note', '$prodid', %% '$agent', '$rev', '$sort_string', '$sound', '$uid', '$url', '$class', '$key', '$desc'}, refs = [#ref{name = vcard_N, min = 0, max = 1, label = '$n'}, #ref{name = vcard_ADR, label = '$adr'}, #ref{name = vcard_LABEL, label = '$label'}, #ref{name = vcard_TEL, label = '$tel'}, #ref{name = vcard_EMAIL, label = '$email'}, #ref{name = vcard_GEO, min = 0, max = 1, label = '$geo'}, #ref{name = vcard_LOGO, min = 0, max = 1, label = '$logo'}, #ref{name = vcard_PHOTO, min = 0, max = 1, label = '$photo'}, #ref{name = vcard_ORG, min = 0, max = 1, label = '$org'}, #ref{name = vcard_SOUND, min = 0, max = 1, label = '$sound'}, #ref{name = vcard_KEY, min = 0, max = 1, label = '$key'}, #ref{name = vcard_VERSION, min = 0, max = 1, label = '$version'}, #ref{name = vcard_FN, min = 0, max = 1, label = '$fn'}, #ref{name = vcard_NICKNAME, min = 0, max = 1, label = '$nickname'}, #ref{name = vcard_BDAY, min = 0, max = 1, label = '$bday'}, #ref{name = vcard_JABBERID, min = 0, max = 1, label = '$jabberid'}, #ref{name = vcard_MAILER, min = 0, max = 1, label = '$mailer'}, #ref{name = vcard_TZ, min = 0, max = 1, label = '$tz'}, #ref{name = vcard_TITLE, min = 0, max = 1, label = '$title'}, #ref{name = vcard_ROLE, min = 0, max = 1, label = '$role'}, #ref{name = vcard_NOTE, min = 0, max = 1, label = '$note'}, #ref{name = vcard_PRODID, min = 0, max = 1, label = '$prodid'}, #ref{name = vcard_REV, min = 0, max = 1, label = '$rev'}, %%#ref{name = vcard_AGENT, min = 0, max = 1, label = '$agent'}, #ref{name = vcard_SORT_STRING, min = 0, max = 1, label = '$sort_string'}, #ref{name = vcard_UID, min = 0, max = 1, label = '$uid'}, #ref{name = vcard_URL, min = 0, max = 1, label = '$url'}, #ref{name = vcard_DESC, min = 0, max = 1, label = '$desc'}, #ref{name = vcard_CATEGORIES, default = [], min = 0, max = 1, label = '$categories'}, #ref{name = vcard_CLASS, min = 0, max = 1, label = '$class'}]}). -xml(vcard_xupdate_photo, #elem{name = <<"photo">>, xmlns = <<"vcard-temp:x:update">>, result = '$cdata'}). -xml(vcard_xupdate, #elem{name = <<"x">>, xmlns = <<"vcard-temp:x:update">>, result = {vcard_xupdate, '$photo'}, refs = [#ref{name = vcard_xupdate_photo, min = 0, max = 1, label = '$photo'}]}). -xml(xdata_field_required, #elem{name = <<"required">>, xmlns = <<"jabber:x:data">>, result = true}). -xml(xdata_field_desc, #elem{name = <<"desc">>, xmlns = <<"jabber:x:data">>, result = '$cdata'}). -xml(xdata_field_value, #elem{name = <<"value">>, xmlns = <<"jabber:x:data">>, result = '$cdata'}). -xml(xdata_field_option, #elem{name = <<"option">>, xmlns = <<"jabber:x:data">>, result = '$value', refs = [#ref{name = xdata_field_value, label = '$value', min = 1, max = 1}]}). -xml(xdata_field, #elem{name = <<"field">>, xmlns = <<"jabber:x:data">>, result = {xdata_field, '$label', '$type', '$var', '$required', '$desc', '$values', '$options'}, attrs = [#attr{name = <<"label">>}, #attr{name = <<"type">>, enc = {enc_enum, []}, dec = {dec_enum, [['boolean', 'fixed', 'hidden', 'jid-multi', 'jid-single', 'list-multi', 'list-single', 'text-multi', 'text-private', 'text-single']]}}, #attr{name = <<"var">>}], refs = [#ref{name = xdata_field_required, label = '$required', default = false, min = 0, max = 1}, #ref{name = xdata_field_desc, label = '$desc', min = 0, max = 1}, #ref{name = xdata_field_value, label = '$values'}, #ref{name = xdata_field_option, label = '$options'}]}). -xml(xdata_instructions, #elem{name = <<"instructions">>, xmlns = <<"jabber:x:data">>, result = '$cdata'}). -xml(xdata_title, #elem{name = <<"title">>, xmlns = <<"jabber:x:data">>, result = '$cdata'}). -xml(xdata_reported, #elem{name = <<"reported">>, xmlns = <<"jabber:x:data">>, result = '$fields', refs = [#ref{name = xdata_field, label = '$fields'}]}). -xml(xdata_item, #elem{name = <<"item">>, xmlns = <<"jabber:x:data">>, result = '$fields', refs = [#ref{name = xdata_field, label = '$fields'}]}). -xml(xdata, #elem{name = <<"x">>, xmlns = <<"jabber:x:data">>, result = {xdata, '$type', '$instructions', '$title', '$reported', '$items', '$fields'}, attrs = [#attr{name = <<"type">>, required = true, dec = {dec_enum, [[cancel, form, result, submit]]}, enc = {enc_enum, []}}], refs = [#ref{name = xdata_instructions, label = '$instructions'}, #ref{name = xdata_title, label = '$title', min = 0, max = 1}, #ref{name = xdata_reported, label = '$reported', min = 0, max = 1}, #ref{name = xdata_item, label = '$items'}, #ref{name = xdata_field, label = '$fields'}]}). -xml(pubsub_subscription, #elem{name = <<"subscription">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_subscription, '$jid', '$node', '$subid', '$type'}, attrs = [#attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"node">>}, #attr{name = <<"subid">>}, #attr{name = <<"subscription">>, label = '$type', dec = {dec_enum, [[none, pending, subscribed, unconfigured]]}, enc = {enc_enum, []}}]}). -xml(pubsub_affiliation, #elem{name = <<"affiliation">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_affiliation, '$node', '$type'}, attrs = [#attr{name = <<"node">>, required = true}, #attr{name = <<"affiliation">>, label = '$type', required = true, dec = {dec_enum, [[member, none, outcast, owner, publisher, 'publish-only']]}, enc = {enc_enum, []}}]}). -xml(pubsub_item, #elem{name = <<"item">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_item, '$id', '$_xmls'}, attrs = [#attr{name = <<"id">>}]}). -xml(pubsub_items, #elem{name = <<"items">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_items, '$node', '$max_items', '$subid', '$items'}, attrs = [#attr{name = <<"max_items">>, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"node">>, required = true}, #attr{name = <<"subid">>}], refs = [#ref{name = pubsub_item, label = '$items'}]}). -xml(pubsub_event_retract, #elem{name = <<"retract">>, xmlns = <<"http://jabber.org/protocol/pubsub#event">>, result = '$id', attrs = [#attr{name = <<"id">>, required = true}]}). -xml(pubsub_event_item, #elem{name = <<"item">>, xmlns = <<"http://jabber.org/protocol/pubsub#event">>, result = {pubsub_event_item, '$id', '$node', '$publisher'}, attrs = [#attr{name = <<"id">>}, #attr{name = <<"node">>}, #attr{name = <<"publisher">>}]}). -xml(pubsub_event_items, #elem{name = <<"items">>, xmlns = <<"http://jabber.org/protocol/pubsub#event">>, result = {pubsub_event_items, '$node', '$retract', '$items'}, attrs = [#attr{name = <<"node">>, required = true}], refs = [#ref{name = pubsub_event_retract, label = '$retract'}, #ref{name = pubsub_event_item, label = '$items'}]}). -xml(pubsub_event, #elem{name = <<"event">>, xmlns = <<"http://jabber.org/protocol/pubsub#event">>, result = {pubsub_event, '$items'}, refs = [#ref{name = pubsub_event_items, label = '$items'}]}). -xml(pubsub_subscriptions, #elem{name = <<"subscriptions">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {'$node', '$subscriptions'}, attrs = [#attr{name = <<"node">>, default = none}], refs = [#ref{name = pubsub_subscription, label = '$subscriptions'}]}). -xml(pubsub_affiliations, #elem{name = <<"affiliations">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = '$affiliations', refs = [#ref{name = pubsub_affiliation, label = '$affiliations'}]}). -xml(pubsub_subscribe, #elem{name = <<"subscribe">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_subscribe, '$node', '$jid'}, attrs = [#attr{name = <<"node">>}, #attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}]}). -xml(pubsub_unsubscribe, #elem{name = <<"unsubscribe">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_unsubscribe, '$node', '$jid', '$subid'}, attrs = [#attr{name = <<"node">>}, #attr{name = <<"subid">>}, #attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}]}). -xml(pubsub_publish, #elem{name = <<"publish">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_publish, '$node', '$items'}, attrs = [#attr{name = <<"node">>, required = true}], refs = [#ref{name = pubsub_item, label = '$items'}]}). -xml(pubsub_options, #elem{name = <<"options">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_options, '$node', '$jid', '$subid', '$xdata'}, attrs = [#attr{name = <<"node">>}, #attr{name = <<"subid">>}, #attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}], refs = [#ref{name = xdata, min = 0, max = 1, label = '$xdata'}]}). -xml(pubsub_retract, #elem{name = <<"retract">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub_retract, '$node', '$notify', '$items'}, attrs = [#attr{name = <<"node">>, required = true}, #attr{name = <<"notify">>, default = false, dec = {dec_bool, []}, enc = {enc_bool, []}}], refs = [#ref{name = pubsub_item, label = '$items'}]}). -xml(pubsub, #elem{name = <<"pubsub">>, xmlns = <<"http://jabber.org/protocol/pubsub">>, result = {pubsub, '$subscriptions', '$affiliations', '$publish', '$subscribe', '$unsubscribe', '$options', '$items', '$retract'}, refs = [#ref{name = pubsub_subscriptions, label = '$subscriptions', min = 0, max = 1}, #ref{name = pubsub_affiliations, label = '$affiliations', min = 0, max = 1}, #ref{name = pubsub_subscribe, label = '$subscribe', min = 0, max = 1}, #ref{name = pubsub_unsubscribe, label = '$unsubscribe', min = 0, max = 1}, #ref{name = pubsub_options, label = '$options', min = 0, max = 1}, #ref{name = pubsub_items, label = '$items', min = 0, max = 1}, #ref{name = pubsub_retract, label = '$retract', min = 0, max = 1}, #ref{name = pubsub_publish, label = '$publish', min = 0, max = 1}]}). -xml(shim_header, #elem{name = <<"header">>, xmlns = <<"http://jabber.org/protocol/shim">>, result = {'$name', '$cdata'}, attrs = [#attr{name = <<"name">>, required = true}]}). -xml(shim_headers, #elem{name = <<"headers">>, xmlns = <<"http://jabber.org/protocol/shim">>, result = {shim, '$headers'}, refs = [#ref{name = shim_header, label = '$headers'}]}). -record(chatstate, {type :: active | composing | gone | inactive | paused}). -xml(chatstate_active, #elem{name = <<"active">>, xmlns = <<"http://jabber.org/protocol/chatstates">>, result = {chatstate, active}}). -xml(chatstate_composing, #elem{name = <<"composing">>, xmlns = <<"http://jabber.org/protocol/chatstates">>, result = {chatstate, composing}}). -xml(chatstate_gone, #elem{name = <<"gone">>, xmlns = <<"http://jabber.org/protocol/chatstates">>, result = {chatstate, gone}}). -xml(chatstate_inactive, #elem{name = <<"inactive">>, xmlns = <<"http://jabber.org/protocol/chatstates">>, result = {chatstate, inactive}}). -xml(chatstate_paused, #elem{name = <<"paused">>, xmlns = <<"http://jabber.org/protocol/chatstates">>, result = {chatstate, paused}}). -xml(delay, #elem{name = <<"delay">>, xmlns = <<"urn:xmpp:delay">>, result = {delay, '$stamp', '$from'}, attrs = [#attr{name = <<"stamp">>, required = true, dec = {dec_utc, []}, enc = {enc_utc, []}}, #attr{name = <<"from">>, dec = {dec_jid, []}, enc = {enc_jid, []}}]}). -xml(bytestreams_streamhost, #elem{name = <<"streamhost">>, xmlns = <<"http://jabber.org/protocol/bytestreams">>, result = {streamhost, '$jid', '$host', '$port'}, attrs = [#attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"host">>, required = true}, #attr{name = <<"port">>, default = 1080, dec = {dec_int, [0, 65535]}, enc = {enc_int, []}}]}). -xml(bytestreams_streamhost_used, #elem{name = <<"streamhost-used">>, xmlns = <<"http://jabber.org/protocol/bytestreams">>, result = '$jid', attrs = [#attr{name = <<"jid">>, required = true, dec = {dec_jid, []}, enc = {enc_jid, []}}]}). -xml(bytestreams_activate, #elem{name = <<"activate">>, xmlns = <<"http://jabber.org/protocol/bytestreams">>, cdata = #cdata{enc = {enc_jid, []}, dec = {dec_jid, []}}, result = '$cdata'}). -xml(bytestreams, #elem{name = <<"query">>, xmlns = <<"http://jabber.org/protocol/bytestreams">>, result = {bytestreams, '$hosts', '$used', '$activate', '$dstaddr', '$mode', '$sid'}, attrs = [#attr{name = <<"dstaddr">>}, #attr{name = <<"sid">>}, #attr{name = <<"mode">>, default = tcp, dec = {dec_enum, [[tcp, udp]]}, enc = {enc_enum, []}}], refs = [#ref{name = bytestreams_streamhost, label = '$hosts'}, #ref{name = bytestreams_streamhost_used, min = 0, max = 1, label = '$used'}, #ref{name = bytestreams_activate, min = 0, max = 1, label = '$activate'}]}). -xml(muc_history, #elem{name = <<"history">>, xmlns = <<"http://jabber.org/protocol/muc">>, result = {muc_history, '$maxchars', '$maxstanzas', '$seconds', '$since'}, attrs = [#attr{name = <<"maxchars">>, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"maxstanzas">>, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"seconds">>, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"since">>, dec = {dec_utc, []}, enc = {enc_utc, []}}]}). -xml(muc_user_reason, #elem{name = <<"reason">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = '$cdata'}). -xml(muc_user_decline, #elem{name = <<"decline">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = {muc_decline, '$reason', '$from', '$to'}, attrs = [#attr{name = <<"to">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"from">>, dec = {dec_jid, []}, enc = {enc_jid, []}}], refs = [#ref{name = muc_user_reason, min = 0, max = 1, label = '$reason'}]}). -xml(muc_user_destroy, #elem{name = <<"destroy">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = {muc_user_destroy, '$reason', '$jid'}, attrs = [#attr{name = <<"jid">>, dec = {dec_jid, []}, enc = {enc_jid, []}}], refs = [#ref{name = muc_user_reason, min = 0, max = 1, label = '$reason'}]}). -xml(muc_user_invite, #elem{name = <<"invite">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = {muc_invite, '$reason', '$from', '$to'}, attrs = [#attr{name = <<"to">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"from">>, dec = {dec_jid, []}, enc = {enc_jid, []}}], refs = [#ref{name = muc_user_reason, min = 0, max = 1, label = '$reason'}]}). -xml(muc_user_actor, #elem{name = <<"actor">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = {muc_actor, '$jid', '$nick'}, attrs = [#attr{name = <<"jid">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"nick">>}]}). -xml(muc_user_continue, #elem{name = <<"continue">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = '$thread', attrs = [#attr{name = <<"thread">>}]}). -xml(muc_user_status, #elem{name = <<"status">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = '$code', attrs = [#attr{name = <<"code">>, dec = {dec_int, [100, 999]}, enc = {enc_int, []}}]}). -xml(muc_user_item, #elem{name = <<"item">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = {muc_item, '$actor', '$continue', '$reason', '$affiliation', '$role', '$jid', '$nick'}, refs = [#ref{name = muc_user_actor, min = 0, max = 1, label = '$actor'}, #ref{name = muc_user_continue, min = 0, max = 1, label = '$continue'}, #ref{name = muc_user_reason, min = 0, max = 1, label = '$reason'}], attrs = [#attr{name = <<"affiliation">>, dec = {dec_enum, [[admin, member, none, outcast, owner]]}, enc = {enc_enum, []}}, #attr{name = <<"role">>, dec = {dec_enum, [[moderator, none, participant, visitor]]}, enc = {enc_enum, []}}, #attr{name = <<"jid">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"nick">>}]}). -xml(muc_user, #elem{name = <<"x">>, xmlns = <<"http://jabber.org/protocol/muc#user">>, result = {muc_user, '$decline', '$destroy', '$invites', '$items', '$status_codes', '$password'}, attrs = [#attr{name = <<"password">>}], refs = [#ref{name = muc_user_decline, min = 0, max = 1, label = '$decline'}, #ref{name = muc_user_destroy, min = 0, max = 1, label = '$destroy'}, #ref{name = muc_user_invite, label = '$invites'}, #ref{name = muc_user_item, label = '$items'}, #ref{name = muc_user_status, label = '$status_codes'}]}). -xml(muc_owner_password, #elem{name = <<"password">>, xmlns = <<"http://jabber.org/protocol/muc#owner">>, result = '$cdata'}). -xml(muc_owner_reason, #elem{name = <<"reason">>, xmlns = <<"http://jabber.org/protocol/muc#owner">>, result = '$cdata'}). -xml(muc_owner_destroy, #elem{name = <<"destroy">>, xmlns = <<"http://jabber.org/protocol/muc#owner">>, result = {muc_owner_destroy, '$jid', '$reason', '$password'}, attrs = [#attr{name = <<"jid">>, dec = {dec_jid, []}, enc = {enc_jid, []}}], refs = [#ref{name = muc_owner_password, min = 0, max = 1, label = '$password'}, #ref{name = muc_owner_reason, min = 0, max = 1, label = '$reason'}]}). -xml(muc_owner, #elem{name = <<"query">>, xmlns = <<"http://jabber.org/protocol/muc#owner">>, result = {muc_owner, '$destroy', '$config'}, refs = [#ref{name = muc_owner_destroy, min = 0, max = 1, label = '$destroy'}, #ref{name = xdata, min = 0, max = 1, label = '$config'}]}). -xml(muc_admin_item, #elem{name = <<"item">>, xmlns = <<"http://jabber.org/protocol/muc#admin">>, result = {muc_item, '$actor', '$continue', '$reason', '$affiliation', '$role', '$jid', '$nick'}, refs = [#ref{name = muc_admin_actor, min = 0, max = 1, label = '$actor'}, #ref{name = muc_admin_continue, min = 0, max = 1, label = '$continue'}, #ref{name = muc_admin_reason, min = 0, max = 1, label = '$reason'}], attrs = [#attr{name = <<"affiliation">>, dec = {dec_enum, [[admin, member, none, outcast, owner]]}, enc = {enc_enum, []}}, #attr{name = <<"role">>, dec = {dec_enum, [[moderator, none, participant, visitor]]}, enc = {enc_enum, []}}, #attr{name = <<"jid">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"nick">>}]}). -xml(muc_admin_actor, #elem{name = <<"actor">>, xmlns = <<"http://jabber.org/protocol/muc#admin">>, result = {muc_actor, '$jid', '$nick'}, attrs = [#attr{name = <<"jid">>, dec = {dec_jid, []}, enc = {enc_jid, []}}, #attr{name = <<"nick">>}]}). -xml(muc_admin_continue, #elem{name = <<"continue">>, xmlns = <<"http://jabber.org/protocol/muc#admin">>, result = '$thread', attrs = [#attr{name = <<"thread">>}]}). -xml(muc_admin_reason, #elem{name = <<"reason">>, xmlns = <<"http://jabber.org/protocol/muc#admin">>, result = '$cdata'}). -xml(muc_admin, #elem{name = <<"query">>, xmlns = <<"http://jabber.org/protocol/muc#admin">>, result = {muc_admin, '$items'}, refs = [#ref{name = muc_admin_item, label = '$items'}]}). -xml(muc, #elem{name = <<"x">>, xmlns = <<"http://jabber.org/protocol/muc">>, result = {muc, '$history', '$password'}, attrs = [#attr{name = <<"password">>}], 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">>, cdata = #cdata{default = none}, 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', '$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, #elem{name = <<"forwarded">>, xmlns = <<"urn:xmpp:forward:0">>, result = {forwarded, '$delay', '$_els'}, refs = [#ref{name = delay, min = 0, max = 1, label = '$delay'}]}). -xml(carbons_disable, #elem{name = <<"disable">>, xmlns = <<"urn:xmpp:carbons:2">>, result = {carbons_disable}}). -xml(carbons_enable, #elem{name = <<"enable">>, xmlns = <<"urn:xmpp:carbons:2">>, result = {carbons_enable}}). -xml(carbons_private, #elem{name = <<"private">>, xmlns = <<"urn:xmpp:carbons:2">>, result = {carbons_private}}). -xml(carbons_received, #elem{name = <<"received">>, xmlns = <<"urn:xmpp:carbons:2">>, result = {carbons_received, '$forwarded'}, refs = [#ref{name = forwarded, min = 1, max = 1, label = '$forwarded'}]}). -xml(carbons_sent, #elem{name = <<"sent">>, xmlns = <<"urn:xmpp:carbons:2">>, result = {carbons_sent, '$forwarded'}, refs = [#ref{name = forwarded, min = 1, max = 1, label = '$forwarded'}]}). -xml(feature_csi, #elem{name = <<"csi">>, xmlns = <<"urn:xmpp:csi:0">>, result = {feature_csi, '$xmlns'}, attrs = [#attr{name = <<"xmlns">>}]}). -record(csi, {type :: active | inactive}). -xml(csi_active, #elem{name = <<"active">>, xmlns = <<"urn:xmpp:csi:0">>, result = {csi, active}}). -xml(csi_inactive, #elem{name = <<"inactive">>, xmlns = <<"urn:xmpp:csi:0">>, result = {csi, inactive}}). -xml(feature_sm, #elem{name = <<"sm">>, xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>], result = {feature_sm, '$xmlns'}, attrs = [#attr{name = <<"xmlns">>}]}). -xml(sm_enable, #elem{name = <<"enable">>, xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>], result = {sm_enable, '$max', '$resume', '$xmlns'}, attrs = [#attr{name = <<"max">>, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"xmlns">>}, #attr{name = <<"resume">>, default = false, dec = {dec_bool, []}, enc = {enc_bool, []}}]}). -xml(sm_enabled, #elem{name = <<"enabled">>, xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>], result = {sm_enabled, '$id', '$location', '$max', '$resume', '$xmlns'}, attrs = [#attr{name = <<"id">>}, #attr{name = <<"location">>}, #attr{name = <<"xmlns">>}, #attr{name = <<"max">>, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"resume">>, default = false, dec = {dec_bool, []}, enc = {enc_bool, []}}]}). -xml(sm_resume, #elem{name = <<"resume">>, xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>], result = {sm_resume, '$h', '$previd', '$xmlns'}, attrs = [#attr{name = <<"h">>, required = true, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"xmlns">>}, #attr{name = <<"previd">>, required = true}]}). -xml(sm_resumed, #elem{name = <<"resumed">>, xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>], result = {sm_resumed, '$h', '$previd', '$xmlns'}, attrs = [#attr{name = <<"h">>, required = true, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"xmlns">>}, #attr{name = <<"previd">>, required = true}]}). -xml(sm_r, #elem{name = <<"r">>, xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>], result = {sm_r, '$xmlns'}, attrs = [#attr{name = <<"xmlns">>}]}). -xml(sm_a, #elem{name = <<"a">>, xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>], result = {sm_a, '$h', '$xmlns'}, attrs = [#attr{name = <<"h">>, required = true, dec = {dec_int, [0, infinity]}, enc = {enc_int, []}}, #attr{name = <<"xmlns">>}]}). -xml(sm_failed, #elem{name = <<"failed">>, xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>], result = {sm_failed, '$reason', '$xmlns'}, attrs = [#attr{name = <<"xmlns">>}], refs = [#ref{name = error_bad_request, min = 0, max = 1, label = '$reason'}, #ref{name = error_conflict, min = 0, max = 1, label = '$reason'}, #ref{name = error_feature_not_implemented, min = 0, max = 1, label = '$reason'}, #ref{name = error_forbidden, min = 0, max = 1, label = '$reason'}, #ref{name = error_gone, min = 0, max = 1, label = '$reason'}, #ref{name = error_internal_server_error, min = 0, max = 1, label = '$reason'}, #ref{name = error_item_not_found, min = 0, max = 1, label = '$reason'}, #ref{name = error_jid_malformed, min = 0, max = 1, label = '$reason'}, #ref{name = error_not_acceptable, min = 0, max = 1, label = '$reason'}, #ref{name = error_not_allowed, min = 0, max = 1, label = '$reason'}, #ref{name = error_not_authorized, min = 0, max = 1, label = '$reason'}, #ref{name = error_policy_violation, min = 0, max = 1, label = '$reason'}, #ref{name = error_recipient_unavailable, min = 0, max = 1, label = '$reason'}, #ref{name = error_redirect, min = 0, max = 1, label = '$reason'}, #ref{name = error_registration_required, min = 0, max = 1, label = '$reason'}, #ref{name = error_remote_server_not_found, min = 0, max = 1, label = '$reason'}, #ref{name = error_remote_server_timeout, min = 0, max = 1, label = '$reason'}, #ref{name = error_resource_constraint, min = 0, max = 1, label = '$reason'}, #ref{name = error_service_unavailable, min = 0, max = 1, label = '$reason'}, #ref{name = error_subscription_required, min = 0, max = 1, label = '$reason'}, #ref{name = error_undefined_condition, min = 0, max = 1, label = '$reason'}, #ref{name = error_unexpected_request, min = 0, max = 1, label = '$reason'}]}). dec_tzo(Val) -> [H1, M1] = str:tokens(Val, <<":">>), H = jlib:binary_to_integer(H1), M = jlib:binary_to_integer(M1), if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end. enc_tzo({H, M}) -> Sign = if H >= 0 -> <<>>; true -> <<"-">> end, list_to_binary([Sign, io_lib:format("~2..0w:~2..0w", [H, M])]). dec_utc(Val) -> {_, _, _} = jlib:datetime_string_to_timestamp(Val). enc_utc(Val) -> jlib:now_to_utc_string(Val). dec_jid(Val) -> case jid:from_string(Val) of error -> erlang:error(badarg); J -> J end. enc_jid(J) -> jid:to_string(J). resourceprep(R) -> case jid:resourceprep(R) of error -> erlang:error(badarg); R1 -> R1 end. dec_bool(<<"false">>) -> false; dec_bool(<<"0">>) -> false; dec_bool(<<"true">>) -> true; dec_bool(<<"1">>) -> true. enc_bool(false) -> <<"false">>; enc_bool(true) -> <<"true">>. %% Local Variables: %% mode: erlang %% End: %% vim: set filetype=erlang tabstop=8: ejabberd-16.01/tools/xmpp_codec.hrl0000644000232200023220000004335612645157216017641 0ustar debalancedebalance%% Created automatically by XML generator (xml_gen.erl) %% Source: xmpp_codec.spec -record(chatstate, {type :: active | composing | gone | inactive | paused}). -record(csi, {type :: active | inactive}). -record(feature_register, {}). -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()}). -record(streamhost, {jid :: any(), host :: binary(), port = 1080 :: non_neg_integer()}). -record(sm_resume, {h :: non_neg_integer(), previd :: binary(), xmlns :: binary()}). -record(carbons_enable, {}). -record(carbons_private, {}). -record(pubsub_unsubscribe, {node :: binary(), jid :: any(), subid :: binary()}). -record(ping, {}). -record(delay, {stamp :: any(), from :: any()}). -record(muc_history, {maxchars :: non_neg_integer(), maxstanzas :: non_neg_integer(), seconds :: non_neg_integer(), since :: any()}). -record(pubsub_affiliation, {node :: binary(), type :: 'member' | 'none' | 'outcast' | 'owner' | 'publish-only' | 'publisher'}). -record(muc_decline, {reason :: binary(), from :: any(), to :: any()}). -record(sm_a, {h :: non_neg_integer(), xmlns :: binary()}). -record(starttls_proceed, {}). -record(sm_resumed, {h :: non_neg_integer(), previd :: binary(), xmlns :: binary()}). -record(forwarded, {delay :: #delay{}, sub_els = [] :: [any()]}). -record(sm_enable, {max :: non_neg_integer(), resume = false :: any(), xmlns :: binary()}). -record(starttls_failure, {}). -record(sasl_challenge, {text :: any()}). -record(gone, {uri :: binary()}). -record(private, {xml_els = [] :: [any()]}). -record(p1_ack, {}). -record(feature_sm, {xmlns :: binary()}). -record(pubsub_item, {id :: binary(), xml_els = [] :: [any()]}). -record(pubsub_publish, {node :: binary(), items = [] :: [#pubsub_item{}]}). -record(roster_item, {jid :: any(), name :: binary(), groups = [] :: [binary()], subscription = none :: 'both' | 'from' | 'none' | 'remove' | 'to', ask :: 'subscribe'}). -record(roster, {items = [] :: [#roster_item{}], ver :: binary()}). -record(pubsub_event_item, {id :: binary(), node :: binary(), publisher :: binary()}). -record(sm_r, {xmlns :: binary()}). -record(muc_actor, {jid :: any(), nick :: binary()}). -record(stat, {name :: binary(), units :: binary(), value :: binary(), error = [] :: [{integer(),'undefined' | binary()}]}). -record('see-other-host', {host :: binary()}). -record(compress, {methods = [] :: [binary()]}). -record(starttls, {required = false :: boolean()}). -record(last, {seconds :: non_neg_integer(), text :: binary()}). -record(redirect, {uri :: binary()}). -record(sm_enabled, {id :: binary(), location :: binary(), max :: non_neg_integer(), resume = false :: any(), xmlns :: binary()}). -record(pubsub_event_items, {node :: binary(), retract = [] :: [binary()], items = [] :: [#pubsub_event_item{}]}). -record(pubsub_event, {items = [] :: [#pubsub_event_items{}]}). -record(sasl_response, {text :: any()}). -record(pubsub_subscribe, {node :: binary(), jid :: any()}). -record(sasl_auth, {mechanism :: binary(), text :: any()}). -record(p1_push, {}). -record(feature_csi, {xmlns :: binary()}). -record(muc_user_destroy, {reason :: binary(), jid :: any()}). -record(disco_item, {jid :: any(), name :: binary(), node :: binary()}). -record(disco_items, {node :: binary(), items = [] :: [#disco_item{}]}). -record(unblock, {items = [] :: [any()]}). -record(block, {items = [] :: [any()]}). -record(session, {}). -record(compression, {methods = [] :: [binary()]}). -record(muc_owner_destroy, {jid :: any(), reason :: binary(), password :: binary()}). -record(pubsub_subscription, {jid :: any(), node :: binary(), subid :: binary(), type :: 'none' | 'pending' | 'subscribed' | 'unconfigured'}). -record(muc_item, {actor :: #muc_actor{}, continue :: binary(), reason :: binary(), affiliation :: 'admin' | 'member' | 'none' | 'outcast' | 'owner', role :: 'moderator' | 'none' | 'participant' | 'visitor', jid :: any(), nick :: binary()}). -record(muc_admin, {items = [] :: [#muc_item{}]}). -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()}). -record(muc, {history :: #muc_history{}, password :: binary()}). -record(stream_features, {sub_els = [] :: [any()]}). -record(stats, {stat = [] :: [#stat{}]}). -record(pubsub_items, {node :: binary(), max_items :: non_neg_integer(), subid :: binary(), items = [] :: [#pubsub_item{}]}). -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'}). -record(sasl_abort, {}). -record(vcard_email, {home = false :: boolean(), work = false :: boolean(), internet = false :: boolean(), pref = false :: boolean(), x400 = false :: boolean(), userid :: binary()}). -record(carbons_received, {forwarded :: #forwarded{}}). -record(pubsub_retract, {node :: binary(), notify = false :: any(), items = [] :: [#pubsub_item{}]}). -record(vcard_geo, {lat :: binary(), lon :: binary()}). -record(compressed, {}). -record(sasl_failure, {reason :: 'aborted' | 'account-disabled' | 'credentials-expired' | 'encryption-required' | 'incorrect-encoding' | 'invalid-authzid' | 'invalid-mechanism' | 'malformed-request' | 'mechanism-too-weak' | 'not-authorized' | 'temporary-auth-failure', text = [] :: [#text{}]}). -record(block_list, {}). -record(xdata_field, {label :: binary(), type :: 'boolean' | 'fixed' | 'hidden' | 'jid-multi' | 'jid-single' | 'list-multi' | 'list-single' | 'text-multi' | 'text-private' | 'text-single', var :: binary(), required = false :: boolean(), desc :: binary(), values = [] :: [binary()], options = [] :: [binary()]}). -record(version, {name :: binary(), ver :: binary(), os :: binary()}). -record(muc_invite, {reason :: binary(), from :: any(), to :: any()}). -record(bind, {jid :: any(), resource :: any()}). -record(muc_user, {decline :: #muc_decline{}, destroy :: #muc_user_destroy{}, invites = [] :: [#muc_invite{}], items = [] :: [#muc_item{}], status_codes = [] :: [pos_integer()], password :: binary()}). -record(vcard_xupdate, {photo :: binary()}). -record(carbons_disable, {}). -record(bytestreams, {hosts = [] :: [#streamhost{}], used :: any(), activate :: any(), dstaddr :: binary(), mode = tcp :: 'tcp' | 'udp', sid :: binary()}). -record(vcard_org, {name :: binary(), units = [] :: [binary()]}). -record(rsm_set, {'after' :: binary(), before :: 'none' | 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{}, stable :: any(), complete :: any()}). -record(vcard_tel, {home = false :: boolean(), work = false :: boolean(), voice = false :: boolean(), fax = false :: boolean(), pager = false :: boolean(), msg = false :: boolean(), cell = false :: boolean(), video = false :: boolean(), bbs = false :: boolean(), modem = false :: boolean(), isdn = false :: boolean(), pcs = false :: boolean(), pref = false :: boolean(), number :: binary()}). -record(vcard_key, {type :: binary(), cred :: binary()}). -record(vcard_name, {family :: binary(), given :: binary(), middle :: binary(), prefix :: binary(), suffix :: binary()}). -record(identity, {category :: binary(), type :: binary(), lang :: binary(), name :: binary()}). -record(bookmark_conference, {name :: binary(), jid :: any(), autojoin = false :: any(), nick :: binary(), password :: binary()}). -record(bookmark_url, {name :: binary(), url :: binary()}). -record(bookmark_storage, {conference = [] :: [#bookmark_conference{}], url = [] :: [#bookmark_url{}]}). -record(vcard_sound, {phonetic :: binary(), binval :: any(), extval :: binary()}). -record(vcard_photo, {type :: binary(), binval :: any(), extval :: binary()}). -record(vcard_label, {home = false :: boolean(), work = false :: boolean(), postal = false :: boolean(), parcel = false :: boolean(), dom = false :: boolean(), intl = false :: boolean(), pref = false :: boolean(), line = [] :: [binary()]}). -record(vcard_adr, {home = false :: boolean(), work = false :: boolean(), postal = false :: boolean(), parcel = false :: boolean(), dom = false :: boolean(), intl = false :: boolean(), pref = false :: boolean(), pobox :: binary(), extadd :: binary(), street :: binary(), locality :: binary(), region :: binary(), pcode :: binary(), ctry :: binary()}). -record(xdata, {type :: 'cancel' | 'form' | 'result' | 'submit', instructions = [] :: [binary()], title :: binary(), reported :: [#xdata_field{}], 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{}}). -record(pubsub_options, {node :: binary(), jid :: any(), subid :: binary(), xdata :: #xdata{}}). -record(pubsub, {subscriptions :: {'none' | binary(),[#pubsub_subscription{}]}, affiliations :: [#pubsub_affiliation{}], publish :: #pubsub_publish{}, subscribe :: #pubsub_subscribe{}, unsubscribe :: #pubsub_unsubscribe{}, options :: #pubsub_options{}, items :: #pubsub_items{}, retract :: #pubsub_retract{}}). -record(register, {registered = false :: boolean(), remove = false :: boolean(), instructions :: binary(), username :: 'none' | binary(), nick :: 'none' | binary(), password :: 'none' | binary(), name :: 'none' | binary(), first :: 'none' | binary(), last :: 'none' | binary(), email :: 'none' | binary(), address :: 'none' | binary(), city :: 'none' | binary(), state :: 'none' | binary(), zip :: 'none' | binary(), phone :: 'none' | binary(), url :: 'none' | binary(), date :: 'none' | binary(), misc :: 'none' | binary(), text :: 'none' | binary(), key :: 'none' | binary(), xdata :: #xdata{}}). -record(disco_info, {node :: binary(), identities = [] :: [#identity{}], features = [] :: [binary()], xdata = [] :: [#xdata{}]}). -record(sasl_mechanisms, {list = [] :: [binary()]}). -record(sm_failed, {reason :: atom() | #gone{} | #redirect{}, xmlns :: binary()}). -record(error, {type :: 'auth' | 'cancel' | 'continue' | 'modify' | 'wait', by :: binary(), reason :: atom() | #gone{} | #redirect{}, text :: #text{}}). -record(presence, {id :: binary(), type :: 'error' | 'probe' | 'subscribe' | 'subscribed' | 'unavailable' | 'unsubscribe' | 'unsubscribed', lang :: binary(), from :: any(), to :: any(), show :: 'away' | 'chat' | 'dnd' | 'xa', status = [] :: [#text{}], priority :: integer(), error :: #error{}, sub_els = [] :: [any()]}). -record(message, {id :: binary(), type = normal :: 'chat' | 'error' | 'groupchat' | 'headline' | 'normal', lang :: binary(), from :: any(), to :: any(), subject = [] :: [#text{}], body = [] :: [#text{}], thread :: binary(), error :: #error{}, sub_els = [] :: [any()]}). -record(iq, {id :: binary(), type :: 'error' | 'get' | 'result' | 'set', lang :: binary(), from :: any(), to :: any(), error :: #error{}, sub_els = [] :: [any()]}). -record(privacy_item, {order :: non_neg_integer(), action :: 'allow' | 'deny', type :: 'group' | 'jid' | 'subscription', value :: binary(), kinds = [] :: ['iq' | 'message' | 'presence-in' | 'presence-out']}). -record(privacy_list, {name :: binary(), items = [] :: [#privacy_item{}]}). -record(privacy, {lists = [] :: [#privacy_list{}], default :: 'none' | binary(), active :: 'none' | binary()}). -record(stream_error, {reason :: atom() | #'see-other-host'{}, text :: #text{}}). -record(vcard_logo, {type :: binary(), binval :: any(), extval :: binary()}). -record(vcard, {version :: binary(), fn :: binary(), n :: #vcard_name{}, nickname :: binary(), photo :: #vcard_photo{}, bday :: binary(), adr = [] :: [#vcard_adr{}], label = [] :: [#vcard_label{}], tel = [] :: [#vcard_tel{}], email = [] :: [#vcard_email{}], jabberid :: binary(), mailer :: binary(), tz :: binary(), geo :: #vcard_geo{}, title :: binary(), role :: binary(), logo :: #vcard_logo{}, org :: #vcard_org{}, categories = [] :: [binary()], note :: binary(), prodid :: binary(), rev :: binary(), sort_string :: binary(), sound :: #vcard_sound{}, uid :: binary(), url :: binary(), class :: 'confidential' | 'private' | 'public', key :: #vcard_key{}, desc :: binary()}). -record(time, {tzo :: any(), utc :: any()}). ejabberd-16.01/tools/ejabberdctl.bc0000644000232200023220000000517612645157216017556 0ustar debalancedebalance# # bash completion for ejabberdctl # get_help() { local COMMANDCACHE=/var/log/ejabberd/bash_completion_$RANDOM ejabberdctl $CTLARGS help >$COMMANDCACHE if [[ $? == 2 ]] ; then ISRUNNING=1 runningcommands=`cat $COMMANDCACHE | grep "^ [a-z]" | awk '{print $1}' | xargs` fi rm $COMMANDCACHE } _ejabberdctl() { local cur prev local ISRUNNING=0 local runningcommands COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" local startcoms="start debug live" local startpars="--config-dir --config --ctl-config --logs --spool" local i=1 local CTLARGS="" while [ $i -lt $COMP_CWORD ] ; do local PARAM="${COMP_WORDS[i]}" i=$((i+1)) case $PARAM in --*) CTLARGS="--node ${COMP_WORDS[i]}" i=$((i+1)) ;; *) break ;; esac done case "${prev##*/}" in ejabberdctl) # This clause matches even when calling `/sbin/ejabberdctl` thanks to the ##*/ in the case get_help COMPREPLY=($(compgen -W "--node --auth ${startpars} ${startcoms} ${runningcommands}" -- $cur)) return 0 ;; start|live) COMPREPLY=($(compgen -W "--node ${startpars}" -- $cur)) return 0 ;; debug) COMPREPLY=($(compgen -W "--node" -- $cur)) return 0 ;; help) get_help COMPREPLY=($(compgen -W "${runningcommands}" -- $cur)) return 0 ;; --node) RUNNINGNODES=`epmd -names | grep name | awk '{print $2"@localhost"}' | xargs` COMPREPLY=($(compgen -W "$RUNNINGNODES" -- $cur)) return 0 ;; --config|--ctl-config) _filedir '?(u)cfg' return 0 ;; --config-dir|--logs|--spool) _filedir return 0 ;; *) prev2="${COMP_WORDS[COMP_CWORD-2]}" get_help if [[ "$prev2" == --* ]]; then COMPREPLY=($(compgen -W "--node --auth ${startpars} ${startcoms} ${runningcommands}" -- $cur)) else if [[ $ISRUNNING == 1 ]]; then echo "" ejabberdctl $CTLARGS help ${PARAM} echo -n "${COMP_LINE}" fi fi return 0 ;; esac } complete -F _ejabberdctl ejabberdctl # Local variables: # mode: shell-script # sh-basic-offset: 4 # sh-indent-comment: t # indent-tabs-mode: nil # End: # ex: ts=4 sw=4 et filetype=sh ejabberd-16.01/tools/captcha.sh0000755000232200023220000000413512645157216016743 0ustar debalancedebalance#!/bin/sh INPUT=$1 if test -n ${BASH_VERSION:-''} ; then get_random () { R=$RANDOM } else for n in `od -A n -t u2 -N 48 /dev/urandom`; do RL="$RL$n "; done get_random () { R=${RL%% *} RL=${RL#* } } fi get_random WAVE1_AMPLITUDE=$((2 + $R % 5)) get_random WAVE1_LENGTH=$((50 + $R % 25)) get_random WAVE2_AMPLITUDE=$((2 + $R % 5)) get_random WAVE2_LENGTH=$((50 + $R % 25)) get_random WAVE3_AMPLITUDE=$((2 + $R % 5)) get_random WAVE3_LENGTH=$((50 + $R % 25)) get_random W1_LINE_START_Y=$((10 + $R % 40)) get_random W1_LINE_STOP_Y=$((10 + $R % 40)) get_random W2_LINE_START_Y=$((10 + $R % 40)) get_random W2_LINE_STOP_Y=$((10 + $R % 40)) get_random W3_LINE_START_Y=$((10 + $R % 40)) get_random W3_LINE_STOP_Y=$((10 + $R % 40)) get_random B1_LINE_START_Y=$(($R % 40)) get_random B1_LINE_STOP_Y=$(($R % 40)) get_random B2_LINE_START_Y=$(($R % 40)) get_random B2_LINE_STOP_Y=$(($R % 40)) #B3_LINE_START_Y=$(($R % 40)) #B3_LINE_STOP_Y=$(($R % 40)) get_random B1_LINE_START_X=$(($R % 20)) get_random B1_LINE_STOP_X=$((100 + $R % 40)) get_random B2_LINE_START_X=$(($R % 20)) get_random B2_LINE_STOP_X=$((100 + $R % 40)) #B3_LINE_START_X=$(($R % 20)) #B3_LINE_STOP_X=$((100 + $R % 40)) get_random ROLL_X=$(($R % 40)) convert -size 180x60 xc:none -pointsize 40 \ \( -clone 0 -fill white \ -stroke black -strokewidth 4 -annotate +0+40 "$INPUT" \ -stroke white -strokewidth 2 -annotate +0+40 "$INPUT" \ -roll +$ROLL_X+0 \ -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ -roll -$ROLL_X+0 \) \ \( -clone 0 -stroke black \ -strokewidth 1 -draw \ "line $B1_LINE_START_X,$B1_LINE_START_Y $B1_LINE_STOP_X,$B1_LINE_STOP_Y" \ -strokewidth 1 -draw \ "line $B2_LINE_START_X,$B2_LINE_START_Y $B2_LINE_STOP_X,$B2_LINE_STOP_Y" \ -wave "$WAVE2_AMPLITUDE"x"$WAVE2_LENGTH" \) \ \( -clone 0 -stroke white \ -strokewidth 2 -draw "line 0,$W1_LINE_START_Y 140,$W1_LINE_STOP_Y" \ -strokewidth 2 -draw "line 0,$W2_LINE_START_Y 140,$W2_LINE_STOP_Y" \ -strokewidth 2 -draw "line 0,$W3_LINE_START_Y 140,$W3_LINE_STOP_Y" \ -wave "$WAVE3_AMPLITUDE"x"$WAVE3_LENGTH" \) \ -flatten -crop 140x60 +repage -quality 90 -depth 8 png:- ejabberd-16.01/tools/xmpp_codec.erl0000644000232200023220000255646412645157216017651 0ustar debalancedebalance%% Created automatically by XML generator (xml_gen.erl) %% Source: xmpp_codec.spec -module(xmpp_codec). -compile({nowarn_unused_function, [{dec_int, 3}, {dec_int, 1}, {dec_enum, 2}, {enc_int, 1}, {get_attr, 2}, {enc_enum, 1}]}). -export([pp/1, format_error/1, decode/1, decode/2, is_known_tag/1, encode/1, get_ns/1]). decode(_el) -> decode(_el, []). decode({xmlel, _name, _attrs, _} = _el, Opts) -> IgnoreEls = proplists:get_bool(ignore_els, Opts), case {_name, get_attr(<<"xmlns">>, _attrs)} of {<<"failed">>, <<"urn:xmpp:sm:2">>} -> decode_sm_failed(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"failed">>, <<"urn:xmpp:sm:3">>} -> decode_sm_failed(<<"urn:xmpp:sm:3">>, IgnoreEls, _el); {<<"a">>, <<"urn:xmpp:sm:2">>} -> decode_sm_a(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"a">>, <<"urn:xmpp:sm:3">>} -> decode_sm_a(<<"urn:xmpp:sm:3">>, IgnoreEls, _el); {<<"r">>, <<"urn:xmpp:sm:2">>} -> decode_sm_r(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"r">>, <<"urn:xmpp:sm:3">>} -> decode_sm_r(<<"urn:xmpp:sm:3">>, IgnoreEls, _el); {<<"resumed">>, <<"urn:xmpp:sm:2">>} -> decode_sm_resumed(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"resumed">>, <<"urn:xmpp:sm:3">>} -> decode_sm_resumed(<<"urn:xmpp:sm:3">>, IgnoreEls, _el); {<<"resume">>, <<"urn:xmpp:sm:2">>} -> decode_sm_resume(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"resume">>, <<"urn:xmpp:sm:3">>} -> decode_sm_resume(<<"urn:xmpp:sm:3">>, IgnoreEls, _el); {<<"enabled">>, <<"urn:xmpp:sm:2">>} -> decode_sm_enabled(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"enabled">>, <<"urn:xmpp:sm:3">>} -> decode_sm_enabled(<<"urn:xmpp:sm:3">>, IgnoreEls, _el); {<<"enable">>, <<"urn:xmpp:sm:2">>} -> decode_sm_enable(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"enable">>, <<"urn:xmpp:sm:3">>} -> decode_sm_enable(<<"urn:xmpp:sm:3">>, IgnoreEls, _el); {<<"sm">>, <<"urn:xmpp:sm:2">>} -> decode_feature_sm(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"sm">>, <<"urn:xmpp:sm:3">>} -> decode_feature_sm(<<"urn:xmpp:sm:3">>, IgnoreEls, _el); {<<"inactive">>, <<"urn:xmpp:csi:0">>} -> decode_csi_inactive(<<"urn:xmpp:csi:0">>, IgnoreEls, _el); {<<"active">>, <<"urn:xmpp:csi:0">>} -> decode_csi_active(<<"urn:xmpp:csi:0">>, IgnoreEls, _el); {<<"csi">>, <<"urn:xmpp:csi:0">>} -> decode_feature_csi(<<"urn:xmpp:csi:0">>, IgnoreEls, _el); {<<"sent">>, <<"urn:xmpp:carbons:2">>} -> decode_carbons_sent(<<"urn:xmpp:carbons:2">>, IgnoreEls, _el); {<<"received">>, <<"urn:xmpp:carbons:2">>} -> decode_carbons_received(<<"urn:xmpp:carbons:2">>, IgnoreEls, _el); {<<"private">>, <<"urn:xmpp:carbons:2">>} -> decode_carbons_private(<<"urn:xmpp:carbons:2">>, IgnoreEls, _el); {<<"enable">>, <<"urn:xmpp:carbons:2">>} -> decode_carbons_enable(<<"urn:xmpp:carbons:2">>, IgnoreEls, _el); {<<"disable">>, <<"urn:xmpp:carbons:2">>} -> decode_carbons_disable(<<"urn:xmpp:carbons:2">>, IgnoreEls, _el); {<<"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); {<<"query">>, <<"http://jabber.org/protocol/muc#admin">>} -> decode_muc_admin(<<"http://jabber.org/protocol/muc#admin">>, IgnoreEls, _el); {<<"reason">>, <<"http://jabber.org/protocol/muc#admin">>} -> decode_muc_admin_reason(<<"http://jabber.org/protocol/muc#admin">>, IgnoreEls, _el); {<<"continue">>, <<"http://jabber.org/protocol/muc#admin">>} -> decode_muc_admin_continue(<<"http://jabber.org/protocol/muc#admin">>, IgnoreEls, _el); {<<"actor">>, <<"http://jabber.org/protocol/muc#admin">>} -> decode_muc_admin_actor(<<"http://jabber.org/protocol/muc#admin">>, IgnoreEls, _el); {<<"item">>, <<"http://jabber.org/protocol/muc#admin">>} -> decode_muc_admin_item(<<"http://jabber.org/protocol/muc#admin">>, IgnoreEls, _el); {<<"query">>, <<"http://jabber.org/protocol/muc#owner">>} -> decode_muc_owner(<<"http://jabber.org/protocol/muc#owner">>, IgnoreEls, _el); {<<"destroy">>, <<"http://jabber.org/protocol/muc#owner">>} -> decode_muc_owner_destroy(<<"http://jabber.org/protocol/muc#owner">>, IgnoreEls, _el); {<<"reason">>, <<"http://jabber.org/protocol/muc#owner">>} -> decode_muc_owner_reason(<<"http://jabber.org/protocol/muc#owner">>, IgnoreEls, _el); {<<"password">>, <<"http://jabber.org/protocol/muc#owner">>} -> decode_muc_owner_password(<<"http://jabber.org/protocol/muc#owner">>, IgnoreEls, _el); {<<"x">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"item">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user_item(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"status">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user_status(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"continue">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user_continue(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"actor">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user_actor(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"invite">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user_invite(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"destroy">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user_destroy(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"decline">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user_decline(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"reason">>, <<"http://jabber.org/protocol/muc#user">>} -> decode_muc_user_reason(<<"http://jabber.org/protocol/muc#user">>, IgnoreEls, _el); {<<"history">>, <<"http://jabber.org/protocol/muc">>} -> decode_muc_history(<<"http://jabber.org/protocol/muc">>, IgnoreEls, _el); {<<"query">>, <<"http://jabber.org/protocol/bytestreams">>} -> decode_bytestreams(<<"http://jabber.org/protocol/bytestreams">>, IgnoreEls, _el); {<<"activate">>, <<"http://jabber.org/protocol/bytestreams">>} -> decode_bytestreams_activate(<<"http://jabber.org/protocol/bytestreams">>, IgnoreEls, _el); {<<"streamhost-used">>, <<"http://jabber.org/protocol/bytestreams">>} -> decode_bytestreams_streamhost_used(<<"http://jabber.org/protocol/bytestreams">>, IgnoreEls, _el); {<<"streamhost">>, <<"http://jabber.org/protocol/bytestreams">>} -> decode_bytestreams_streamhost(<<"http://jabber.org/protocol/bytestreams">>, IgnoreEls, _el); {<<"delay">>, <<"urn:xmpp:delay">>} -> decode_delay(<<"urn:xmpp:delay">>, IgnoreEls, _el); {<<"paused">>, <<"http://jabber.org/protocol/chatstates">>} -> decode_chatstate_paused(<<"http://jabber.org/protocol/chatstates">>, IgnoreEls, _el); {<<"inactive">>, <<"http://jabber.org/protocol/chatstates">>} -> decode_chatstate_inactive(<<"http://jabber.org/protocol/chatstates">>, IgnoreEls, _el); {<<"gone">>, <<"http://jabber.org/protocol/chatstates">>} -> decode_chatstate_gone(<<"http://jabber.org/protocol/chatstates">>, IgnoreEls, _el); {<<"composing">>, <<"http://jabber.org/protocol/chatstates">>} -> decode_chatstate_composing(<<"http://jabber.org/protocol/chatstates">>, IgnoreEls, _el); {<<"active">>, <<"http://jabber.org/protocol/chatstates">>} -> decode_chatstate_active(<<"http://jabber.org/protocol/chatstates">>, IgnoreEls, _el); {<<"headers">>, <<"http://jabber.org/protocol/shim">>} -> decode_shim_headers(<<"http://jabber.org/protocol/shim">>, IgnoreEls, _el); {<<"header">>, <<"http://jabber.org/protocol/shim">>} -> decode_shim_header(<<"http://jabber.org/protocol/shim">>, IgnoreEls, _el); {<<"pubsub">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"retract">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_retract(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"options">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_options(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"publish">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_publish(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"unsubscribe">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_unsubscribe(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"subscribe">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_subscribe(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"affiliations">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_affiliations(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"subscriptions">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_subscriptions(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"event">>, <<"http://jabber.org/protocol/pubsub#event">>} -> decode_pubsub_event(<<"http://jabber.org/protocol/pubsub#event">>, IgnoreEls, _el); {<<"items">>, <<"http://jabber.org/protocol/pubsub#event">>} -> decode_pubsub_event_items(<<"http://jabber.org/protocol/pubsub#event">>, IgnoreEls, _el); {<<"item">>, <<"http://jabber.org/protocol/pubsub#event">>} -> decode_pubsub_event_item(<<"http://jabber.org/protocol/pubsub#event">>, IgnoreEls, _el); {<<"retract">>, <<"http://jabber.org/protocol/pubsub#event">>} -> decode_pubsub_event_retract(<<"http://jabber.org/protocol/pubsub#event">>, IgnoreEls, _el); {<<"items">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_items(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"item">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_item(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"affiliation">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_affiliation(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"subscription">>, <<"http://jabber.org/protocol/pubsub">>} -> decode_pubsub_subscription(<<"http://jabber.org/protocol/pubsub">>, IgnoreEls, _el); {<<"x">>, <<"jabber:x:data">>} -> decode_xdata(<<"jabber:x:data">>, IgnoreEls, _el); {<<"item">>, <<"jabber:x:data">>} -> decode_xdata_item(<<"jabber:x:data">>, IgnoreEls, _el); {<<"reported">>, <<"jabber:x:data">>} -> decode_xdata_reported(<<"jabber:x:data">>, IgnoreEls, _el); {<<"title">>, <<"jabber:x:data">>} -> decode_xdata_title(<<"jabber:x:data">>, IgnoreEls, _el); {<<"instructions">>, <<"jabber:x:data">>} -> decode_xdata_instructions(<<"jabber:x:data">>, IgnoreEls, _el); {<<"field">>, <<"jabber:x:data">>} -> decode_xdata_field(<<"jabber:x:data">>, IgnoreEls, _el); {<<"option">>, <<"jabber:x:data">>} -> decode_xdata_field_option(<<"jabber:x:data">>, IgnoreEls, _el); {<<"value">>, <<"jabber:x:data">>} -> decode_xdata_field_value(<<"jabber:x:data">>, IgnoreEls, _el); {<<"desc">>, <<"jabber:x:data">>} -> decode_xdata_field_desc(<<"jabber:x:data">>, IgnoreEls, _el); {<<"required">>, <<"jabber:x:data">>} -> decode_xdata_field_required(<<"jabber:x:data">>, IgnoreEls, _el); {<<"x">>, <<"vcard-temp:x:update">>} -> decode_vcard_xupdate(<<"vcard-temp:x:update">>, IgnoreEls, _el); {<<"photo">>, <<"vcard-temp:x:update">>} -> decode_vcard_xupdate_photo(<<"vcard-temp:x:update">>, IgnoreEls, _el); {<<"vCard">>, <<"vcard-temp">>} -> decode_vcard(<<"vcard-temp">>, IgnoreEls, _el); {<<"CLASS">>, <<"vcard-temp">>} -> decode_vcard_CLASS(<<"vcard-temp">>, IgnoreEls, _el); {<<"CATEGORIES">>, <<"vcard-temp">>} -> decode_vcard_CATEGORIES(<<"vcard-temp">>, IgnoreEls, _el); {<<"KEY">>, <<"vcard-temp">>} -> decode_vcard_KEY(<<"vcard-temp">>, IgnoreEls, _el); {<<"SOUND">>, <<"vcard-temp">>} -> decode_vcard_SOUND(<<"vcard-temp">>, IgnoreEls, _el); {<<"ORG">>, <<"vcard-temp">>} -> decode_vcard_ORG(<<"vcard-temp">>, IgnoreEls, _el); {<<"PHOTO">>, <<"vcard-temp">>} -> decode_vcard_PHOTO(<<"vcard-temp">>, IgnoreEls, _el); {<<"LOGO">>, <<"vcard-temp">>} -> decode_vcard_LOGO(<<"vcard-temp">>, IgnoreEls, _el); {<<"BINVAL">>, <<"vcard-temp">>} -> decode_vcard_BINVAL(<<"vcard-temp">>, IgnoreEls, _el); {<<"GEO">>, <<"vcard-temp">>} -> decode_vcard_GEO(<<"vcard-temp">>, IgnoreEls, _el); {<<"EMAIL">>, <<"vcard-temp">>} -> decode_vcard_EMAIL(<<"vcard-temp">>, IgnoreEls, _el); {<<"TEL">>, <<"vcard-temp">>} -> decode_vcard_TEL(<<"vcard-temp">>, IgnoreEls, _el); {<<"LABEL">>, <<"vcard-temp">>} -> decode_vcard_LABEL(<<"vcard-temp">>, IgnoreEls, _el); {<<"ADR">>, <<"vcard-temp">>} -> decode_vcard_ADR(<<"vcard-temp">>, IgnoreEls, _el); {<<"N">>, <<"vcard-temp">>} -> decode_vcard_N(<<"vcard-temp">>, IgnoreEls, _el); {<<"CONFIDENTIAL">>, <<"vcard-temp">>} -> decode_vcard_CONFIDENTIAL(<<"vcard-temp">>, IgnoreEls, _el); {<<"PRIVATE">>, <<"vcard-temp">>} -> decode_vcard_PRIVATE(<<"vcard-temp">>, IgnoreEls, _el); {<<"PUBLIC">>, <<"vcard-temp">>} -> decode_vcard_PUBLIC(<<"vcard-temp">>, IgnoreEls, _el); {<<"EXTVAL">>, <<"vcard-temp">>} -> decode_vcard_EXTVAL(<<"vcard-temp">>, IgnoreEls, _el); {<<"TYPE">>, <<"vcard-temp">>} -> decode_vcard_TYPE(<<"vcard-temp">>, IgnoreEls, _el); {<<"DESC">>, <<"vcard-temp">>} -> decode_vcard_DESC(<<"vcard-temp">>, IgnoreEls, _el); {<<"URL">>, <<"vcard-temp">>} -> decode_vcard_URL(<<"vcard-temp">>, IgnoreEls, _el); {<<"UID">>, <<"vcard-temp">>} -> decode_vcard_UID(<<"vcard-temp">>, IgnoreEls, _el); {<<"SORT-STRING">>, <<"vcard-temp">>} -> decode_vcard_SORT_STRING(<<"vcard-temp">>, IgnoreEls, _el); {<<"REV">>, <<"vcard-temp">>} -> decode_vcard_REV(<<"vcard-temp">>, IgnoreEls, _el); {<<"PRODID">>, <<"vcard-temp">>} -> decode_vcard_PRODID(<<"vcard-temp">>, IgnoreEls, _el); {<<"NOTE">>, <<"vcard-temp">>} -> decode_vcard_NOTE(<<"vcard-temp">>, IgnoreEls, _el); {<<"KEYWORD">>, <<"vcard-temp">>} -> decode_vcard_KEYWORD(<<"vcard-temp">>, IgnoreEls, _el); {<<"ROLE">>, <<"vcard-temp">>} -> decode_vcard_ROLE(<<"vcard-temp">>, IgnoreEls, _el); {<<"TITLE">>, <<"vcard-temp">>} -> decode_vcard_TITLE(<<"vcard-temp">>, IgnoreEls, _el); {<<"TZ">>, <<"vcard-temp">>} -> decode_vcard_TZ(<<"vcard-temp">>, IgnoreEls, _el); {<<"MAILER">>, <<"vcard-temp">>} -> decode_vcard_MAILER(<<"vcard-temp">>, IgnoreEls, _el); {<<"JABBERID">>, <<"vcard-temp">>} -> decode_vcard_JABBERID(<<"vcard-temp">>, IgnoreEls, _el); {<<"BDAY">>, <<"vcard-temp">>} -> decode_vcard_BDAY(<<"vcard-temp">>, IgnoreEls, _el); {<<"NICKNAME">>, <<"vcard-temp">>} -> decode_vcard_NICKNAME(<<"vcard-temp">>, IgnoreEls, _el); {<<"FN">>, <<"vcard-temp">>} -> decode_vcard_FN(<<"vcard-temp">>, IgnoreEls, _el); {<<"VERSION">>, <<"vcard-temp">>} -> decode_vcard_VERSION(<<"vcard-temp">>, IgnoreEls, _el); {<<"CRED">>, <<"vcard-temp">>} -> decode_vcard_CRED(<<"vcard-temp">>, IgnoreEls, _el); {<<"PHONETIC">>, <<"vcard-temp">>} -> decode_vcard_PHONETIC(<<"vcard-temp">>, IgnoreEls, _el); {<<"ORGUNIT">>, <<"vcard-temp">>} -> decode_vcard_ORGUNIT(<<"vcard-temp">>, IgnoreEls, _el); {<<"ORGNAME">>, <<"vcard-temp">>} -> decode_vcard_ORGNAME(<<"vcard-temp">>, IgnoreEls, _el); {<<"LON">>, <<"vcard-temp">>} -> decode_vcard_LON(<<"vcard-temp">>, IgnoreEls, _el); {<<"LAT">>, <<"vcard-temp">>} -> decode_vcard_LAT(<<"vcard-temp">>, IgnoreEls, _el); {<<"USERID">>, <<"vcard-temp">>} -> decode_vcard_USERID(<<"vcard-temp">>, IgnoreEls, _el); {<<"NUMBER">>, <<"vcard-temp">>} -> decode_vcard_NUMBER(<<"vcard-temp">>, IgnoreEls, _el); {<<"LINE">>, <<"vcard-temp">>} -> decode_vcard_LINE(<<"vcard-temp">>, IgnoreEls, _el); {<<"CTRY">>, <<"vcard-temp">>} -> decode_vcard_CTRY(<<"vcard-temp">>, IgnoreEls, _el); {<<"PCODE">>, <<"vcard-temp">>} -> decode_vcard_PCODE(<<"vcard-temp">>, IgnoreEls, _el); {<<"REGION">>, <<"vcard-temp">>} -> decode_vcard_REGION(<<"vcard-temp">>, IgnoreEls, _el); {<<"LOCALITY">>, <<"vcard-temp">>} -> decode_vcard_LOCALITY(<<"vcard-temp">>, IgnoreEls, _el); {<<"STREET">>, <<"vcard-temp">>} -> decode_vcard_STREET(<<"vcard-temp">>, IgnoreEls, _el); {<<"EXTADD">>, <<"vcard-temp">>} -> decode_vcard_EXTADD(<<"vcard-temp">>, IgnoreEls, _el); {<<"POBOX">>, <<"vcard-temp">>} -> decode_vcard_POBOX(<<"vcard-temp">>, IgnoreEls, _el); {<<"SUFFIX">>, <<"vcard-temp">>} -> decode_vcard_SUFFIX(<<"vcard-temp">>, IgnoreEls, _el); {<<"PREFIX">>, <<"vcard-temp">>} -> decode_vcard_PREFIX(<<"vcard-temp">>, IgnoreEls, _el); {<<"MIDDLE">>, <<"vcard-temp">>} -> decode_vcard_MIDDLE(<<"vcard-temp">>, IgnoreEls, _el); {<<"GIVEN">>, <<"vcard-temp">>} -> decode_vcard_GIVEN(<<"vcard-temp">>, IgnoreEls, _el); {<<"FAMILY">>, <<"vcard-temp">>} -> decode_vcard_FAMILY(<<"vcard-temp">>, IgnoreEls, _el); {<<"X400">>, <<"vcard-temp">>} -> decode_vcard_X400(<<"vcard-temp">>, IgnoreEls, _el); {<<"INTERNET">>, <<"vcard-temp">>} -> decode_vcard_INTERNET(<<"vcard-temp">>, IgnoreEls, _el); {<<"PREF">>, <<"vcard-temp">>} -> decode_vcard_PREF(<<"vcard-temp">>, IgnoreEls, _el); {<<"INTL">>, <<"vcard-temp">>} -> decode_vcard_INTL(<<"vcard-temp">>, IgnoreEls, _el); {<<"DOM">>, <<"vcard-temp">>} -> decode_vcard_DOM(<<"vcard-temp">>, IgnoreEls, _el); {<<"PARCEL">>, <<"vcard-temp">>} -> decode_vcard_PARCEL(<<"vcard-temp">>, IgnoreEls, _el); {<<"POSTAL">>, <<"vcard-temp">>} -> decode_vcard_POSTAL(<<"vcard-temp">>, IgnoreEls, _el); {<<"PCS">>, <<"vcard-temp">>} -> decode_vcard_PCS(<<"vcard-temp">>, IgnoreEls, _el); {<<"ISDN">>, <<"vcard-temp">>} -> decode_vcard_ISDN(<<"vcard-temp">>, IgnoreEls, _el); {<<"MODEM">>, <<"vcard-temp">>} -> decode_vcard_MODEM(<<"vcard-temp">>, IgnoreEls, _el); {<<"BBS">>, <<"vcard-temp">>} -> decode_vcard_BBS(<<"vcard-temp">>, IgnoreEls, _el); {<<"VIDEO">>, <<"vcard-temp">>} -> decode_vcard_VIDEO(<<"vcard-temp">>, IgnoreEls, _el); {<<"CELL">>, <<"vcard-temp">>} -> decode_vcard_CELL(<<"vcard-temp">>, IgnoreEls, _el); {<<"MSG">>, <<"vcard-temp">>} -> decode_vcard_MSG(<<"vcard-temp">>, IgnoreEls, _el); {<<"PAGER">>, <<"vcard-temp">>} -> decode_vcard_PAGER(<<"vcard-temp">>, IgnoreEls, _el); {<<"FAX">>, <<"vcard-temp">>} -> decode_vcard_FAX(<<"vcard-temp">>, IgnoreEls, _el); {<<"VOICE">>, <<"vcard-temp">>} -> decode_vcard_VOICE(<<"vcard-temp">>, IgnoreEls, _el); {<<"WORK">>, <<"vcard-temp">>} -> decode_vcard_WORK(<<"vcard-temp">>, IgnoreEls, _el); {<<"HOME">>, <<"vcard-temp">>} -> decode_vcard_HOME(<<"vcard-temp">>, IgnoreEls, _el); {<<"stream:error">>, <<"http://etherx.jabber.org/streams">>} -> decode_stream_error(<<"http://etherx.jabber.org/streams">>, IgnoreEls, _el); {<<"unsupported-version">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_unsupported_version(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"unsupported-stanza-type">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_unsupported_stanza_type(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"unsupported-encoding">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_unsupported_encoding(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"undefined-condition">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_undefined_condition(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"system-shutdown">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_system_shutdown(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"see-other-host">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_see_other_host(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"restricted-xml">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_restricted_xml(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"resource-constraint">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_resource_constraint(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"reset">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_reset(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"remote-connection-failed">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_remote_connection_failed(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"policy-violation">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_policy_violation(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"not-well-formed">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_not_well_formed(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"not-authorized">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_not_authorized(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"invalid-xml">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_invalid_xml(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"invalid-namespace">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_invalid_namespace(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"invalid-id">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_invalid_id(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"invalid-from">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_invalid_from(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"internal-server-error">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_internal_server_error(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"improper-addressing">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_improper_addressing(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"host-unknown">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_host_unknown(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"host-gone">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_host_gone(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"connection-timeout">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_connection_timeout(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"conflict">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_conflict(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"bad-namespace-prefix">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_bad_namespace_prefix(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"bad-format">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_bad_format(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"text">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> decode_stream_error_text(<<"urn:ietf:params:xml:ns:xmpp-streams">>, IgnoreEls, _el); {<<"time">>, <<"urn:xmpp:time">>} -> decode_time(<<"urn:xmpp:time">>, IgnoreEls, _el); {<<"tzo">>, <<"urn:xmpp:time">>} -> decode_time_tzo(<<"urn:xmpp:time">>, IgnoreEls, _el); {<<"utc">>, <<"urn:xmpp:time">>} -> decode_time_utc(<<"urn:xmpp:time">>, IgnoreEls, _el); {<<"ping">>, <<"urn:xmpp:ping">>} -> decode_ping(<<"urn:xmpp:ping">>, IgnoreEls, _el); {<<"session">>, <<"urn:ietf:params:xml:ns:xmpp-session">>} -> decode_session(<<"urn:ietf:params:xml:ns:xmpp-session">>, IgnoreEls, _el); {<<"query">>, <<"jabber:iq:register">>} -> decode_register(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"key">>, <<"jabber:iq:register">>} -> decode_register_key(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"text">>, <<"jabber:iq:register">>} -> decode_register_text(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"misc">>, <<"jabber:iq:register">>} -> decode_register_misc(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"date">>, <<"jabber:iq:register">>} -> decode_register_date(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"url">>, <<"jabber:iq:register">>} -> decode_register_url(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"phone">>, <<"jabber:iq:register">>} -> decode_register_phone(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"zip">>, <<"jabber:iq:register">>} -> decode_register_zip(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"state">>, <<"jabber:iq:register">>} -> decode_register_state(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"city">>, <<"jabber:iq:register">>} -> decode_register_city(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"address">>, <<"jabber:iq:register">>} -> decode_register_address(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"email">>, <<"jabber:iq:register">>} -> decode_register_email(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"last">>, <<"jabber:iq:register">>} -> decode_register_last(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"first">>, <<"jabber:iq:register">>} -> decode_register_first(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"name">>, <<"jabber:iq:register">>} -> decode_register_name(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"password">>, <<"jabber:iq:register">>} -> decode_register_password(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"nick">>, <<"jabber:iq:register">>} -> decode_register_nick(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"username">>, <<"jabber:iq:register">>} -> decode_register_username(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"instructions">>, <<"jabber:iq:register">>} -> decode_register_instructions(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"remove">>, <<"jabber:iq:register">>} -> decode_register_remove(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"registered">>, <<"jabber:iq:register">>} -> decode_register_registered(<<"jabber:iq:register">>, IgnoreEls, _el); {<<"register">>, <<"http://jabber.org/features/iq-register">>} -> decode_feature_register(<<"http://jabber.org/features/iq-register">>, IgnoreEls, _el); {<<"c">>, <<"http://jabber.org/protocol/caps">>} -> decode_caps(<<"http://jabber.org/protocol/caps">>, IgnoreEls, _el); {<<"ack">>, <<"p1:ack">>} -> decode_p1_ack(<<"p1:ack">>, IgnoreEls, _el); {<<"rebind">>, <<"p1:rebind">>} -> decode_p1_rebind(<<"p1:rebind">>, IgnoreEls, _el); {<<"push">>, <<"p1:push">>} -> decode_p1_push(<<"p1:push">>, IgnoreEls, _el); {<<"stream:features">>, <<"http://etherx.jabber.org/streams">>} -> decode_stream_features(<<"http://etherx.jabber.org/streams">>, IgnoreEls, _el); {<<"compression">>, <<"http://jabber.org/features/compress">>} -> decode_compression(<<"http://jabber.org/features/compress">>, IgnoreEls, _el); {<<"method">>, <<"http://jabber.org/features/compress">>} -> decode_compression_method(<<"http://jabber.org/features/compress">>, IgnoreEls, _el); {<<"compressed">>, <<"http://jabber.org/protocol/compress">>} -> decode_compressed(<<"http://jabber.org/protocol/compress">>, IgnoreEls, _el); {<<"compress">>, <<"http://jabber.org/protocol/compress">>} -> decode_compress(<<"http://jabber.org/protocol/compress">>, IgnoreEls, _el); {<<"method">>, <<"http://jabber.org/protocol/compress">>} -> decode_compress_method(<<"http://jabber.org/protocol/compress">>, IgnoreEls, _el); {<<"failure">>, <<"http://jabber.org/protocol/compress">>} -> decode_compress_failure(<<"http://jabber.org/protocol/compress">>, IgnoreEls, _el); {<<"unsupported-method">>, <<"http://jabber.org/protocol/compress">>} -> decode_compress_failure_unsupported_method(<<"http://jabber.org/protocol/compress">>, IgnoreEls, _el); {<<"processing-failed">>, <<"http://jabber.org/protocol/compress">>} -> decode_compress_failure_processing_failed(<<"http://jabber.org/protocol/compress">>, IgnoreEls, _el); {<<"setup-failed">>, <<"http://jabber.org/protocol/compress">>} -> decode_compress_failure_setup_failed(<<"http://jabber.org/protocol/compress">>, IgnoreEls, _el); {<<"failure">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> decode_starttls_failure(<<"urn:ietf:params:xml:ns:xmpp-tls">>, IgnoreEls, _el); {<<"proceed">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> decode_starttls_proceed(<<"urn:ietf:params:xml:ns:xmpp-tls">>, IgnoreEls, _el); {<<"starttls">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> decode_starttls(<<"urn:ietf:params:xml:ns:xmpp-tls">>, IgnoreEls, _el); {<<"required">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> decode_starttls_required(<<"urn:ietf:params:xml:ns:xmpp-tls">>, IgnoreEls, _el); {<<"mechanisms">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_mechanisms(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"mechanism">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_mechanism(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"failure">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"temporary-auth-failure">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_temporary_auth_failure(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"not-authorized">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_not_authorized(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"mechanism-too-weak">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_mechanism_too_weak(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"malformed-request">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_malformed_request(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"invalid-mechanism">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_invalid_mechanism(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"invalid-authzid">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_invalid_authzid(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"incorrect-encoding">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_incorrect_encoding(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"encryption-required">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_encryption_required(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"credentials-expired">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_credentials_expired(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"account-disabled">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_account_disabled(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"aborted">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_aborted(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"text">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_failure_text(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"success">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_success(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"response">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_response(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"challenge">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_challenge(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"abort">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_abort(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"auth">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> decode_sasl_auth(<<"urn:ietf:params:xml:ns:xmpp-sasl">>, IgnoreEls, _el); {<<"bind">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>} -> decode_bind(<<"urn:ietf:params:xml:ns:xmpp-bind">>, IgnoreEls, _el); {<<"resource">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>} -> decode_bind_resource(<<"urn:ietf:params:xml:ns:xmpp-bind">>, IgnoreEls, _el); {<<"jid">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>} -> decode_bind_jid(<<"urn:ietf:params:xml:ns:xmpp-bind">>, IgnoreEls, _el); {<<"error">>, <<"jabber:client">>} -> decode_error(<<"jabber:client">>, IgnoreEls, _el); {<<"text">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_text(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"unexpected-request">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_unexpected_request(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"undefined-condition">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_undefined_condition(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"subscription-required">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_subscription_required(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"service-unavailable">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_service_unavailable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"resource-constraint">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_resource_constraint(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"remote-server-timeout">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_remote_server_timeout(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"remote-server-not-found">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_remote_server_not_found(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"registration-required">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_registration_required(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"redirect">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_redirect(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"recipient-unavailable">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_recipient_unavailable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"policy-violation">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_policy_violation(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"not-authorized">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_not_authorized(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"not-allowed">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_not_allowed(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"not-acceptable">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_not_acceptable(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"jid-malformed">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_jid_malformed(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"item-not-found">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_item_not_found(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"internal-server-error">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_internal_server_error(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"gone">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_gone(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"forbidden">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_forbidden(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"feature-not-implemented">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_feature_not_implemented(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"conflict">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_conflict(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"bad-request">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> decode_error_bad_request(<<"urn:ietf:params:xml:ns:xmpp-stanzas">>, IgnoreEls, _el); {<<"presence">>, <<"jabber:client">>} -> decode_presence(<<"jabber:client">>, IgnoreEls, _el); {<<"priority">>, <<"jabber:client">>} -> decode_presence_priority(<<"jabber:client">>, IgnoreEls, _el); {<<"status">>, <<"jabber:client">>} -> decode_presence_status(<<"jabber:client">>, IgnoreEls, _el); {<<"show">>, <<"jabber:client">>} -> decode_presence_show(<<"jabber:client">>, IgnoreEls, _el); {<<"message">>, <<"jabber:client">>} -> decode_message(<<"jabber:client">>, IgnoreEls, _el); {<<"thread">>, <<"jabber:client">>} -> decode_message_thread(<<"jabber:client">>, IgnoreEls, _el); {<<"body">>, <<"jabber:client">>} -> decode_message_body(<<"jabber:client">>, IgnoreEls, _el); {<<"subject">>, <<"jabber:client">>} -> decode_message_subject(<<"jabber:client">>, IgnoreEls, _el); {<<"iq">>, <<"jabber:client">>} -> decode_iq(<<"jabber:client">>, IgnoreEls, _el); {<<"query">>, <<"http://jabber.org/protocol/stats">>} -> decode_stats(<<"http://jabber.org/protocol/stats">>, IgnoreEls, _el); {<<"stat">>, <<"http://jabber.org/protocol/stats">>} -> decode_stat(<<"http://jabber.org/protocol/stats">>, IgnoreEls, _el); {<<"error">>, <<"http://jabber.org/protocol/stats">>} -> decode_stat_error(<<"http://jabber.org/protocol/stats">>, IgnoreEls, _el); {<<"storage">>, <<"storage:bookmarks">>} -> decode_bookmarks_storage(<<"storage:bookmarks">>, IgnoreEls, _el); {<<"url">>, <<"storage:bookmarks">>} -> decode_bookmark_url(<<"storage:bookmarks">>, IgnoreEls, _el); {<<"conference">>, <<"storage:bookmarks">>} -> decode_bookmark_conference(<<"storage:bookmarks">>, IgnoreEls, _el); {<<"password">>, <<"storage:bookmarks">>} -> decode_conference_password(<<"storage:bookmarks">>, IgnoreEls, _el); {<<"nick">>, <<"storage:bookmarks">>} -> decode_conference_nick(<<"storage:bookmarks">>, IgnoreEls, _el); {<<"query">>, <<"jabber:iq:private">>} -> decode_private(<<"jabber:iq:private">>, IgnoreEls, _el); {<<"query">>, <<"http://jabber.org/protocol/disco#items">>} -> decode_disco_items(<<"http://jabber.org/protocol/disco#items">>, IgnoreEls, _el); {<<"item">>, <<"http://jabber.org/protocol/disco#items">>} -> decode_disco_item(<<"http://jabber.org/protocol/disco#items">>, IgnoreEls, _el); {<<"query">>, <<"http://jabber.org/protocol/disco#info">>} -> decode_disco_info(<<"http://jabber.org/protocol/disco#info">>, IgnoreEls, _el); {<<"feature">>, <<"http://jabber.org/protocol/disco#info">>} -> decode_disco_feature(<<"http://jabber.org/protocol/disco#info">>, IgnoreEls, _el); {<<"identity">>, <<"http://jabber.org/protocol/disco#info">>} -> decode_disco_identity(<<"http://jabber.org/protocol/disco#info">>, IgnoreEls, _el); {<<"blocklist">>, <<"urn:xmpp:blocking">>} -> decode_block_list(<<"urn:xmpp:blocking">>, IgnoreEls, _el); {<<"unblock">>, <<"urn:xmpp:blocking">>} -> decode_unblock(<<"urn:xmpp:blocking">>, IgnoreEls, _el); {<<"block">>, <<"urn:xmpp:blocking">>} -> decode_block(<<"urn:xmpp:blocking">>, IgnoreEls, _el); {<<"item">>, <<"urn:xmpp:blocking">>} -> decode_block_item(<<"urn:xmpp:blocking">>, IgnoreEls, _el); {<<"query">>, <<"jabber:iq:privacy">>} -> decode_privacy(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"active">>, <<"jabber:iq:privacy">>} -> decode_privacy_active_list(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"default">>, <<"jabber:iq:privacy">>} -> decode_privacy_default_list(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"list">>, <<"jabber:iq:privacy">>} -> decode_privacy_list(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"item">>, <<"jabber:iq:privacy">>} -> decode_privacy_item(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"presence-out">>, <<"jabber:iq:privacy">>} -> decode_privacy_presence_out(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"presence-in">>, <<"jabber:iq:privacy">>} -> decode_privacy_presence_in(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"iq">>, <<"jabber:iq:privacy">>} -> decode_privacy_iq(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"message">>, <<"jabber:iq:privacy">>} -> decode_privacy_message(<<"jabber:iq:privacy">>, IgnoreEls, _el); {<<"query">>, <<"jabber:iq:roster">>} -> decode_roster(<<"jabber:iq:roster">>, IgnoreEls, _el); {<<"item">>, <<"jabber:iq:roster">>} -> decode_roster_item(<<"jabber:iq:roster">>, IgnoreEls, _el); {<<"group">>, <<"jabber:iq:roster">>} -> decode_roster_group(<<"jabber:iq:roster">>, IgnoreEls, _el); {<<"query">>, <<"jabber:iq:version">>} -> decode_version(<<"jabber:iq:version">>, IgnoreEls, _el); {<<"os">>, <<"jabber:iq:version">>} -> decode_version_os(<<"jabber:iq:version">>, IgnoreEls, _el); {<<"version">>, <<"jabber:iq:version">>} -> decode_version_ver(<<"jabber:iq:version">>, IgnoreEls, _el); {<<"name">>, <<"jabber:iq:version">>} -> decode_version_name(<<"jabber:iq:version">>, IgnoreEls, _el); {<<"query">>, <<"jabber:iq:last">>} -> decode_last(<<"jabber:iq:last">>, IgnoreEls, _el); {_name, _xmlns} -> erlang:error({xmpp_codec, {unknown_tag, _name, _xmlns}}) end. is_known_tag({xmlel, _name, _attrs, _} = _el) -> case {_name, get_attr(<<"xmlns">>, _attrs)} of {<<"failed">>, <<"urn:xmpp:sm:2">>} -> true; {<<"failed">>, <<"urn:xmpp:sm:3">>} -> true; {<<"a">>, <<"urn:xmpp:sm:2">>} -> true; {<<"a">>, <<"urn:xmpp:sm:3">>} -> true; {<<"r">>, <<"urn:xmpp:sm:2">>} -> true; {<<"r">>, <<"urn:xmpp:sm:3">>} -> true; {<<"resumed">>, <<"urn:xmpp:sm:2">>} -> true; {<<"resumed">>, <<"urn:xmpp:sm:3">>} -> true; {<<"resume">>, <<"urn:xmpp:sm:2">>} -> true; {<<"resume">>, <<"urn:xmpp:sm:3">>} -> true; {<<"enabled">>, <<"urn:xmpp:sm:2">>} -> true; {<<"enabled">>, <<"urn:xmpp:sm:3">>} -> true; {<<"enable">>, <<"urn:xmpp:sm:2">>} -> true; {<<"enable">>, <<"urn:xmpp:sm:3">>} -> true; {<<"sm">>, <<"urn:xmpp:sm:2">>} -> true; {<<"sm">>, <<"urn:xmpp:sm:3">>} -> true; {<<"inactive">>, <<"urn:xmpp:csi:0">>} -> true; {<<"active">>, <<"urn:xmpp:csi:0">>} -> true; {<<"csi">>, <<"urn:xmpp:csi:0">>} -> true; {<<"sent">>, <<"urn:xmpp:carbons:2">>} -> true; {<<"received">>, <<"urn:xmpp:carbons:2">>} -> true; {<<"private">>, <<"urn:xmpp:carbons:2">>} -> true; {<<"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">>} -> true; {<<"reason">>, <<"http://jabber.org/protocol/muc#admin">>} -> true; {<<"continue">>, <<"http://jabber.org/protocol/muc#admin">>} -> true; {<<"actor">>, <<"http://jabber.org/protocol/muc#admin">>} -> true; {<<"item">>, <<"http://jabber.org/protocol/muc#admin">>} -> true; {<<"query">>, <<"http://jabber.org/protocol/muc#owner">>} -> true; {<<"destroy">>, <<"http://jabber.org/protocol/muc#owner">>} -> true; {<<"reason">>, <<"http://jabber.org/protocol/muc#owner">>} -> true; {<<"password">>, <<"http://jabber.org/protocol/muc#owner">>} -> true; {<<"x">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"item">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"status">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"continue">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"actor">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"invite">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"destroy">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"decline">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"reason">>, <<"http://jabber.org/protocol/muc#user">>} -> true; {<<"history">>, <<"http://jabber.org/protocol/muc">>} -> true; {<<"query">>, <<"http://jabber.org/protocol/bytestreams">>} -> true; {<<"activate">>, <<"http://jabber.org/protocol/bytestreams">>} -> true; {<<"streamhost-used">>, <<"http://jabber.org/protocol/bytestreams">>} -> true; {<<"streamhost">>, <<"http://jabber.org/protocol/bytestreams">>} -> true; {<<"delay">>, <<"urn:xmpp:delay">>} -> true; {<<"paused">>, <<"http://jabber.org/protocol/chatstates">>} -> true; {<<"inactive">>, <<"http://jabber.org/protocol/chatstates">>} -> true; {<<"gone">>, <<"http://jabber.org/protocol/chatstates">>} -> true; {<<"composing">>, <<"http://jabber.org/protocol/chatstates">>} -> true; {<<"active">>, <<"http://jabber.org/protocol/chatstates">>} -> true; {<<"headers">>, <<"http://jabber.org/protocol/shim">>} -> true; {<<"header">>, <<"http://jabber.org/protocol/shim">>} -> true; {<<"pubsub">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"retract">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"options">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"publish">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"unsubscribe">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"subscribe">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"affiliations">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"subscriptions">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"event">>, <<"http://jabber.org/protocol/pubsub#event">>} -> true; {<<"items">>, <<"http://jabber.org/protocol/pubsub#event">>} -> true; {<<"item">>, <<"http://jabber.org/protocol/pubsub#event">>} -> true; {<<"retract">>, <<"http://jabber.org/protocol/pubsub#event">>} -> true; {<<"items">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"item">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"affiliation">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"subscription">>, <<"http://jabber.org/protocol/pubsub">>} -> true; {<<"x">>, <<"jabber:x:data">>} -> true; {<<"item">>, <<"jabber:x:data">>} -> true; {<<"reported">>, <<"jabber:x:data">>} -> true; {<<"title">>, <<"jabber:x:data">>} -> true; {<<"instructions">>, <<"jabber:x:data">>} -> true; {<<"field">>, <<"jabber:x:data">>} -> true; {<<"option">>, <<"jabber:x:data">>} -> true; {<<"value">>, <<"jabber:x:data">>} -> true; {<<"desc">>, <<"jabber:x:data">>} -> true; {<<"required">>, <<"jabber:x:data">>} -> true; {<<"x">>, <<"vcard-temp:x:update">>} -> true; {<<"photo">>, <<"vcard-temp:x:update">>} -> true; {<<"vCard">>, <<"vcard-temp">>} -> true; {<<"CLASS">>, <<"vcard-temp">>} -> true; {<<"CATEGORIES">>, <<"vcard-temp">>} -> true; {<<"KEY">>, <<"vcard-temp">>} -> true; {<<"SOUND">>, <<"vcard-temp">>} -> true; {<<"ORG">>, <<"vcard-temp">>} -> true; {<<"PHOTO">>, <<"vcard-temp">>} -> true; {<<"LOGO">>, <<"vcard-temp">>} -> true; {<<"BINVAL">>, <<"vcard-temp">>} -> true; {<<"GEO">>, <<"vcard-temp">>} -> true; {<<"EMAIL">>, <<"vcard-temp">>} -> true; {<<"TEL">>, <<"vcard-temp">>} -> true; {<<"LABEL">>, <<"vcard-temp">>} -> true; {<<"ADR">>, <<"vcard-temp">>} -> true; {<<"N">>, <<"vcard-temp">>} -> true; {<<"CONFIDENTIAL">>, <<"vcard-temp">>} -> true; {<<"PRIVATE">>, <<"vcard-temp">>} -> true; {<<"PUBLIC">>, <<"vcard-temp">>} -> true; {<<"EXTVAL">>, <<"vcard-temp">>} -> true; {<<"TYPE">>, <<"vcard-temp">>} -> true; {<<"DESC">>, <<"vcard-temp">>} -> true; {<<"URL">>, <<"vcard-temp">>} -> true; {<<"UID">>, <<"vcard-temp">>} -> true; {<<"SORT-STRING">>, <<"vcard-temp">>} -> true; {<<"REV">>, <<"vcard-temp">>} -> true; {<<"PRODID">>, <<"vcard-temp">>} -> true; {<<"NOTE">>, <<"vcard-temp">>} -> true; {<<"KEYWORD">>, <<"vcard-temp">>} -> true; {<<"ROLE">>, <<"vcard-temp">>} -> true; {<<"TITLE">>, <<"vcard-temp">>} -> true; {<<"TZ">>, <<"vcard-temp">>} -> true; {<<"MAILER">>, <<"vcard-temp">>} -> true; {<<"JABBERID">>, <<"vcard-temp">>} -> true; {<<"BDAY">>, <<"vcard-temp">>} -> true; {<<"NICKNAME">>, <<"vcard-temp">>} -> true; {<<"FN">>, <<"vcard-temp">>} -> true; {<<"VERSION">>, <<"vcard-temp">>} -> true; {<<"CRED">>, <<"vcard-temp">>} -> true; {<<"PHONETIC">>, <<"vcard-temp">>} -> true; {<<"ORGUNIT">>, <<"vcard-temp">>} -> true; {<<"ORGNAME">>, <<"vcard-temp">>} -> true; {<<"LON">>, <<"vcard-temp">>} -> true; {<<"LAT">>, <<"vcard-temp">>} -> true; {<<"USERID">>, <<"vcard-temp">>} -> true; {<<"NUMBER">>, <<"vcard-temp">>} -> true; {<<"LINE">>, <<"vcard-temp">>} -> true; {<<"CTRY">>, <<"vcard-temp">>} -> true; {<<"PCODE">>, <<"vcard-temp">>} -> true; {<<"REGION">>, <<"vcard-temp">>} -> true; {<<"LOCALITY">>, <<"vcard-temp">>} -> true; {<<"STREET">>, <<"vcard-temp">>} -> true; {<<"EXTADD">>, <<"vcard-temp">>} -> true; {<<"POBOX">>, <<"vcard-temp">>} -> true; {<<"SUFFIX">>, <<"vcard-temp">>} -> true; {<<"PREFIX">>, <<"vcard-temp">>} -> true; {<<"MIDDLE">>, <<"vcard-temp">>} -> true; {<<"GIVEN">>, <<"vcard-temp">>} -> true; {<<"FAMILY">>, <<"vcard-temp">>} -> true; {<<"X400">>, <<"vcard-temp">>} -> true; {<<"INTERNET">>, <<"vcard-temp">>} -> true; {<<"PREF">>, <<"vcard-temp">>} -> true; {<<"INTL">>, <<"vcard-temp">>} -> true; {<<"DOM">>, <<"vcard-temp">>} -> true; {<<"PARCEL">>, <<"vcard-temp">>} -> true; {<<"POSTAL">>, <<"vcard-temp">>} -> true; {<<"PCS">>, <<"vcard-temp">>} -> true; {<<"ISDN">>, <<"vcard-temp">>} -> true; {<<"MODEM">>, <<"vcard-temp">>} -> true; {<<"BBS">>, <<"vcard-temp">>} -> true; {<<"VIDEO">>, <<"vcard-temp">>} -> true; {<<"CELL">>, <<"vcard-temp">>} -> true; {<<"MSG">>, <<"vcard-temp">>} -> true; {<<"PAGER">>, <<"vcard-temp">>} -> true; {<<"FAX">>, <<"vcard-temp">>} -> true; {<<"VOICE">>, <<"vcard-temp">>} -> true; {<<"WORK">>, <<"vcard-temp">>} -> true; {<<"HOME">>, <<"vcard-temp">>} -> true; {<<"stream:error">>, <<"http://etherx.jabber.org/streams">>} -> true; {<<"unsupported-version">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"unsupported-stanza-type">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"unsupported-encoding">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"undefined-condition">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"system-shutdown">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"see-other-host">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"restricted-xml">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"resource-constraint">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"reset">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"remote-connection-failed">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"policy-violation">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"not-well-formed">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"not-authorized">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"invalid-xml">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"invalid-namespace">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"invalid-id">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"invalid-from">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"internal-server-error">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"improper-addressing">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"host-unknown">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"host-gone">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"connection-timeout">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"conflict">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"bad-namespace-prefix">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"bad-format">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"text">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>} -> true; {<<"time">>, <<"urn:xmpp:time">>} -> true; {<<"tzo">>, <<"urn:xmpp:time">>} -> true; {<<"utc">>, <<"urn:xmpp:time">>} -> true; {<<"ping">>, <<"urn:xmpp:ping">>} -> true; {<<"session">>, <<"urn:ietf:params:xml:ns:xmpp-session">>} -> true; {<<"query">>, <<"jabber:iq:register">>} -> true; {<<"key">>, <<"jabber:iq:register">>} -> true; {<<"text">>, <<"jabber:iq:register">>} -> true; {<<"misc">>, <<"jabber:iq:register">>} -> true; {<<"date">>, <<"jabber:iq:register">>} -> true; {<<"url">>, <<"jabber:iq:register">>} -> true; {<<"phone">>, <<"jabber:iq:register">>} -> true; {<<"zip">>, <<"jabber:iq:register">>} -> true; {<<"state">>, <<"jabber:iq:register">>} -> true; {<<"city">>, <<"jabber:iq:register">>} -> true; {<<"address">>, <<"jabber:iq:register">>} -> true; {<<"email">>, <<"jabber:iq:register">>} -> true; {<<"last">>, <<"jabber:iq:register">>} -> true; {<<"first">>, <<"jabber:iq:register">>} -> true; {<<"name">>, <<"jabber:iq:register">>} -> true; {<<"password">>, <<"jabber:iq:register">>} -> true; {<<"nick">>, <<"jabber:iq:register">>} -> true; {<<"username">>, <<"jabber:iq:register">>} -> true; {<<"instructions">>, <<"jabber:iq:register">>} -> true; {<<"remove">>, <<"jabber:iq:register">>} -> true; {<<"registered">>, <<"jabber:iq:register">>} -> true; {<<"register">>, <<"http://jabber.org/features/iq-register">>} -> true; {<<"c">>, <<"http://jabber.org/protocol/caps">>} -> true; {<<"ack">>, <<"p1:ack">>} -> true; {<<"rebind">>, <<"p1:rebind">>} -> true; {<<"push">>, <<"p1:push">>} -> true; {<<"stream:features">>, <<"http://etherx.jabber.org/streams">>} -> true; {<<"compression">>, <<"http://jabber.org/features/compress">>} -> true; {<<"method">>, <<"http://jabber.org/features/compress">>} -> true; {<<"compressed">>, <<"http://jabber.org/protocol/compress">>} -> true; {<<"compress">>, <<"http://jabber.org/protocol/compress">>} -> true; {<<"method">>, <<"http://jabber.org/protocol/compress">>} -> true; {<<"failure">>, <<"http://jabber.org/protocol/compress">>} -> true; {<<"unsupported-method">>, <<"http://jabber.org/protocol/compress">>} -> true; {<<"processing-failed">>, <<"http://jabber.org/protocol/compress">>} -> true; {<<"setup-failed">>, <<"http://jabber.org/protocol/compress">>} -> true; {<<"failure">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> true; {<<"proceed">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> true; {<<"starttls">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> true; {<<"required">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> true; {<<"mechanisms">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"mechanism">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"failure">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"temporary-auth-failure">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"not-authorized">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"mechanism-too-weak">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"malformed-request">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"invalid-mechanism">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"invalid-authzid">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"incorrect-encoding">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"encryption-required">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"credentials-expired">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"account-disabled">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"aborted">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"text">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"success">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"response">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"challenge">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"abort">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"auth">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} -> true; {<<"bind">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>} -> true; {<<"resource">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>} -> true; {<<"jid">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>} -> true; {<<"error">>, <<"jabber:client">>} -> true; {<<"text">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"unexpected-request">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"undefined-condition">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"subscription-required">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"service-unavailable">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"resource-constraint">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"remote-server-timeout">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"remote-server-not-found">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"registration-required">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"redirect">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"recipient-unavailable">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"policy-violation">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"not-authorized">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"not-allowed">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"not-acceptable">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"jid-malformed">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"item-not-found">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"internal-server-error">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"gone">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"forbidden">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"feature-not-implemented">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"conflict">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"bad-request">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>} -> true; {<<"presence">>, <<"jabber:client">>} -> true; {<<"priority">>, <<"jabber:client">>} -> true; {<<"status">>, <<"jabber:client">>} -> true; {<<"show">>, <<"jabber:client">>} -> true; {<<"message">>, <<"jabber:client">>} -> true; {<<"thread">>, <<"jabber:client">>} -> true; {<<"body">>, <<"jabber:client">>} -> true; {<<"subject">>, <<"jabber:client">>} -> true; {<<"iq">>, <<"jabber:client">>} -> true; {<<"query">>, <<"http://jabber.org/protocol/stats">>} -> true; {<<"stat">>, <<"http://jabber.org/protocol/stats">>} -> true; {<<"error">>, <<"http://jabber.org/protocol/stats">>} -> true; {<<"storage">>, <<"storage:bookmarks">>} -> true; {<<"url">>, <<"storage:bookmarks">>} -> true; {<<"conference">>, <<"storage:bookmarks">>} -> true; {<<"password">>, <<"storage:bookmarks">>} -> true; {<<"nick">>, <<"storage:bookmarks">>} -> true; {<<"query">>, <<"jabber:iq:private">>} -> true; {<<"query">>, <<"http://jabber.org/protocol/disco#items">>} -> true; {<<"item">>, <<"http://jabber.org/protocol/disco#items">>} -> true; {<<"query">>, <<"http://jabber.org/protocol/disco#info">>} -> true; {<<"feature">>, <<"http://jabber.org/protocol/disco#info">>} -> true; {<<"identity">>, <<"http://jabber.org/protocol/disco#info">>} -> true; {<<"blocklist">>, <<"urn:xmpp:blocking">>} -> true; {<<"unblock">>, <<"urn:xmpp:blocking">>} -> true; {<<"block">>, <<"urn:xmpp:blocking">>} -> true; {<<"item">>, <<"urn:xmpp:blocking">>} -> true; {<<"query">>, <<"jabber:iq:privacy">>} -> true; {<<"active">>, <<"jabber:iq:privacy">>} -> true; {<<"default">>, <<"jabber:iq:privacy">>} -> true; {<<"list">>, <<"jabber:iq:privacy">>} -> true; {<<"item">>, <<"jabber:iq:privacy">>} -> true; {<<"presence-out">>, <<"jabber:iq:privacy">>} -> true; {<<"presence-in">>, <<"jabber:iq:privacy">>} -> true; {<<"iq">>, <<"jabber:iq:privacy">>} -> true; {<<"message">>, <<"jabber:iq:privacy">>} -> true; {<<"query">>, <<"jabber:iq:roster">>} -> true; {<<"item">>, <<"jabber:iq:roster">>} -> true; {<<"group">>, <<"jabber:iq:roster">>} -> true; {<<"query">>, <<"jabber:iq:version">>} -> true; {<<"os">>, <<"jabber:iq:version">>} -> true; {<<"version">>, <<"jabber:iq:version">>} -> true; {<<"name">>, <<"jabber:iq:version">>} -> true; {<<"query">>, <<"jabber:iq:last">>} -> true; _ -> false end. encode({xmlel, _, _, _} = El) -> El; encode({last, _, _} = Query) -> encode_last(Query, [{<<"xmlns">>, <<"jabber:iq:last">>}]); encode({version, _, _, _} = Query) -> encode_version(Query, [{<<"xmlns">>, <<"jabber:iq:version">>}]); encode({roster_item, _, _, _, _, _} = Item) -> encode_roster_item(Item, [{<<"xmlns">>, <<"jabber:iq:roster">>}]); encode({roster, _, _} = Query) -> encode_roster(Query, [{<<"xmlns">>, <<"jabber:iq:roster">>}]); encode({privacy_item, _, _, _, _, _} = Item) -> encode_privacy_item(Item, [{<<"xmlns">>, <<"jabber:iq:privacy">>}]); encode({privacy_list, _, _} = List) -> encode_privacy_list(List, [{<<"xmlns">>, <<"jabber:iq:privacy">>}]); encode({privacy, _, _, _} = Query) -> encode_privacy(Query, [{<<"xmlns">>, <<"jabber:iq:privacy">>}]); encode({block, _} = Block) -> encode_block(Block, [{<<"xmlns">>, <<"urn:xmpp:blocking">>}]); encode({unblock, _} = Unblock) -> encode_unblock(Unblock, [{<<"xmlns">>, <<"urn:xmpp:blocking">>}]); encode({block_list} = Blocklist) -> encode_block_list(Blocklist, [{<<"xmlns">>, <<"urn:xmpp:blocking">>}]); encode({identity, _, _, _, _} = Identity) -> encode_disco_identity(Identity, [{<<"xmlns">>, <<"http://jabber.org/protocol/disco#info">>}]); encode({disco_info, _, _, _, _} = Query) -> encode_disco_info(Query, [{<<"xmlns">>, <<"http://jabber.org/protocol/disco#info">>}]); encode({disco_item, _, _, _} = Item) -> encode_disco_item(Item, [{<<"xmlns">>, <<"http://jabber.org/protocol/disco#items">>}]); encode({disco_items, _, _} = Query) -> encode_disco_items(Query, [{<<"xmlns">>, <<"http://jabber.org/protocol/disco#items">>}]); encode({private, _} = Query) -> encode_private(Query, [{<<"xmlns">>, <<"jabber:iq:private">>}]); encode({bookmark_conference, _, _, _, _, _} = Conference) -> encode_bookmark_conference(Conference, [{<<"xmlns">>, <<"storage:bookmarks">>}]); encode({bookmark_url, _, _} = Url) -> encode_bookmark_url(Url, [{<<"xmlns">>, <<"storage:bookmarks">>}]); encode({bookmark_storage, _, _} = Storage) -> encode_bookmarks_storage(Storage, [{<<"xmlns">>, <<"storage:bookmarks">>}]); encode({stat, _, _, _, _} = Stat) -> encode_stat(Stat, [{<<"xmlns">>, <<"http://jabber.org/protocol/stats">>}]); encode({stats, _} = Query) -> encode_stats(Query, [{<<"xmlns">>, <<"http://jabber.org/protocol/stats">>}]); encode({iq, _, _, _, _, _, _, _} = Iq) -> encode_iq(Iq, [{<<"xmlns">>, <<"jabber:client">>}]); encode({message, _, _, _, _, _, _, _, _, _, _} = Message) -> encode_message(Message, [{<<"xmlns">>, <<"jabber:client">>}]); encode({presence, _, _, _, _, _, _, _, _, _, _} = Presence) -> encode_presence(Presence, [{<<"xmlns">>, <<"jabber:client">>}]); encode({gone, _} = Gone) -> encode_error_gone(Gone, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]); encode({redirect, _} = Redirect) -> encode_error_redirect(Redirect, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]); encode({error, _, _, _, _} = Error) -> encode_error(Error, [{<<"xmlns">>, <<"jabber:client">>}]); encode({bind, _, _} = Bind) -> encode_bind(Bind, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-bind">>}]); encode({sasl_auth, _, _} = Auth) -> encode_sasl_auth(Auth, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]); encode({sasl_abort} = Abort) -> encode_sasl_abort(Abort, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]); encode({sasl_challenge, _} = Challenge) -> encode_sasl_challenge(Challenge, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]); encode({sasl_response, _} = Response) -> encode_sasl_response(Response, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]); encode({sasl_success, _} = Success) -> encode_sasl_success(Success, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]); encode({sasl_failure, _, _} = Failure) -> encode_sasl_failure(Failure, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]); encode({sasl_mechanisms, _} = Mechanisms) -> encode_sasl_mechanisms(Mechanisms, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]); encode({starttls, _} = Starttls) -> encode_starttls(Starttls, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>}]); encode({starttls_proceed} = Proceed) -> encode_starttls_proceed(Proceed, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>}]); encode({starttls_failure} = Failure) -> encode_starttls_failure(Failure, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>}]); encode({compress_failure, _} = Failure) -> encode_compress_failure(Failure, [{<<"xmlns">>, <<"http://jabber.org/protocol/compress">>}]); encode({compress, _} = Compress) -> encode_compress(Compress, [{<<"xmlns">>, <<"http://jabber.org/protocol/compress">>}]); encode({compressed} = Compressed) -> encode_compressed(Compressed, [{<<"xmlns">>, <<"http://jabber.org/protocol/compress">>}]); encode({compression, _} = Compression) -> encode_compression(Compression, [{<<"xmlns">>, <<"http://jabber.org/features/compress">>}]); encode({stream_features, _} = Stream_features) -> encode_stream_features(Stream_features, [{<<"xmlns">>, <<"http://etherx.jabber.org/streams">>}]); encode({p1_push} = Push) -> encode_p1_push(Push, [{<<"xmlns">>, <<"p1:push">>}]); encode({p1_rebind} = Rebind) -> encode_p1_rebind(Rebind, [{<<"xmlns">>, <<"p1:rebind">>}]); encode({p1_ack} = Ack) -> encode_p1_ack(Ack, [{<<"xmlns">>, <<"p1:ack">>}]); encode({caps, _, _, _} = C) -> encode_caps(C, [{<<"xmlns">>, <<"http://jabber.org/protocol/caps">>}]); encode({feature_register} = Register) -> encode_feature_register(Register, [{<<"xmlns">>, <<"http://jabber.org/features/iq-register">>}]); encode({register, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Query) -> encode_register(Query, [{<<"xmlns">>, <<"jabber:iq:register">>}]); encode({session} = Session) -> encode_session(Session, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-session">>}]); encode({ping} = Ping) -> encode_ping(Ping, [{<<"xmlns">>, <<"urn:xmpp:ping">>}]); encode({time, _, _} = Time) -> encode_time(Time, [{<<"xmlns">>, <<"urn:xmpp:time">>}]); encode({text, _, _} = Text) -> encode_stream_error_text(Text, []); encode({'see-other-host', _} = See_other_host) -> encode_stream_error_see_other_host(See_other_host, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]); encode({stream_error, _, _} = Stream_error) -> encode_stream_error(Stream_error, [{<<"xmlns">>, <<"http://etherx.jabber.org/streams">>}]); encode({vcard_name, _, _, _, _, _} = N) -> encode_vcard_N(N, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_adr, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Adr) -> encode_vcard_ADR(Adr, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_label, _, _, _, _, _, _, _, _} = Label) -> encode_vcard_LABEL(Label, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_tel, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Tel) -> encode_vcard_TEL(Tel, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_email, _, _, _, _, _, _} = Email) -> encode_vcard_EMAIL(Email, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_geo, _, _} = Geo) -> encode_vcard_GEO(Geo, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_logo, _, _, _} = Logo) -> encode_vcard_LOGO(Logo, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_photo, _, _, _} = Photo) -> encode_vcard_PHOTO(Photo, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_org, _, _} = Org) -> encode_vcard_ORG(Org, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_sound, _, _, _} = Sound) -> encode_vcard_SOUND(Sound, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_key, _, _} = Key) -> encode_vcard_KEY(Key, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Vcard) -> encode_vcard(Vcard, [{<<"xmlns">>, <<"vcard-temp">>}]); encode({vcard_xupdate, _} = X) -> encode_vcard_xupdate(X, [{<<"xmlns">>, <<"vcard-temp:x:update">>}]); encode({xdata_field, _, _, _, _, _, _, _} = Field) -> encode_xdata_field(Field, [{<<"xmlns">>, <<"jabber:x:data">>}]); encode({xdata, _, _, _, _, _, _} = X) -> encode_xdata(X, [{<<"xmlns">>, <<"jabber:x:data">>}]); encode({pubsub_subscription, _, _, _, _} = Subscription) -> encode_pubsub_subscription(Subscription, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub_affiliation, _, _} = Affiliation) -> encode_pubsub_affiliation(Affiliation, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub_item, _, _} = Item) -> encode_pubsub_item(Item, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub_items, _, _, _, _} = Items) -> encode_pubsub_items(Items, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub_event_item, _, _, _} = Item) -> encode_pubsub_event_item(Item, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub#event">>}]); encode({pubsub_event_items, _, _, _} = Items) -> encode_pubsub_event_items(Items, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub#event">>}]); encode({pubsub_event, _} = Event) -> encode_pubsub_event(Event, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub#event">>}]); encode({pubsub_subscribe, _, _} = Subscribe) -> encode_pubsub_subscribe(Subscribe, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub_unsubscribe, _, _, _} = Unsubscribe) -> encode_pubsub_unsubscribe(Unsubscribe, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub_publish, _, _} = Publish) -> encode_pubsub_publish(Publish, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub_options, _, _, _, _} = Options) -> encode_pubsub_options(Options, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub_retract, _, _, _} = Retract) -> encode_pubsub_retract(Retract, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({pubsub, _, _, _, _, _, _, _, _} = Pubsub) -> encode_pubsub(Pubsub, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); encode({shim, _} = Headers) -> encode_shim_headers(Headers, [{<<"xmlns">>, <<"http://jabber.org/protocol/shim">>}]); encode({chatstate, active} = Active) -> encode_chatstate_active(Active, [{<<"xmlns">>, <<"http://jabber.org/protocol/chatstates">>}]); encode({chatstate, composing} = Composing) -> encode_chatstate_composing(Composing, [{<<"xmlns">>, <<"http://jabber.org/protocol/chatstates">>}]); encode({chatstate, gone} = Gone) -> encode_chatstate_gone(Gone, [{<<"xmlns">>, <<"http://jabber.org/protocol/chatstates">>}]); encode({chatstate, inactive} = Inactive) -> encode_chatstate_inactive(Inactive, [{<<"xmlns">>, <<"http://jabber.org/protocol/chatstates">>}]); encode({chatstate, paused} = Paused) -> encode_chatstate_paused(Paused, [{<<"xmlns">>, <<"http://jabber.org/protocol/chatstates">>}]); encode({delay, _, _} = Delay) -> encode_delay(Delay, [{<<"xmlns">>, <<"urn:xmpp:delay">>}]); encode({streamhost, _, _, _} = Streamhost) -> encode_bytestreams_streamhost(Streamhost, [{<<"xmlns">>, <<"http://jabber.org/protocol/bytestreams">>}]); encode({bytestreams, _, _, _, _, _, _} = Query) -> encode_bytestreams(Query, [{<<"xmlns">>, <<"http://jabber.org/protocol/bytestreams">>}]); encode({muc_history, _, _, _, _} = History) -> encode_muc_history(History, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc">>}]); encode({muc_decline, _, _, _} = Decline) -> encode_muc_user_decline(Decline, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc#user">>}]); encode({muc_user_destroy, _, _} = Destroy) -> encode_muc_user_destroy(Destroy, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc#user">>}]); encode({muc_invite, _, _, _} = Invite) -> encode_muc_user_invite(Invite, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc#user">>}]); encode({muc_user, _, _, _, _, _, _} = X) -> encode_muc_user(X, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc#user">>}]); encode({muc_owner_destroy, _, _, _} = Destroy) -> encode_muc_owner_destroy(Destroy, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc#owner">>}]); encode({muc_owner, _, _} = Query) -> encode_muc_owner(Query, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc#owner">>}]); encode({muc_item, _, _, _, _, _, _, _} = Item) -> encode_muc_admin_item(Item, []); encode({muc_actor, _, _} = Actor) -> encode_muc_admin_actor(Actor, []); encode({muc_admin, _} = Query) -> encode_muc_admin(Query, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc#admin">>}]); 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">>}]); encode({carbons_disable} = Disable) -> encode_carbons_disable(Disable, [{<<"xmlns">>, <<"urn:xmpp:carbons:2">>}]); encode({carbons_enable} = Enable) -> encode_carbons_enable(Enable, [{<<"xmlns">>, <<"urn:xmpp:carbons:2">>}]); encode({carbons_private} = Private) -> encode_carbons_private(Private, [{<<"xmlns">>, <<"urn:xmpp:carbons:2">>}]); encode({carbons_received, _} = Received) -> encode_carbons_received(Received, [{<<"xmlns">>, <<"urn:xmpp:carbons:2">>}]); encode({carbons_sent, _} = Sent) -> encode_carbons_sent(Sent, [{<<"xmlns">>, <<"urn:xmpp:carbons:2">>}]); encode({feature_csi, _} = Csi) -> encode_feature_csi(Csi, []); encode({csi, active} = Active) -> encode_csi_active(Active, [{<<"xmlns">>, <<"urn:xmpp:csi:0">>}]); encode({csi, inactive} = Inactive) -> encode_csi_inactive(Inactive, [{<<"xmlns">>, <<"urn:xmpp:csi:0">>}]); encode({feature_sm, _} = Sm) -> encode_feature_sm(Sm, []); encode({sm_enable, _, _, _} = Enable) -> encode_sm_enable(Enable, []); encode({sm_enabled, _, _, _, _, _} = Enabled) -> encode_sm_enabled(Enabled, []); encode({sm_resume, _, _, _} = Resume) -> encode_sm_resume(Resume, []); encode({sm_resumed, _, _, _} = Resumed) -> 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, []). get_ns({last, _, _}) -> <<"jabber:iq:last">>; get_ns({version, _, _, _}) -> <<"jabber:iq:version">>; get_ns({roster_item, _, _, _, _, _}) -> <<"jabber:iq:roster">>; get_ns({roster, _, _}) -> <<"jabber:iq:roster">>; get_ns({privacy_item, _, _, _, _, _}) -> <<"jabber:iq:privacy">>; get_ns({privacy_list, _, _}) -> <<"jabber:iq:privacy">>; get_ns({privacy, _, _, _}) -> <<"jabber:iq:privacy">>; get_ns({block, _}) -> <<"urn:xmpp:blocking">>; get_ns({unblock, _}) -> <<"urn:xmpp:blocking">>; get_ns({block_list}) -> <<"urn:xmpp:blocking">>; get_ns({identity, _, _, _, _}) -> <<"http://jabber.org/protocol/disco#info">>; get_ns({disco_info, _, _, _, _}) -> <<"http://jabber.org/protocol/disco#info">>; get_ns({disco_item, _, _, _}) -> <<"http://jabber.org/protocol/disco#items">>; get_ns({disco_items, _, _}) -> <<"http://jabber.org/protocol/disco#items">>; get_ns({private, _}) -> <<"jabber:iq:private">>; get_ns({bookmark_conference, _, _, _, _, _}) -> <<"storage:bookmarks">>; get_ns({bookmark_url, _, _}) -> <<"storage:bookmarks">>; get_ns({bookmark_storage, _, _}) -> <<"storage:bookmarks">>; get_ns({stat, _, _, _, _}) -> <<"http://jabber.org/protocol/stats">>; get_ns({stats, _}) -> <<"http://jabber.org/protocol/stats">>; get_ns({iq, _, _, _, _, _, _, _}) -> <<"jabber:client">>; get_ns({message, _, _, _, _, _, _, _, _, _, _}) -> <<"jabber:client">>; get_ns({presence, _, _, _, _, _, _, _, _, _, _}) -> <<"jabber:client">>; get_ns({gone, _}) -> <<"urn:ietf:params:xml:ns:xmpp-stanzas">>; get_ns({redirect, _}) -> <<"urn:ietf:params:xml:ns:xmpp-stanzas">>; get_ns({error, _, _, _, _}) -> <<"jabber:client">>; get_ns({bind, _, _}) -> <<"urn:ietf:params:xml:ns:xmpp-bind">>; get_ns({sasl_auth, _, _}) -> <<"urn:ietf:params:xml:ns:xmpp-sasl">>; get_ns({sasl_abort}) -> <<"urn:ietf:params:xml:ns:xmpp-sasl">>; get_ns({sasl_challenge, _}) -> <<"urn:ietf:params:xml:ns:xmpp-sasl">>; get_ns({sasl_response, _}) -> <<"urn:ietf:params:xml:ns:xmpp-sasl">>; get_ns({sasl_success, _}) -> <<"urn:ietf:params:xml:ns:xmpp-sasl">>; get_ns({sasl_failure, _, _}) -> <<"urn:ietf:params:xml:ns:xmpp-sasl">>; get_ns({sasl_mechanisms, _}) -> <<"urn:ietf:params:xml:ns:xmpp-sasl">>; get_ns({starttls, _}) -> <<"urn:ietf:params:xml:ns:xmpp-tls">>; get_ns({starttls_proceed}) -> <<"urn:ietf:params:xml:ns:xmpp-tls">>; get_ns({starttls_failure}) -> <<"urn:ietf:params:xml:ns:xmpp-tls">>; get_ns({compress_failure, _}) -> <<"http://jabber.org/protocol/compress">>; get_ns({compress, _}) -> <<"http://jabber.org/protocol/compress">>; get_ns({compressed}) -> <<"http://jabber.org/protocol/compress">>; get_ns({compression, _}) -> <<"http://jabber.org/features/compress">>; get_ns({stream_features, _}) -> <<"http://etherx.jabber.org/streams">>; get_ns({p1_push}) -> <<"p1:push">>; get_ns({p1_rebind}) -> <<"p1:rebind">>; get_ns({p1_ack}) -> <<"p1:ack">>; get_ns({caps, _, _, _}) -> <<"http://jabber.org/protocol/caps">>; get_ns({feature_register}) -> <<"http://jabber.org/features/iq-register">>; get_ns({register, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> <<"jabber:iq:register">>; get_ns({session}) -> <<"urn:ietf:params:xml:ns:xmpp-session">>; get_ns({ping}) -> <<"urn:xmpp:ping">>; get_ns({time, _, _}) -> <<"urn:xmpp:time">>; get_ns({'see-other-host', _}) -> <<"urn:ietf:params:xml:ns:xmpp-streams">>; get_ns({stream_error, _, _}) -> <<"http://etherx.jabber.org/streams">>; get_ns({vcard_name, _, _, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_adr, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_label, _, _, _, _, _, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_tel, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_email, _, _, _, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_geo, _, _}) -> <<"vcard-temp">>; get_ns({vcard_logo, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_photo, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_org, _, _}) -> <<"vcard-temp">>; get_ns({vcard_sound, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_key, _, _}) -> <<"vcard-temp">>; get_ns({vcard, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> <<"vcard-temp">>; get_ns({vcard_xupdate, _}) -> <<"vcard-temp:x:update">>; get_ns({xdata_field, _, _, _, _, _, _, _}) -> <<"jabber:x:data">>; get_ns({xdata, _, _, _, _, _, _}) -> <<"jabber:x:data">>; get_ns({pubsub_subscription, _, _, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_affiliation, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_item, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_items, _, _, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_event_item, _, _, _}) -> <<"http://jabber.org/protocol/pubsub#event">>; get_ns({pubsub_event_items, _, _, _}) -> <<"http://jabber.org/protocol/pubsub#event">>; get_ns({pubsub_event, _}) -> <<"http://jabber.org/protocol/pubsub#event">>; get_ns({pubsub_subscribe, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_unsubscribe, _, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_publish, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_options, _, _, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_retract, _, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub, _, _, _, _, _, _, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({shim, _}) -> <<"http://jabber.org/protocol/shim">>; get_ns({chatstate, active}) -> <<"http://jabber.org/protocol/chatstates">>; get_ns({chatstate, composing}) -> <<"http://jabber.org/protocol/chatstates">>; get_ns({chatstate, gone}) -> <<"http://jabber.org/protocol/chatstates">>; get_ns({chatstate, inactive}) -> <<"http://jabber.org/protocol/chatstates">>; get_ns({chatstate, paused}) -> <<"http://jabber.org/protocol/chatstates">>; get_ns({delay, _, _}) -> <<"urn:xmpp:delay">>; get_ns({streamhost, _, _, _}) -> <<"http://jabber.org/protocol/bytestreams">>; get_ns({bytestreams, _, _, _, _, _, _}) -> <<"http://jabber.org/protocol/bytestreams">>; get_ns({muc_history, _, _, _, _}) -> <<"http://jabber.org/protocol/muc">>; get_ns({muc_decline, _, _, _}) -> <<"http://jabber.org/protocol/muc#user">>; get_ns({muc_user_destroy, _, _}) -> <<"http://jabber.org/protocol/muc#user">>; get_ns({muc_invite, _, _, _}) -> <<"http://jabber.org/protocol/muc#user">>; get_ns({muc_user, _, _, _, _, _, _}) -> <<"http://jabber.org/protocol/muc#user">>; get_ns({muc_owner_destroy, _, _, _}) -> <<"http://jabber.org/protocol/muc#owner">>; get_ns({muc_owner, _, _}) -> <<"http://jabber.org/protocol/muc#owner">>; 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">>; get_ns({carbons_private}) -> <<"urn:xmpp:carbons:2">>; get_ns({carbons_received, _}) -> <<"urn:xmpp:carbons:2">>; 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(_) -> <<>>. dec_int(Val) -> dec_int(Val, infinity, infinity). dec_int(Val, Min, Max) -> case list_to_integer(binary_to_list(Val)) of Int when Int =< Max, Min == infinity -> Int; Int when Int =< Max, Int >= Min -> Int end. enc_int(Int) -> list_to_binary(integer_to_list(Int)). dec_enum(Val, Enums) -> AtomVal = erlang:binary_to_existing_atom(Val, utf8), case lists:member(AtomVal, Enums) of true -> AtomVal end. enc_enum(Atom) -> erlang:atom_to_binary(Atom, utf8). format_error({bad_attr_value, Attr, Tag, XMLNS}) -> <<"Bad value of attribute '", Attr/binary, "' in tag <", Tag/binary, "/> qualified by namespace '", XMLNS/binary, "'">>; format_error({bad_cdata_value, <<>>, Tag, XMLNS}) -> <<"Bad value of cdata in tag <", Tag/binary, "/> qualified by namespace '", XMLNS/binary, "'">>; format_error({missing_tag, Tag, XMLNS}) -> <<"Missing tag <", Tag/binary, "/> qualified by namespace '", XMLNS/binary, "'">>; format_error({missing_attr, Attr, Tag, XMLNS}) -> <<"Missing attribute '", Attr/binary, "' in tag <", Tag/binary, "/> qualified by namespace '", XMLNS/binary, "'">>; format_error({missing_cdata, <<>>, Tag, XMLNS}) -> <<"Missing cdata in tag <", Tag/binary, "/> qualified by namespace '", XMLNS/binary, "'">>; format_error({unknown_tag, Tag, XMLNS}) -> <<"Unknown tag <", Tag/binary, "/> qualified by namespace '", XMLNS/binary, "'">>. get_attr(Attr, Attrs) -> case lists:keyfind(Attr, 1, Attrs) of {_, Val} -> Val; false -> <<>> end. pp(Term) -> io_lib_pretty:print(Term, fun pp/2). pp(last, 2) -> [seconds, text]; pp(version, 3) -> [name, ver, os]; pp(roster_item, 5) -> [jid, name, groups, subscription, ask]; pp(roster, 2) -> [items, ver]; pp(privacy_item, 5) -> [order, action, type, value, kinds]; pp(privacy_list, 2) -> [name, items]; pp(privacy, 3) -> [lists, default, active]; pp(block, 1) -> [items]; pp(unblock, 1) -> [items]; pp(block_list, 0) -> []; pp(identity, 4) -> [category, type, lang, name]; pp(disco_info, 4) -> [node, identities, features, xdata]; pp(disco_item, 3) -> [jid, name, node]; pp(disco_items, 2) -> [node, items]; pp(private, 1) -> [xml_els]; pp(bookmark_conference, 5) -> [name, jid, autojoin, nick, password]; pp(bookmark_url, 2) -> [name, url]; pp(bookmark_storage, 2) -> [conference, url]; pp(stat, 4) -> [name, units, value, error]; pp(stats, 1) -> [stat]; pp(iq, 7) -> [id, type, lang, from, to, error, sub_els]; pp(message, 10) -> [id, type, lang, from, to, subject, body, thread, error, sub_els]; pp(presence, 10) -> [id, type, lang, from, to, show, status, priority, error, sub_els]; pp(gone, 1) -> [uri]; pp(redirect, 1) -> [uri]; pp(error, 4) -> [type, by, reason, text]; pp(bind, 2) -> [jid, resource]; pp(sasl_auth, 2) -> [mechanism, text]; pp(sasl_abort, 0) -> []; pp(sasl_challenge, 1) -> [text]; pp(sasl_response, 1) -> [text]; pp(sasl_success, 1) -> [text]; pp(sasl_failure, 2) -> [reason, text]; pp(sasl_mechanisms, 1) -> [list]; pp(starttls, 1) -> [required]; pp(starttls_proceed, 0) -> []; pp(starttls_failure, 0) -> []; pp(compress_failure, 1) -> [reason]; pp(compress, 1) -> [methods]; pp(compressed, 0) -> []; pp(compression, 1) -> [methods]; pp(stream_features, 1) -> [sub_els]; pp(p1_push, 0) -> []; pp(p1_rebind, 0) -> []; pp(p1_ack, 0) -> []; pp(caps, 3) -> [hash, node, ver]; pp(feature_register, 0) -> []; pp(register, 21) -> [registered, remove, instructions, username, nick, password, name, first, last, email, address, city, state, zip, phone, url, date, misc, text, key, xdata]; pp(session, 0) -> []; pp(ping, 0) -> []; pp(time, 2) -> [tzo, utc]; pp(text, 2) -> [lang, data]; pp('see-other-host', 1) -> [host]; pp(stream_error, 2) -> [reason, text]; pp(vcard_name, 5) -> [family, given, middle, prefix, suffix]; pp(vcard_adr, 14) -> [home, work, postal, parcel, dom, intl, pref, pobox, extadd, street, locality, region, pcode, ctry]; pp(vcard_label, 8) -> [home, work, postal, parcel, dom, intl, pref, line]; pp(vcard_tel, 14) -> [home, work, voice, fax, pager, msg, cell, video, bbs, modem, isdn, pcs, pref, number]; pp(vcard_email, 6) -> [home, work, internet, pref, x400, userid]; pp(vcard_geo, 2) -> [lat, lon]; pp(vcard_logo, 3) -> [type, binval, extval]; pp(vcard_photo, 3) -> [type, binval, extval]; pp(vcard_org, 2) -> [name, units]; pp(vcard_sound, 3) -> [phonetic, binval, extval]; pp(vcard_key, 2) -> [type, cred]; pp(vcard, 29) -> [version, fn, n, nickname, photo, bday, adr, label, tel, email, jabberid, mailer, tz, geo, title, role, logo, org, categories, note, prodid, rev, sort_string, sound, uid, url, class, key, desc]; pp(vcard_xupdate, 1) -> [photo]; pp(xdata_field, 7) -> [label, type, var, required, desc, values, options]; pp(xdata, 6) -> [type, instructions, title, reported, items, fields]; 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_items, 3) -> [node, retract, items]; pp(pubsub_event, 1) -> [items]; pp(pubsub_subscribe, 2) -> [node, jid]; pp(pubsub_unsubscribe, 3) -> [node, jid, subid]; pp(pubsub_publish, 2) -> [node, items]; pp(pubsub_options, 4) -> [node, jid, subid, xdata]; pp(pubsub_retract, 3) -> [node, notify, items]; pp(pubsub, 8) -> [subscriptions, affiliations, publish, subscribe, unsubscribe, options, items, retract]; pp(shim, 1) -> [headers]; pp(chatstate, 1) -> [type]; pp(delay, 2) -> [stamp, from]; pp(streamhost, 3) -> [jid, host, port]; pp(bytestreams, 6) -> [hosts, used, activate, dstaddr, mode, sid]; pp(muc_history, 4) -> [maxchars, maxstanzas, seconds, since]; pp(muc_decline, 3) -> [reason, from, to]; pp(muc_user_destroy, 2) -> [reason, jid]; pp(muc_invite, 3) -> [reason, from, to]; pp(muc_user, 6) -> [decline, destroy, invites, items, status_codes, password]; pp(muc_owner_destroy, 3) -> [jid, reason, password]; pp(muc_owner, 2) -> [destroy, config]; pp(muc_item, 7) -> [actor, continue, reason, affiliation, role, jid, nick]; 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, 4) -> [id, rsm, stable, complete]; pp(forwarded, 2) -> [delay, sub_els]; pp(carbons_disable, 0) -> []; pp(carbons_enable, 0) -> []; pp(carbons_private, 0) -> []; pp(carbons_received, 1) -> [forwarded]; pp(carbons_sent, 1) -> [forwarded]; pp(feature_csi, 1) -> [xmlns]; pp(csi, 1) -> [type]; pp(feature_sm, 1) -> [xmlns]; pp(sm_enable, 3) -> [max, resume, xmlns]; pp(sm_enabled, 5) -> [id, location, max, resume, xmlns]; pp(sm_resume, 3) -> [h, previd, xmlns]; 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(_, _) -> no. enc_bool(false) -> <<"false">>; enc_bool(true) -> <<"true">>. dec_bool(<<"false">>) -> false; dec_bool(<<"0">>) -> false; dec_bool(<<"true">>) -> true; dec_bool(<<"1">>) -> true. resourceprep(R) -> case jid:resourceprep(R) of error -> erlang:error(badarg); R1 -> R1 end. enc_jid(J) -> jid:to_string(J). dec_jid(Val) -> case jid:from_string(Val) of error -> erlang:error(badarg); J -> J end. enc_utc(Val) -> jlib:now_to_utc_string(Val). dec_utc(Val) -> {_, _, _} = jlib:datetime_string_to_timestamp(Val). enc_tzo({H, M}) -> Sign = if H >= 0 -> <<>>; true -> <<"-">> end, list_to_binary([Sign, io_lib:format("~2..0w:~2..0w", [H, M])]). dec_tzo(Val) -> [H1, M1] = str:tokens(Val, <<":">>), H = jlib:binary_to_integer(H1), M = jlib:binary_to_integer(M1), if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end. decode_sm_failed(__TopXMLNS, __IgnoreEls, {xmlel, <<"failed">>, _attrs, _els}) -> Reason = decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, undefined), Xmlns = decode_sm_failed_attrs(__TopXMLNS, _attrs, undefined), {sm_failed, Reason, Xmlns}. decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [], Reason) -> Reason; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"bad-request">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_bad_request(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"conflict">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_conflict(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"feature-not-implemented">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_feature_not_implemented(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"forbidden">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_forbidden(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"gone">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_gone(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"internal-server-error">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_internal_server_error(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item-not-found">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_item_not_found(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"jid-malformed">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_jid_malformed(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-acceptable">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_not_acceptable(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-allowed">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_not_allowed(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-authorized">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_not_authorized(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"policy-violation">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_policy_violation(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"recipient-unavailable">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_recipient_unavailable(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"redirect">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_redirect(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"registration-required">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_registration_required(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"remote-server-not-found">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_remote_server_not_found(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"remote-server-timeout">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_remote_server_timeout(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"resource-constraint">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_resource_constraint(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"service-unavailable">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_service_unavailable(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"subscription-required">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_subscription_required(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"undefined-condition">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_undefined_condition(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"unexpected-request">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, decode_error_unexpected_request(_xmlns, __IgnoreEls, _el)); true -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_sm_failed_els(__TopXMLNS, __IgnoreEls, [_ | _els], Reason) -> decode_sm_failed_els(__TopXMLNS, __IgnoreEls, _els, Reason). decode_sm_failed_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], _Xmlns) -> decode_sm_failed_attrs(__TopXMLNS, _attrs, _val); decode_sm_failed_attrs(__TopXMLNS, [_ | _attrs], Xmlns) -> decode_sm_failed_attrs(__TopXMLNS, _attrs, Xmlns); decode_sm_failed_attrs(__TopXMLNS, [], Xmlns) -> decode_sm_failed_attr_xmlns(__TopXMLNS, Xmlns). encode_sm_failed({sm_failed, Reason, Xmlns}, _xmlns_attrs) -> _els = lists:reverse('encode_sm_failed_$reason'(Reason, [])), _attrs = encode_sm_failed_attr_xmlns(Xmlns, _xmlns_attrs), {xmlel, <<"failed">>, _attrs, _els}. 'encode_sm_failed_$reason'(undefined, _acc) -> _acc; 'encode_sm_failed_$reason'('bad-request' = Reason, _acc) -> [encode_error_bad_request(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'(conflict = Reason, _acc) -> [encode_error_conflict(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('feature-not-implemented' = Reason, _acc) -> [encode_error_feature_not_implemented(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'(forbidden = Reason, _acc) -> [encode_error_forbidden(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'({gone, _} = Reason, _acc) -> [encode_error_gone(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('internal-server-error' = Reason, _acc) -> [encode_error_internal_server_error(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('item-not-found' = Reason, _acc) -> [encode_error_item_not_found(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('jid-malformed' = Reason, _acc) -> [encode_error_jid_malformed(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('not-acceptable' = Reason, _acc) -> [encode_error_not_acceptable(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('not-allowed' = Reason, _acc) -> [encode_error_not_allowed(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('not-authorized' = Reason, _acc) -> [encode_error_not_authorized(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('policy-violation' = Reason, _acc) -> [encode_error_policy_violation(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('recipient-unavailable' = Reason, _acc) -> [encode_error_recipient_unavailable(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'({redirect, _} = Reason, _acc) -> [encode_error_redirect(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('registration-required' = Reason, _acc) -> [encode_error_registration_required(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('remote-server-not-found' = Reason, _acc) -> [encode_error_remote_server_not_found(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('remote-server-timeout' = Reason, _acc) -> [encode_error_remote_server_timeout(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('resource-constraint' = Reason, _acc) -> [encode_error_resource_constraint(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('service-unavailable' = Reason, _acc) -> [encode_error_service_unavailable(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('subscription-required' = Reason, _acc) -> [encode_error_subscription_required(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('undefined-condition' = Reason, _acc) -> [encode_error_undefined_condition(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_sm_failed_$reason'('unexpected-request' = Reason, _acc) -> [encode_error_unexpected_request(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]. decode_sm_failed_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_sm_failed_attr_xmlns(__TopXMLNS, _val) -> _val. encode_sm_failed_attr_xmlns(undefined, _acc) -> _acc; encode_sm_failed_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_sm_a(__TopXMLNS, __IgnoreEls, {xmlel, <<"a">>, _attrs, _els}) -> {H, Xmlns} = decode_sm_a_attrs(__TopXMLNS, _attrs, undefined, undefined), {sm_a, H, Xmlns}. decode_sm_a_attrs(__TopXMLNS, [{<<"h">>, _val} | _attrs], _H, Xmlns) -> decode_sm_a_attrs(__TopXMLNS, _attrs, _val, Xmlns); decode_sm_a_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], H, _Xmlns) -> decode_sm_a_attrs(__TopXMLNS, _attrs, H, _val); decode_sm_a_attrs(__TopXMLNS, [_ | _attrs], H, Xmlns) -> decode_sm_a_attrs(__TopXMLNS, _attrs, H, Xmlns); decode_sm_a_attrs(__TopXMLNS, [], H, Xmlns) -> {decode_sm_a_attr_h(__TopXMLNS, H), decode_sm_a_attr_xmlns(__TopXMLNS, Xmlns)}. encode_sm_a({sm_a, H, Xmlns}, _xmlns_attrs) -> _els = [], _attrs = encode_sm_a_attr_xmlns(Xmlns, encode_sm_a_attr_h(H, _xmlns_attrs)), {xmlel, <<"a">>, _attrs, _els}. decode_sm_a_attr_h(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"h">>, <<"a">>, __TopXMLNS}}); decode_sm_a_attr_h(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"h">>, <<"a">>, __TopXMLNS}}); _res -> _res end. encode_sm_a_attr_h(_val, _acc) -> [{<<"h">>, enc_int(_val)} | _acc]. decode_sm_a_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_sm_a_attr_xmlns(__TopXMLNS, _val) -> _val. encode_sm_a_attr_xmlns(undefined, _acc) -> _acc; encode_sm_a_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_sm_r(__TopXMLNS, __IgnoreEls, {xmlel, <<"r">>, _attrs, _els}) -> Xmlns = decode_sm_r_attrs(__TopXMLNS, _attrs, undefined), {sm_r, Xmlns}. decode_sm_r_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], _Xmlns) -> decode_sm_r_attrs(__TopXMLNS, _attrs, _val); decode_sm_r_attrs(__TopXMLNS, [_ | _attrs], Xmlns) -> decode_sm_r_attrs(__TopXMLNS, _attrs, Xmlns); decode_sm_r_attrs(__TopXMLNS, [], Xmlns) -> decode_sm_r_attr_xmlns(__TopXMLNS, Xmlns). encode_sm_r({sm_r, Xmlns}, _xmlns_attrs) -> _els = [], _attrs = encode_sm_r_attr_xmlns(Xmlns, _xmlns_attrs), {xmlel, <<"r">>, _attrs, _els}. decode_sm_r_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_sm_r_attr_xmlns(__TopXMLNS, _val) -> _val. encode_sm_r_attr_xmlns(undefined, _acc) -> _acc; encode_sm_r_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_sm_resumed(__TopXMLNS, __IgnoreEls, {xmlel, <<"resumed">>, _attrs, _els}) -> {H, Xmlns, Previd} = decode_sm_resumed_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {sm_resumed, H, Previd, Xmlns}. decode_sm_resumed_attrs(__TopXMLNS, [{<<"h">>, _val} | _attrs], _H, Xmlns, Previd) -> decode_sm_resumed_attrs(__TopXMLNS, _attrs, _val, Xmlns, Previd); decode_sm_resumed_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], H, _Xmlns, Previd) -> decode_sm_resumed_attrs(__TopXMLNS, _attrs, H, _val, Previd); decode_sm_resumed_attrs(__TopXMLNS, [{<<"previd">>, _val} | _attrs], H, Xmlns, _Previd) -> decode_sm_resumed_attrs(__TopXMLNS, _attrs, H, Xmlns, _val); decode_sm_resumed_attrs(__TopXMLNS, [_ | _attrs], H, Xmlns, Previd) -> decode_sm_resumed_attrs(__TopXMLNS, _attrs, H, Xmlns, Previd); decode_sm_resumed_attrs(__TopXMLNS, [], H, Xmlns, Previd) -> {decode_sm_resumed_attr_h(__TopXMLNS, H), decode_sm_resumed_attr_xmlns(__TopXMLNS, Xmlns), decode_sm_resumed_attr_previd(__TopXMLNS, Previd)}. encode_sm_resumed({sm_resumed, H, Previd, Xmlns}, _xmlns_attrs) -> _els = [], _attrs = encode_sm_resumed_attr_previd(Previd, encode_sm_resumed_attr_xmlns(Xmlns, encode_sm_resumed_attr_h(H, _xmlns_attrs))), {xmlel, <<"resumed">>, _attrs, _els}. decode_sm_resumed_attr_h(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"h">>, <<"resumed">>, __TopXMLNS}}); decode_sm_resumed_attr_h(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"h">>, <<"resumed">>, __TopXMLNS}}); _res -> _res end. encode_sm_resumed_attr_h(_val, _acc) -> [{<<"h">>, enc_int(_val)} | _acc]. decode_sm_resumed_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_sm_resumed_attr_xmlns(__TopXMLNS, _val) -> _val. encode_sm_resumed_attr_xmlns(undefined, _acc) -> _acc; encode_sm_resumed_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_sm_resumed_attr_previd(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"previd">>, <<"resumed">>, __TopXMLNS}}); decode_sm_resumed_attr_previd(__TopXMLNS, _val) -> _val. encode_sm_resumed_attr_previd(_val, _acc) -> [{<<"previd">>, _val} | _acc]. decode_sm_resume(__TopXMLNS, __IgnoreEls, {xmlel, <<"resume">>, _attrs, _els}) -> {H, Xmlns, Previd} = decode_sm_resume_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {sm_resume, H, Previd, Xmlns}. decode_sm_resume_attrs(__TopXMLNS, [{<<"h">>, _val} | _attrs], _H, Xmlns, Previd) -> decode_sm_resume_attrs(__TopXMLNS, _attrs, _val, Xmlns, Previd); decode_sm_resume_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], H, _Xmlns, Previd) -> decode_sm_resume_attrs(__TopXMLNS, _attrs, H, _val, Previd); decode_sm_resume_attrs(__TopXMLNS, [{<<"previd">>, _val} | _attrs], H, Xmlns, _Previd) -> decode_sm_resume_attrs(__TopXMLNS, _attrs, H, Xmlns, _val); decode_sm_resume_attrs(__TopXMLNS, [_ | _attrs], H, Xmlns, Previd) -> decode_sm_resume_attrs(__TopXMLNS, _attrs, H, Xmlns, Previd); decode_sm_resume_attrs(__TopXMLNS, [], H, Xmlns, Previd) -> {decode_sm_resume_attr_h(__TopXMLNS, H), decode_sm_resume_attr_xmlns(__TopXMLNS, Xmlns), decode_sm_resume_attr_previd(__TopXMLNS, Previd)}. encode_sm_resume({sm_resume, H, Previd, Xmlns}, _xmlns_attrs) -> _els = [], _attrs = encode_sm_resume_attr_previd(Previd, encode_sm_resume_attr_xmlns(Xmlns, encode_sm_resume_attr_h(H, _xmlns_attrs))), {xmlel, <<"resume">>, _attrs, _els}. decode_sm_resume_attr_h(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"h">>, <<"resume">>, __TopXMLNS}}); decode_sm_resume_attr_h(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"h">>, <<"resume">>, __TopXMLNS}}); _res -> _res end. encode_sm_resume_attr_h(_val, _acc) -> [{<<"h">>, enc_int(_val)} | _acc]. decode_sm_resume_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_sm_resume_attr_xmlns(__TopXMLNS, _val) -> _val. encode_sm_resume_attr_xmlns(undefined, _acc) -> _acc; encode_sm_resume_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_sm_resume_attr_previd(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"previd">>, <<"resume">>, __TopXMLNS}}); decode_sm_resume_attr_previd(__TopXMLNS, _val) -> _val. encode_sm_resume_attr_previd(_val, _acc) -> [{<<"previd">>, _val} | _acc]. decode_sm_enabled(__TopXMLNS, __IgnoreEls, {xmlel, <<"enabled">>, _attrs, _els}) -> {Id, Location, Xmlns, Max, Resume} = decode_sm_enabled_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined, undefined), {sm_enabled, Id, Location, Max, Resume, Xmlns}. decode_sm_enabled_attrs(__TopXMLNS, [{<<"id">>, _val} | _attrs], _Id, Location, Xmlns, Max, Resume) -> decode_sm_enabled_attrs(__TopXMLNS, _attrs, _val, Location, Xmlns, Max, Resume); decode_sm_enabled_attrs(__TopXMLNS, [{<<"location">>, _val} | _attrs], Id, _Location, Xmlns, Max, Resume) -> decode_sm_enabled_attrs(__TopXMLNS, _attrs, Id, _val, Xmlns, Max, Resume); decode_sm_enabled_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], Id, Location, _Xmlns, Max, Resume) -> decode_sm_enabled_attrs(__TopXMLNS, _attrs, Id, Location, _val, Max, Resume); decode_sm_enabled_attrs(__TopXMLNS, [{<<"max">>, _val} | _attrs], Id, Location, Xmlns, _Max, Resume) -> decode_sm_enabled_attrs(__TopXMLNS, _attrs, Id, Location, Xmlns, _val, Resume); decode_sm_enabled_attrs(__TopXMLNS, [{<<"resume">>, _val} | _attrs], Id, Location, Xmlns, Max, _Resume) -> decode_sm_enabled_attrs(__TopXMLNS, _attrs, Id, Location, Xmlns, Max, _val); decode_sm_enabled_attrs(__TopXMLNS, [_ | _attrs], Id, Location, Xmlns, Max, Resume) -> decode_sm_enabled_attrs(__TopXMLNS, _attrs, Id, Location, Xmlns, Max, Resume); decode_sm_enabled_attrs(__TopXMLNS, [], Id, Location, Xmlns, Max, Resume) -> {decode_sm_enabled_attr_id(__TopXMLNS, Id), decode_sm_enabled_attr_location(__TopXMLNS, Location), decode_sm_enabled_attr_xmlns(__TopXMLNS, Xmlns), decode_sm_enabled_attr_max(__TopXMLNS, Max), decode_sm_enabled_attr_resume(__TopXMLNS, Resume)}. encode_sm_enabled({sm_enabled, Id, Location, Max, Resume, Xmlns}, _xmlns_attrs) -> _els = [], _attrs = encode_sm_enabled_attr_resume(Resume, encode_sm_enabled_attr_max(Max, encode_sm_enabled_attr_xmlns(Xmlns, encode_sm_enabled_attr_location(Location, encode_sm_enabled_attr_id(Id, _xmlns_attrs))))), {xmlel, <<"enabled">>, _attrs, _els}. decode_sm_enabled_attr_id(__TopXMLNS, undefined) -> undefined; decode_sm_enabled_attr_id(__TopXMLNS, _val) -> _val. encode_sm_enabled_attr_id(undefined, _acc) -> _acc; encode_sm_enabled_attr_id(_val, _acc) -> [{<<"id">>, _val} | _acc]. decode_sm_enabled_attr_location(__TopXMLNS, undefined) -> undefined; decode_sm_enabled_attr_location(__TopXMLNS, _val) -> _val. encode_sm_enabled_attr_location(undefined, _acc) -> _acc; encode_sm_enabled_attr_location(_val, _acc) -> [{<<"location">>, _val} | _acc]. decode_sm_enabled_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_sm_enabled_attr_xmlns(__TopXMLNS, _val) -> _val. encode_sm_enabled_attr_xmlns(undefined, _acc) -> _acc; encode_sm_enabled_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_sm_enabled_attr_max(__TopXMLNS, undefined) -> undefined; decode_sm_enabled_attr_max(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"max">>, <<"enabled">>, __TopXMLNS}}); _res -> _res end. encode_sm_enabled_attr_max(undefined, _acc) -> _acc; encode_sm_enabled_attr_max(_val, _acc) -> [{<<"max">>, enc_int(_val)} | _acc]. decode_sm_enabled_attr_resume(__TopXMLNS, undefined) -> false; decode_sm_enabled_attr_resume(__TopXMLNS, _val) -> case catch dec_bool(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"resume">>, <<"enabled">>, __TopXMLNS}}); _res -> _res end. encode_sm_enabled_attr_resume(false, _acc) -> _acc; encode_sm_enabled_attr_resume(_val, _acc) -> [{<<"resume">>, enc_bool(_val)} | _acc]. decode_sm_enable(__TopXMLNS, __IgnoreEls, {xmlel, <<"enable">>, _attrs, _els}) -> {Max, Xmlns, Resume} = decode_sm_enable_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {sm_enable, Max, Resume, Xmlns}. decode_sm_enable_attrs(__TopXMLNS, [{<<"max">>, _val} | _attrs], _Max, Xmlns, Resume) -> decode_sm_enable_attrs(__TopXMLNS, _attrs, _val, Xmlns, Resume); decode_sm_enable_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], Max, _Xmlns, Resume) -> decode_sm_enable_attrs(__TopXMLNS, _attrs, Max, _val, Resume); decode_sm_enable_attrs(__TopXMLNS, [{<<"resume">>, _val} | _attrs], Max, Xmlns, _Resume) -> decode_sm_enable_attrs(__TopXMLNS, _attrs, Max, Xmlns, _val); decode_sm_enable_attrs(__TopXMLNS, [_ | _attrs], Max, Xmlns, Resume) -> decode_sm_enable_attrs(__TopXMLNS, _attrs, Max, Xmlns, Resume); decode_sm_enable_attrs(__TopXMLNS, [], Max, Xmlns, Resume) -> {decode_sm_enable_attr_max(__TopXMLNS, Max), decode_sm_enable_attr_xmlns(__TopXMLNS, Xmlns), decode_sm_enable_attr_resume(__TopXMLNS, Resume)}. encode_sm_enable({sm_enable, Max, Resume, Xmlns}, _xmlns_attrs) -> _els = [], _attrs = encode_sm_enable_attr_resume(Resume, encode_sm_enable_attr_xmlns(Xmlns, encode_sm_enable_attr_max(Max, _xmlns_attrs))), {xmlel, <<"enable">>, _attrs, _els}. decode_sm_enable_attr_max(__TopXMLNS, undefined) -> undefined; decode_sm_enable_attr_max(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"max">>, <<"enable">>, __TopXMLNS}}); _res -> _res end. encode_sm_enable_attr_max(undefined, _acc) -> _acc; encode_sm_enable_attr_max(_val, _acc) -> [{<<"max">>, enc_int(_val)} | _acc]. decode_sm_enable_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_sm_enable_attr_xmlns(__TopXMLNS, _val) -> _val. encode_sm_enable_attr_xmlns(undefined, _acc) -> _acc; encode_sm_enable_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_sm_enable_attr_resume(__TopXMLNS, undefined) -> false; decode_sm_enable_attr_resume(__TopXMLNS, _val) -> case catch dec_bool(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"resume">>, <<"enable">>, __TopXMLNS}}); _res -> _res end. encode_sm_enable_attr_resume(false, _acc) -> _acc; encode_sm_enable_attr_resume(_val, _acc) -> [{<<"resume">>, enc_bool(_val)} | _acc]. decode_feature_sm(__TopXMLNS, __IgnoreEls, {xmlel, <<"sm">>, _attrs, _els}) -> Xmlns = decode_feature_sm_attrs(__TopXMLNS, _attrs, undefined), {feature_sm, Xmlns}. decode_feature_sm_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], _Xmlns) -> decode_feature_sm_attrs(__TopXMLNS, _attrs, _val); decode_feature_sm_attrs(__TopXMLNS, [_ | _attrs], Xmlns) -> decode_feature_sm_attrs(__TopXMLNS, _attrs, Xmlns); decode_feature_sm_attrs(__TopXMLNS, [], Xmlns) -> decode_feature_sm_attr_xmlns(__TopXMLNS, Xmlns). encode_feature_sm({feature_sm, Xmlns}, _xmlns_attrs) -> _els = [], _attrs = encode_feature_sm_attr_xmlns(Xmlns, _xmlns_attrs), {xmlel, <<"sm">>, _attrs, _els}. decode_feature_sm_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_feature_sm_attr_xmlns(__TopXMLNS, _val) -> _val. encode_feature_sm_attr_xmlns(undefined, _acc) -> _acc; encode_feature_sm_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_csi_inactive(__TopXMLNS, __IgnoreEls, {xmlel, <<"inactive">>, _attrs, _els}) -> {csi, inactive}. encode_csi_inactive({csi, inactive}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"inactive">>, _attrs, _els}. decode_csi_active(__TopXMLNS, __IgnoreEls, {xmlel, <<"active">>, _attrs, _els}) -> {csi, active}. encode_csi_active({csi, active}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"active">>, _attrs, _els}. decode_feature_csi(__TopXMLNS, __IgnoreEls, {xmlel, <<"csi">>, _attrs, _els}) -> Xmlns = decode_feature_csi_attrs(__TopXMLNS, _attrs, undefined), {feature_csi, Xmlns}. decode_feature_csi_attrs(__TopXMLNS, [{<<"xmlns">>, _val} | _attrs], _Xmlns) -> decode_feature_csi_attrs(__TopXMLNS, _attrs, _val); decode_feature_csi_attrs(__TopXMLNS, [_ | _attrs], Xmlns) -> decode_feature_csi_attrs(__TopXMLNS, _attrs, Xmlns); decode_feature_csi_attrs(__TopXMLNS, [], Xmlns) -> decode_feature_csi_attr_xmlns(__TopXMLNS, Xmlns). encode_feature_csi({feature_csi, Xmlns}, _xmlns_attrs) -> _els = [], _attrs = encode_feature_csi_attr_xmlns(Xmlns, _xmlns_attrs), {xmlel, <<"csi">>, _attrs, _els}. decode_feature_csi_attr_xmlns(__TopXMLNS, undefined) -> undefined; decode_feature_csi_attr_xmlns(__TopXMLNS, _val) -> _val. encode_feature_csi_attr_xmlns(undefined, _acc) -> _acc; encode_feature_csi_attr_xmlns(_val, _acc) -> [{<<"xmlns">>, _val} | _acc]. decode_carbons_sent(__TopXMLNS, __IgnoreEls, {xmlel, <<"sent">>, _attrs, _els}) -> Forwarded = decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, _els, error), {carbons_sent, Forwarded}. decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, [], Forwarded) -> case Forwarded of error -> erlang:error({xmpp_codec, {missing_tag, <<"forwarded">>, __TopXMLNS}}); {value, Forwarded1} -> Forwarded1 end; decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"forwarded">>, _attrs, _} = _el | _els], Forwarded) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:xmpp:forward:0">> -> decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, _els, {value, decode_forwarded(_xmlns, __IgnoreEls, _el)}); true -> decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, _els, Forwarded) end; decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, [_ | _els], Forwarded) -> decode_carbons_sent_els(__TopXMLNS, __IgnoreEls, _els, Forwarded). encode_carbons_sent({carbons_sent, Forwarded}, _xmlns_attrs) -> _els = lists:reverse('encode_carbons_sent_$forwarded'(Forwarded, [])), _attrs = _xmlns_attrs, {xmlel, <<"sent">>, _attrs, _els}. 'encode_carbons_sent_$forwarded'(Forwarded, _acc) -> [encode_forwarded(Forwarded, [{<<"xmlns">>, <<"urn:xmpp:forward:0">>}]) | _acc]. decode_carbons_received(__TopXMLNS, __IgnoreEls, {xmlel, <<"received">>, _attrs, _els}) -> Forwarded = decode_carbons_received_els(__TopXMLNS, __IgnoreEls, _els, error), {carbons_received, Forwarded}. decode_carbons_received_els(__TopXMLNS, __IgnoreEls, [], Forwarded) -> case Forwarded of error -> erlang:error({xmpp_codec, {missing_tag, <<"forwarded">>, __TopXMLNS}}); {value, Forwarded1} -> Forwarded1 end; decode_carbons_received_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"forwarded">>, _attrs, _} = _el | _els], Forwarded) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:xmpp:forward:0">> -> decode_carbons_received_els(__TopXMLNS, __IgnoreEls, _els, {value, decode_forwarded(_xmlns, __IgnoreEls, _el)}); true -> decode_carbons_received_els(__TopXMLNS, __IgnoreEls, _els, Forwarded) end; decode_carbons_received_els(__TopXMLNS, __IgnoreEls, [_ | _els], Forwarded) -> decode_carbons_received_els(__TopXMLNS, __IgnoreEls, _els, Forwarded). encode_carbons_received({carbons_received, Forwarded}, _xmlns_attrs) -> _els = lists:reverse('encode_carbons_received_$forwarded'(Forwarded, [])), _attrs = _xmlns_attrs, {xmlel, <<"received">>, _attrs, _els}. 'encode_carbons_received_$forwarded'(Forwarded, _acc) -> [encode_forwarded(Forwarded, [{<<"xmlns">>, <<"urn:xmpp:forward:0">>}]) | _acc]. decode_carbons_private(__TopXMLNS, __IgnoreEls, {xmlel, <<"private">>, _attrs, _els}) -> {carbons_private}. encode_carbons_private({carbons_private}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"private">>, _attrs, _els}. decode_carbons_enable(__TopXMLNS, __IgnoreEls, {xmlel, <<"enable">>, _attrs, _els}) -> {carbons_enable}. encode_carbons_enable({carbons_enable}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"enable">>, _attrs, _els}. decode_carbons_disable(__TopXMLNS, __IgnoreEls, {xmlel, <<"disable">>, _attrs, _els}) -> {carbons_disable}. encode_carbons_disable({carbons_disable}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"disable">>, _attrs, _els}. decode_forwarded(__TopXMLNS, __IgnoreEls, {xmlel, <<"forwarded">>, _attrs, _els}) -> {Delay, __Els} = decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, undefined, []), {forwarded, Delay, __Els}. decode_forwarded_els(__TopXMLNS, __IgnoreEls, [], Delay, __Els) -> {Delay, lists:reverse(__Els)}; decode_forwarded_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"delay">>, _attrs, _} = _el | _els], Delay, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:xmpp:delay">> -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, decode_delay(_xmlns, __IgnoreEls, _el), __Els); true -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, Delay, __Els) end; decode_forwarded_els(__TopXMLNS, __IgnoreEls, [{xmlel, _, _, _} = _el | _els], Delay, __Els) -> if __IgnoreEls -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, Delay, [_el | __Els]); true -> case is_known_tag(_el) of true -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, Delay, [decode(_el) | __Els]); false -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, Delay, __Els) end end; decode_forwarded_els(__TopXMLNS, __IgnoreEls, [_ | _els], Delay, __Els) -> decode_forwarded_els(__TopXMLNS, __IgnoreEls, _els, Delay, __Els). encode_forwarded({forwarded, Delay, __Els}, _xmlns_attrs) -> _els = [encode(_el) || _el <- __Els] ++ lists:reverse('encode_forwarded_$delay'(Delay, [])), _attrs = _xmlns_attrs, {xmlel, <<"forwarded">>, _attrs, _els}. 'encode_forwarded_$delay'(undefined, _acc) -> _acc; 'encode_forwarded_$delay'(Delay, _acc) -> [encode_delay(Delay, [{<<"xmlns">>, <<"urn:xmpp:delay">>}]) | _acc]. decode_mam_fin(__TopXMLNS, __IgnoreEls, {xmlel, <<"fin">>, _attrs, _els}) -> Rsm = decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, undefined), {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; 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, 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_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; '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_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, __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, <<>>) -> none; decode_rsm_before_cdata(__TopXMLNS, _val) -> _val. encode_rsm_before_cdata(none, _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, undefined), Password = decode_muc_attrs(__TopXMLNS, _attrs, undefined), {muc, History, Password}. decode_muc_els(__TopXMLNS, __IgnoreEls, [], History) -> History; decode_muc_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"history">>, _attrs, _} = _el | _els], History) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_els(__TopXMLNS, __IgnoreEls, _els, decode_muc_history(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_els(__TopXMLNS, __IgnoreEls, _els, History) end; decode_muc_els(__TopXMLNS, __IgnoreEls, [_ | _els], History) -> decode_muc_els(__TopXMLNS, __IgnoreEls, _els, History). decode_muc_attrs(__TopXMLNS, [{<<"password">>, _val} | _attrs], _Password) -> decode_muc_attrs(__TopXMLNS, _attrs, _val); decode_muc_attrs(__TopXMLNS, [_ | _attrs], Password) -> decode_muc_attrs(__TopXMLNS, _attrs, Password); decode_muc_attrs(__TopXMLNS, [], Password) -> decode_muc_attr_password(__TopXMLNS, Password). encode_muc({muc, History, Password}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_$history'(History, [])), _attrs = encode_muc_attr_password(Password, _xmlns_attrs), {xmlel, <<"x">>, _attrs, _els}. 'encode_muc_$history'(undefined, _acc) -> _acc; 'encode_muc_$history'(History, _acc) -> [encode_muc_history(History, []) | _acc]. decode_muc_attr_password(__TopXMLNS, undefined) -> undefined; decode_muc_attr_password(__TopXMLNS, _val) -> _val. encode_muc_attr_password(undefined, _acc) -> _acc; encode_muc_attr_password(_val, _acc) -> [{<<"password">>, _val} | _acc]. decode_muc_admin(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> Items = decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els, []), {muc_admin, Items}. decode_muc_admin_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_muc_admin_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els, [decode_muc_admin_item(__TopXMLNS, __IgnoreEls, _el) | Items]); true -> decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_muc_admin_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_muc_admin_els(__TopXMLNS, __IgnoreEls, _els, Items). encode_muc_admin({muc_admin, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_admin_$items'(Items, [])), _attrs = _xmlns_attrs, {xmlel, <<"query">>, _attrs, _els}. 'encode_muc_admin_$items'([], _acc) -> _acc; 'encode_muc_admin_$items'([Items | _els], _acc) -> 'encode_muc_admin_$items'(_els, [encode_muc_admin_item(Items, []) | _acc]). decode_muc_admin_reason(__TopXMLNS, __IgnoreEls, {xmlel, <<"reason">>, _attrs, _els}) -> Cdata = decode_muc_admin_reason_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_muc_admin_reason_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_muc_admin_reason_cdata(__TopXMLNS, Cdata); decode_muc_admin_reason_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_muc_admin_reason_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_muc_admin_reason_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_muc_admin_reason_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_muc_admin_reason(Cdata, _xmlns_attrs) -> _els = encode_muc_admin_reason_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"reason">>, _attrs, _els}. decode_muc_admin_reason_cdata(__TopXMLNS, <<>>) -> undefined; decode_muc_admin_reason_cdata(__TopXMLNS, _val) -> _val. encode_muc_admin_reason_cdata(undefined, _acc) -> _acc; encode_muc_admin_reason_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_muc_admin_continue(__TopXMLNS, __IgnoreEls, {xmlel, <<"continue">>, _attrs, _els}) -> Thread = decode_muc_admin_continue_attrs(__TopXMLNS, _attrs, undefined), Thread. decode_muc_admin_continue_attrs(__TopXMLNS, [{<<"thread">>, _val} | _attrs], _Thread) -> decode_muc_admin_continue_attrs(__TopXMLNS, _attrs, _val); decode_muc_admin_continue_attrs(__TopXMLNS, [_ | _attrs], Thread) -> decode_muc_admin_continue_attrs(__TopXMLNS, _attrs, Thread); decode_muc_admin_continue_attrs(__TopXMLNS, [], Thread) -> decode_muc_admin_continue_attr_thread(__TopXMLNS, Thread). encode_muc_admin_continue(Thread, _xmlns_attrs) -> _els = [], _attrs = encode_muc_admin_continue_attr_thread(Thread, _xmlns_attrs), {xmlel, <<"continue">>, _attrs, _els}. decode_muc_admin_continue_attr_thread(__TopXMLNS, undefined) -> undefined; decode_muc_admin_continue_attr_thread(__TopXMLNS, _val) -> _val. encode_muc_admin_continue_attr_thread(undefined, _acc) -> _acc; encode_muc_admin_continue_attr_thread(_val, _acc) -> [{<<"thread">>, _val} | _acc]. decode_muc_admin_actor(__TopXMLNS, __IgnoreEls, {xmlel, <<"actor">>, _attrs, _els}) -> {Jid, Nick} = decode_muc_admin_actor_attrs(__TopXMLNS, _attrs, undefined, undefined), {muc_actor, Jid, Nick}. decode_muc_admin_actor_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid, Nick) -> decode_muc_admin_actor_attrs(__TopXMLNS, _attrs, _val, Nick); decode_muc_admin_actor_attrs(__TopXMLNS, [{<<"nick">>, _val} | _attrs], Jid, _Nick) -> decode_muc_admin_actor_attrs(__TopXMLNS, _attrs, Jid, _val); decode_muc_admin_actor_attrs(__TopXMLNS, [_ | _attrs], Jid, Nick) -> decode_muc_admin_actor_attrs(__TopXMLNS, _attrs, Jid, Nick); decode_muc_admin_actor_attrs(__TopXMLNS, [], Jid, Nick) -> {decode_muc_admin_actor_attr_jid(__TopXMLNS, Jid), decode_muc_admin_actor_attr_nick(__TopXMLNS, Nick)}. encode_muc_admin_actor({muc_actor, Jid, Nick}, _xmlns_attrs) -> _els = [], _attrs = encode_muc_admin_actor_attr_nick(Nick, encode_muc_admin_actor_attr_jid(Jid, _xmlns_attrs)), {xmlel, <<"actor">>, _attrs, _els}. decode_muc_admin_actor_attr_jid(__TopXMLNS, undefined) -> undefined; decode_muc_admin_actor_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"actor">>, __TopXMLNS}}); _res -> _res end. encode_muc_admin_actor_attr_jid(undefined, _acc) -> _acc; encode_muc_admin_actor_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_muc_admin_actor_attr_nick(__TopXMLNS, undefined) -> undefined; decode_muc_admin_actor_attr_nick(__TopXMLNS, _val) -> _val. encode_muc_admin_actor_attr_nick(undefined, _acc) -> _acc; encode_muc_admin_actor_attr_nick(_val, _acc) -> [{<<"nick">>, _val} | _acc]. decode_muc_admin_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> {Actor, Continue, Reason} = decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined), {Affiliation, Role, Jid, Nick} = decode_muc_admin_item_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined), {muc_item, Actor, Continue, Reason, Affiliation, Role, Jid, Nick}. decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, [], Actor, Continue, Reason) -> {Actor, Continue, Reason}; decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"actor">>, _attrs, _} = _el | _els], Actor, Continue, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els, decode_muc_admin_actor(__TopXMLNS, __IgnoreEls, _el), Continue, Reason); true -> decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, Reason) end; decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"continue">>, _attrs, _} = _el | _els], Actor, Continue, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, decode_muc_admin_continue(__TopXMLNS, __IgnoreEls, _el), Reason); true -> decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, Reason) end; decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"reason">>, _attrs, _} = _el | _els], Actor, Continue, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, decode_muc_admin_reason(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, Reason) end; decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, [_ | _els], Actor, Continue, Reason) -> decode_muc_admin_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, Reason). decode_muc_admin_item_attrs(__TopXMLNS, [{<<"affiliation">>, _val} | _attrs], _Affiliation, Role, Jid, Nick) -> decode_muc_admin_item_attrs(__TopXMLNS, _attrs, _val, Role, Jid, Nick); decode_muc_admin_item_attrs(__TopXMLNS, [{<<"role">>, _val} | _attrs], Affiliation, _Role, Jid, Nick) -> decode_muc_admin_item_attrs(__TopXMLNS, _attrs, Affiliation, _val, Jid, Nick); decode_muc_admin_item_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], Affiliation, Role, _Jid, Nick) -> decode_muc_admin_item_attrs(__TopXMLNS, _attrs, Affiliation, Role, _val, Nick); decode_muc_admin_item_attrs(__TopXMLNS, [{<<"nick">>, _val} | _attrs], Affiliation, Role, Jid, _Nick) -> decode_muc_admin_item_attrs(__TopXMLNS, _attrs, Affiliation, Role, Jid, _val); decode_muc_admin_item_attrs(__TopXMLNS, [_ | _attrs], Affiliation, Role, Jid, Nick) -> decode_muc_admin_item_attrs(__TopXMLNS, _attrs, Affiliation, Role, Jid, Nick); decode_muc_admin_item_attrs(__TopXMLNS, [], Affiliation, Role, Jid, Nick) -> {decode_muc_admin_item_attr_affiliation(__TopXMLNS, Affiliation), decode_muc_admin_item_attr_role(__TopXMLNS, Role), decode_muc_admin_item_attr_jid(__TopXMLNS, Jid), decode_muc_admin_item_attr_nick(__TopXMLNS, Nick)}. encode_muc_admin_item({muc_item, Actor, Continue, Reason, Affiliation, Role, Jid, Nick}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_admin_item_$actor'(Actor, 'encode_muc_admin_item_$continue'(Continue, 'encode_muc_admin_item_$reason'(Reason, [])))), _attrs = encode_muc_admin_item_attr_nick(Nick, encode_muc_admin_item_attr_jid(Jid, encode_muc_admin_item_attr_role(Role, encode_muc_admin_item_attr_affiliation(Affiliation, _xmlns_attrs)))), {xmlel, <<"item">>, _attrs, _els}. 'encode_muc_admin_item_$actor'(undefined, _acc) -> _acc; 'encode_muc_admin_item_$actor'(Actor, _acc) -> [encode_muc_admin_actor(Actor, []) | _acc]. 'encode_muc_admin_item_$continue'(undefined, _acc) -> _acc; 'encode_muc_admin_item_$continue'(Continue, _acc) -> [encode_muc_admin_continue(Continue, []) | _acc]. 'encode_muc_admin_item_$reason'(undefined, _acc) -> _acc; 'encode_muc_admin_item_$reason'(Reason, _acc) -> [encode_muc_admin_reason(Reason, []) | _acc]. decode_muc_admin_item_attr_affiliation(__TopXMLNS, undefined) -> undefined; decode_muc_admin_item_attr_affiliation(__TopXMLNS, _val) -> case catch dec_enum(_val, [admin, member, none, outcast, owner]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"affiliation">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_muc_admin_item_attr_affiliation(undefined, _acc) -> _acc; encode_muc_admin_item_attr_affiliation(_val, _acc) -> [{<<"affiliation">>, enc_enum(_val)} | _acc]. decode_muc_admin_item_attr_role(__TopXMLNS, undefined) -> undefined; decode_muc_admin_item_attr_role(__TopXMLNS, _val) -> case catch dec_enum(_val, [moderator, none, participant, visitor]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"role">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_muc_admin_item_attr_role(undefined, _acc) -> _acc; encode_muc_admin_item_attr_role(_val, _acc) -> [{<<"role">>, enc_enum(_val)} | _acc]. decode_muc_admin_item_attr_jid(__TopXMLNS, undefined) -> undefined; decode_muc_admin_item_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_muc_admin_item_attr_jid(undefined, _acc) -> _acc; encode_muc_admin_item_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_muc_admin_item_attr_nick(__TopXMLNS, undefined) -> undefined; decode_muc_admin_item_attr_nick(__TopXMLNS, _val) -> _val. encode_muc_admin_item_attr_nick(undefined, _acc) -> _acc; encode_muc_admin_item_attr_nick(_val, _acc) -> [{<<"nick">>, _val} | _acc]. decode_muc_owner(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> {Config, Destroy} = decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), {muc_owner, Destroy, Config}. decode_muc_owner_els(__TopXMLNS, __IgnoreEls, [], Config, Destroy) -> {Config, Destroy}; decode_muc_owner_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"destroy">>, _attrs, _} = _el | _els], Config, Destroy) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els, Config, decode_muc_owner_destroy(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els, Config, Destroy) end; decode_muc_owner_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"x">>, _attrs, _} = _el | _els], Config, Destroy) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"jabber:x:data">> -> decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els, decode_xdata(_xmlns, __IgnoreEls, _el), Destroy); true -> decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els, Config, Destroy) end; decode_muc_owner_els(__TopXMLNS, __IgnoreEls, [_ | _els], Config, Destroy) -> decode_muc_owner_els(__TopXMLNS, __IgnoreEls, _els, Config, Destroy). encode_muc_owner({muc_owner, Destroy, Config}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_owner_$config'(Config, 'encode_muc_owner_$destroy'(Destroy, []))), _attrs = _xmlns_attrs, {xmlel, <<"query">>, _attrs, _els}. 'encode_muc_owner_$config'(undefined, _acc) -> _acc; 'encode_muc_owner_$config'(Config, _acc) -> [encode_xdata(Config, [{<<"xmlns">>, <<"jabber:x:data">>}]) | _acc]. 'encode_muc_owner_$destroy'(undefined, _acc) -> _acc; 'encode_muc_owner_$destroy'(Destroy, _acc) -> [encode_muc_owner_destroy(Destroy, []) | _acc]. decode_muc_owner_destroy(__TopXMLNS, __IgnoreEls, {xmlel, <<"destroy">>, _attrs, _els}) -> {Password, Reason} = decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), Jid = decode_muc_owner_destroy_attrs(__TopXMLNS, _attrs, undefined), {muc_owner_destroy, Jid, Reason, Password}. decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, [], Password, Reason) -> {Password, Reason}; decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"password">>, _attrs, _} = _el | _els], Password, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, _els, decode_muc_owner_password(__TopXMLNS, __IgnoreEls, _el), Reason); true -> decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, _els, Password, Reason) end; decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"reason">>, _attrs, _} = _el | _els], Password, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, _els, Password, decode_muc_owner_reason(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, _els, Password, Reason) end; decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, [_ | _els], Password, Reason) -> decode_muc_owner_destroy_els(__TopXMLNS, __IgnoreEls, _els, Password, Reason). decode_muc_owner_destroy_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid) -> decode_muc_owner_destroy_attrs(__TopXMLNS, _attrs, _val); decode_muc_owner_destroy_attrs(__TopXMLNS, [_ | _attrs], Jid) -> decode_muc_owner_destroy_attrs(__TopXMLNS, _attrs, Jid); decode_muc_owner_destroy_attrs(__TopXMLNS, [], Jid) -> decode_muc_owner_destroy_attr_jid(__TopXMLNS, Jid). encode_muc_owner_destroy({muc_owner_destroy, Jid, Reason, Password}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_owner_destroy_$password'(Password, 'encode_muc_owner_destroy_$reason'(Reason, []))), _attrs = encode_muc_owner_destroy_attr_jid(Jid, _xmlns_attrs), {xmlel, <<"destroy">>, _attrs, _els}. 'encode_muc_owner_destroy_$password'(undefined, _acc) -> _acc; 'encode_muc_owner_destroy_$password'(Password, _acc) -> [encode_muc_owner_password(Password, []) | _acc]. 'encode_muc_owner_destroy_$reason'(undefined, _acc) -> _acc; 'encode_muc_owner_destroy_$reason'(Reason, _acc) -> [encode_muc_owner_reason(Reason, []) | _acc]. decode_muc_owner_destroy_attr_jid(__TopXMLNS, undefined) -> undefined; decode_muc_owner_destroy_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"destroy">>, __TopXMLNS}}); _res -> _res end. encode_muc_owner_destroy_attr_jid(undefined, _acc) -> _acc; encode_muc_owner_destroy_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_muc_owner_reason(__TopXMLNS, __IgnoreEls, {xmlel, <<"reason">>, _attrs, _els}) -> Cdata = decode_muc_owner_reason_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_muc_owner_reason_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_muc_owner_reason_cdata(__TopXMLNS, Cdata); decode_muc_owner_reason_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_muc_owner_reason_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_muc_owner_reason_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_muc_owner_reason_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_muc_owner_reason(Cdata, _xmlns_attrs) -> _els = encode_muc_owner_reason_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"reason">>, _attrs, _els}. decode_muc_owner_reason_cdata(__TopXMLNS, <<>>) -> undefined; decode_muc_owner_reason_cdata(__TopXMLNS, _val) -> _val. encode_muc_owner_reason_cdata(undefined, _acc) -> _acc; encode_muc_owner_reason_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_muc_owner_password(__TopXMLNS, __IgnoreEls, {xmlel, <<"password">>, _attrs, _els}) -> Cdata = decode_muc_owner_password_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_muc_owner_password_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_muc_owner_password_cdata(__TopXMLNS, Cdata); decode_muc_owner_password_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_muc_owner_password_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_muc_owner_password_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_muc_owner_password_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_muc_owner_password(Cdata, _xmlns_attrs) -> _els = encode_muc_owner_password_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"password">>, _attrs, _els}. decode_muc_owner_password_cdata(__TopXMLNS, <<>>) -> undefined; decode_muc_owner_password_cdata(__TopXMLNS, _val) -> _val. encode_muc_owner_password_cdata(undefined, _acc) -> _acc; encode_muc_owner_password_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_muc_user(__TopXMLNS, __IgnoreEls, {xmlel, <<"x">>, _attrs, _els}) -> {Status_codes, Items, Invites, Decline, Destroy} = decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, [], [], [], undefined, undefined), Password = decode_muc_user_attrs(__TopXMLNS, _attrs, undefined), {muc_user, Decline, Destroy, Invites, Items, Status_codes, Password}. decode_muc_user_els(__TopXMLNS, __IgnoreEls, [], Status_codes, Items, Invites, Decline, Destroy) -> {lists:reverse(Status_codes), lists:reverse(Items), lists:reverse(Invites), Decline, Destroy}; decode_muc_user_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"decline">>, _attrs, _} = _el | _els], Status_codes, Items, Invites, Decline, Destroy) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, Invites, decode_muc_user_decline(__TopXMLNS, __IgnoreEls, _el), Destroy); true -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, Invites, Decline, Destroy) end; decode_muc_user_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"destroy">>, _attrs, _} = _el | _els], Status_codes, Items, Invites, Decline, Destroy) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, Invites, Decline, decode_muc_user_destroy(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, Invites, Decline, Destroy) end; decode_muc_user_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"invite">>, _attrs, _} = _el | _els], Status_codes, Items, Invites, Decline, Destroy) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, [decode_muc_user_invite(__TopXMLNS, __IgnoreEls, _el) | Invites], Decline, Destroy); true -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, Invites, Decline, Destroy) end; decode_muc_user_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Status_codes, Items, Invites, Decline, Destroy) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, [decode_muc_user_item(__TopXMLNS, __IgnoreEls, _el) | Items], Invites, Decline, Destroy); true -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, Invites, Decline, Destroy) end; decode_muc_user_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"status">>, _attrs, _} = _el | _els], Status_codes, Items, Invites, Decline, Destroy) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, case decode_muc_user_status(__TopXMLNS, __IgnoreEls, _el) of undefined -> Status_codes; _new_el -> [_new_el | Status_codes] end, Items, Invites, Decline, Destroy); true -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, Invites, Decline, Destroy) end; decode_muc_user_els(__TopXMLNS, __IgnoreEls, [_ | _els], Status_codes, Items, Invites, Decline, Destroy) -> decode_muc_user_els(__TopXMLNS, __IgnoreEls, _els, Status_codes, Items, Invites, Decline, Destroy). decode_muc_user_attrs(__TopXMLNS, [{<<"password">>, _val} | _attrs], _Password) -> decode_muc_user_attrs(__TopXMLNS, _attrs, _val); decode_muc_user_attrs(__TopXMLNS, [_ | _attrs], Password) -> decode_muc_user_attrs(__TopXMLNS, _attrs, Password); decode_muc_user_attrs(__TopXMLNS, [], Password) -> decode_muc_user_attr_password(__TopXMLNS, Password). encode_muc_user({muc_user, Decline, Destroy, Invites, Items, Status_codes, Password}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_user_$status_codes'(Status_codes, 'encode_muc_user_$items'(Items, 'encode_muc_user_$invites'(Invites, 'encode_muc_user_$decline'(Decline, 'encode_muc_user_$destroy'(Destroy, [])))))), _attrs = encode_muc_user_attr_password(Password, _xmlns_attrs), {xmlel, <<"x">>, _attrs, _els}. 'encode_muc_user_$status_codes'([], _acc) -> _acc; 'encode_muc_user_$status_codes'([Status_codes | _els], _acc) -> 'encode_muc_user_$status_codes'(_els, [encode_muc_user_status(Status_codes, []) | _acc]). 'encode_muc_user_$items'([], _acc) -> _acc; 'encode_muc_user_$items'([Items | _els], _acc) -> 'encode_muc_user_$items'(_els, [encode_muc_user_item(Items, []) | _acc]). 'encode_muc_user_$invites'([], _acc) -> _acc; 'encode_muc_user_$invites'([Invites | _els], _acc) -> 'encode_muc_user_$invites'(_els, [encode_muc_user_invite(Invites, []) | _acc]). 'encode_muc_user_$decline'(undefined, _acc) -> _acc; 'encode_muc_user_$decline'(Decline, _acc) -> [encode_muc_user_decline(Decline, []) | _acc]. 'encode_muc_user_$destroy'(undefined, _acc) -> _acc; 'encode_muc_user_$destroy'(Destroy, _acc) -> [encode_muc_user_destroy(Destroy, []) | _acc]. decode_muc_user_attr_password(__TopXMLNS, undefined) -> undefined; decode_muc_user_attr_password(__TopXMLNS, _val) -> _val. encode_muc_user_attr_password(undefined, _acc) -> _acc; encode_muc_user_attr_password(_val, _acc) -> [{<<"password">>, _val} | _acc]. decode_muc_user_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> {Actor, Continue, Reason} = decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined), {Affiliation, Role, Jid, Nick} = decode_muc_user_item_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined), {muc_item, Actor, Continue, Reason, Affiliation, Role, Jid, Nick}. decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, [], Actor, Continue, Reason) -> {Actor, Continue, Reason}; decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"actor">>, _attrs, _} = _el | _els], Actor, Continue, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els, decode_muc_user_actor(__TopXMLNS, __IgnoreEls, _el), Continue, Reason); true -> decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, Reason) end; decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"continue">>, _attrs, _} = _el | _els], Actor, Continue, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, decode_muc_user_continue(__TopXMLNS, __IgnoreEls, _el), Reason); true -> decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, Reason) end; decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"reason">>, _attrs, _} = _el | _els], Actor, Continue, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, decode_muc_user_reason(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, Reason) end; decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, [_ | _els], Actor, Continue, Reason) -> decode_muc_user_item_els(__TopXMLNS, __IgnoreEls, _els, Actor, Continue, Reason). decode_muc_user_item_attrs(__TopXMLNS, [{<<"affiliation">>, _val} | _attrs], _Affiliation, Role, Jid, Nick) -> decode_muc_user_item_attrs(__TopXMLNS, _attrs, _val, Role, Jid, Nick); decode_muc_user_item_attrs(__TopXMLNS, [{<<"role">>, _val} | _attrs], Affiliation, _Role, Jid, Nick) -> decode_muc_user_item_attrs(__TopXMLNS, _attrs, Affiliation, _val, Jid, Nick); decode_muc_user_item_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], Affiliation, Role, _Jid, Nick) -> decode_muc_user_item_attrs(__TopXMLNS, _attrs, Affiliation, Role, _val, Nick); decode_muc_user_item_attrs(__TopXMLNS, [{<<"nick">>, _val} | _attrs], Affiliation, Role, Jid, _Nick) -> decode_muc_user_item_attrs(__TopXMLNS, _attrs, Affiliation, Role, Jid, _val); decode_muc_user_item_attrs(__TopXMLNS, [_ | _attrs], Affiliation, Role, Jid, Nick) -> decode_muc_user_item_attrs(__TopXMLNS, _attrs, Affiliation, Role, Jid, Nick); decode_muc_user_item_attrs(__TopXMLNS, [], Affiliation, Role, Jid, Nick) -> {decode_muc_user_item_attr_affiliation(__TopXMLNS, Affiliation), decode_muc_user_item_attr_role(__TopXMLNS, Role), decode_muc_user_item_attr_jid(__TopXMLNS, Jid), decode_muc_user_item_attr_nick(__TopXMLNS, Nick)}. encode_muc_user_item({muc_item, Actor, Continue, Reason, Affiliation, Role, Jid, Nick}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_user_item_$actor'(Actor, 'encode_muc_user_item_$continue'(Continue, 'encode_muc_user_item_$reason'(Reason, [])))), _attrs = encode_muc_user_item_attr_nick(Nick, encode_muc_user_item_attr_jid(Jid, encode_muc_user_item_attr_role(Role, encode_muc_user_item_attr_affiliation(Affiliation, _xmlns_attrs)))), {xmlel, <<"item">>, _attrs, _els}. 'encode_muc_user_item_$actor'(undefined, _acc) -> _acc; 'encode_muc_user_item_$actor'(Actor, _acc) -> [encode_muc_user_actor(Actor, []) | _acc]. 'encode_muc_user_item_$continue'(undefined, _acc) -> _acc; 'encode_muc_user_item_$continue'(Continue, _acc) -> [encode_muc_user_continue(Continue, []) | _acc]. 'encode_muc_user_item_$reason'(undefined, _acc) -> _acc; 'encode_muc_user_item_$reason'(Reason, _acc) -> [encode_muc_user_reason(Reason, []) | _acc]. decode_muc_user_item_attr_affiliation(__TopXMLNS, undefined) -> undefined; decode_muc_user_item_attr_affiliation(__TopXMLNS, _val) -> case catch dec_enum(_val, [admin, member, none, outcast, owner]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"affiliation">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_item_attr_affiliation(undefined, _acc) -> _acc; encode_muc_user_item_attr_affiliation(_val, _acc) -> [{<<"affiliation">>, enc_enum(_val)} | _acc]. decode_muc_user_item_attr_role(__TopXMLNS, undefined) -> undefined; decode_muc_user_item_attr_role(__TopXMLNS, _val) -> case catch dec_enum(_val, [moderator, none, participant, visitor]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"role">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_item_attr_role(undefined, _acc) -> _acc; encode_muc_user_item_attr_role(_val, _acc) -> [{<<"role">>, enc_enum(_val)} | _acc]. decode_muc_user_item_attr_jid(__TopXMLNS, undefined) -> undefined; decode_muc_user_item_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_item_attr_jid(undefined, _acc) -> _acc; encode_muc_user_item_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_muc_user_item_attr_nick(__TopXMLNS, undefined) -> undefined; decode_muc_user_item_attr_nick(__TopXMLNS, _val) -> _val. encode_muc_user_item_attr_nick(undefined, _acc) -> _acc; encode_muc_user_item_attr_nick(_val, _acc) -> [{<<"nick">>, _val} | _acc]. decode_muc_user_status(__TopXMLNS, __IgnoreEls, {xmlel, <<"status">>, _attrs, _els}) -> Code = decode_muc_user_status_attrs(__TopXMLNS, _attrs, undefined), Code. decode_muc_user_status_attrs(__TopXMLNS, [{<<"code">>, _val} | _attrs], _Code) -> decode_muc_user_status_attrs(__TopXMLNS, _attrs, _val); decode_muc_user_status_attrs(__TopXMLNS, [_ | _attrs], Code) -> decode_muc_user_status_attrs(__TopXMLNS, _attrs, Code); decode_muc_user_status_attrs(__TopXMLNS, [], Code) -> decode_muc_user_status_attr_code(__TopXMLNS, Code). encode_muc_user_status(Code, _xmlns_attrs) -> _els = [], _attrs = encode_muc_user_status_attr_code(Code, _xmlns_attrs), {xmlel, <<"status">>, _attrs, _els}. decode_muc_user_status_attr_code(__TopXMLNS, undefined) -> undefined; decode_muc_user_status_attr_code(__TopXMLNS, _val) -> case catch dec_int(_val, 100, 999) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"code">>, <<"status">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_status_attr_code(undefined, _acc) -> _acc; encode_muc_user_status_attr_code(_val, _acc) -> [{<<"code">>, enc_int(_val)} | _acc]. decode_muc_user_continue(__TopXMLNS, __IgnoreEls, {xmlel, <<"continue">>, _attrs, _els}) -> Thread = decode_muc_user_continue_attrs(__TopXMLNS, _attrs, undefined), Thread. decode_muc_user_continue_attrs(__TopXMLNS, [{<<"thread">>, _val} | _attrs], _Thread) -> decode_muc_user_continue_attrs(__TopXMLNS, _attrs, _val); decode_muc_user_continue_attrs(__TopXMLNS, [_ | _attrs], Thread) -> decode_muc_user_continue_attrs(__TopXMLNS, _attrs, Thread); decode_muc_user_continue_attrs(__TopXMLNS, [], Thread) -> decode_muc_user_continue_attr_thread(__TopXMLNS, Thread). encode_muc_user_continue(Thread, _xmlns_attrs) -> _els = [], _attrs = encode_muc_user_continue_attr_thread(Thread, _xmlns_attrs), {xmlel, <<"continue">>, _attrs, _els}. decode_muc_user_continue_attr_thread(__TopXMLNS, undefined) -> undefined; decode_muc_user_continue_attr_thread(__TopXMLNS, _val) -> _val. encode_muc_user_continue_attr_thread(undefined, _acc) -> _acc; encode_muc_user_continue_attr_thread(_val, _acc) -> [{<<"thread">>, _val} | _acc]. decode_muc_user_actor(__TopXMLNS, __IgnoreEls, {xmlel, <<"actor">>, _attrs, _els}) -> {Jid, Nick} = decode_muc_user_actor_attrs(__TopXMLNS, _attrs, undefined, undefined), {muc_actor, Jid, Nick}. decode_muc_user_actor_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid, Nick) -> decode_muc_user_actor_attrs(__TopXMLNS, _attrs, _val, Nick); decode_muc_user_actor_attrs(__TopXMLNS, [{<<"nick">>, _val} | _attrs], Jid, _Nick) -> decode_muc_user_actor_attrs(__TopXMLNS, _attrs, Jid, _val); decode_muc_user_actor_attrs(__TopXMLNS, [_ | _attrs], Jid, Nick) -> decode_muc_user_actor_attrs(__TopXMLNS, _attrs, Jid, Nick); decode_muc_user_actor_attrs(__TopXMLNS, [], Jid, Nick) -> {decode_muc_user_actor_attr_jid(__TopXMLNS, Jid), decode_muc_user_actor_attr_nick(__TopXMLNS, Nick)}. encode_muc_user_actor({muc_actor, Jid, Nick}, _xmlns_attrs) -> _els = [], _attrs = encode_muc_user_actor_attr_nick(Nick, encode_muc_user_actor_attr_jid(Jid, _xmlns_attrs)), {xmlel, <<"actor">>, _attrs, _els}. decode_muc_user_actor_attr_jid(__TopXMLNS, undefined) -> undefined; decode_muc_user_actor_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"actor">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_actor_attr_jid(undefined, _acc) -> _acc; encode_muc_user_actor_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_muc_user_actor_attr_nick(__TopXMLNS, undefined) -> undefined; decode_muc_user_actor_attr_nick(__TopXMLNS, _val) -> _val. encode_muc_user_actor_attr_nick(undefined, _acc) -> _acc; encode_muc_user_actor_attr_nick(_val, _acc) -> [{<<"nick">>, _val} | _acc]. decode_muc_user_invite(__TopXMLNS, __IgnoreEls, {xmlel, <<"invite">>, _attrs, _els}) -> Reason = decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls, _els, undefined), {To, From} = decode_muc_user_invite_attrs(__TopXMLNS, _attrs, undefined, undefined), {muc_invite, Reason, From, To}. decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls, [], Reason) -> Reason; decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"reason">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls, _els, decode_muc_user_reason(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls, [_ | _els], Reason) -> decode_muc_user_invite_els(__TopXMLNS, __IgnoreEls, _els, Reason). decode_muc_user_invite_attrs(__TopXMLNS, [{<<"to">>, _val} | _attrs], _To, From) -> decode_muc_user_invite_attrs(__TopXMLNS, _attrs, _val, From); decode_muc_user_invite_attrs(__TopXMLNS, [{<<"from">>, _val} | _attrs], To, _From) -> decode_muc_user_invite_attrs(__TopXMLNS, _attrs, To, _val); decode_muc_user_invite_attrs(__TopXMLNS, [_ | _attrs], To, From) -> decode_muc_user_invite_attrs(__TopXMLNS, _attrs, To, From); decode_muc_user_invite_attrs(__TopXMLNS, [], To, From) -> {decode_muc_user_invite_attr_to(__TopXMLNS, To), decode_muc_user_invite_attr_from(__TopXMLNS, From)}. encode_muc_user_invite({muc_invite, Reason, From, To}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_user_invite_$reason'(Reason, [])), _attrs = encode_muc_user_invite_attr_from(From, encode_muc_user_invite_attr_to(To, _xmlns_attrs)), {xmlel, <<"invite">>, _attrs, _els}. 'encode_muc_user_invite_$reason'(undefined, _acc) -> _acc; 'encode_muc_user_invite_$reason'(Reason, _acc) -> [encode_muc_user_reason(Reason, []) | _acc]. decode_muc_user_invite_attr_to(__TopXMLNS, undefined) -> undefined; decode_muc_user_invite_attr_to(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"to">>, <<"invite">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_invite_attr_to(undefined, _acc) -> _acc; encode_muc_user_invite_attr_to(_val, _acc) -> [{<<"to">>, enc_jid(_val)} | _acc]. decode_muc_user_invite_attr_from(__TopXMLNS, undefined) -> undefined; decode_muc_user_invite_attr_from(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"from">>, <<"invite">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_invite_attr_from(undefined, _acc) -> _acc; encode_muc_user_invite_attr_from(_val, _acc) -> [{<<"from">>, enc_jid(_val)} | _acc]. decode_muc_user_destroy(__TopXMLNS, __IgnoreEls, {xmlel, <<"destroy">>, _attrs, _els}) -> Reason = decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls, _els, undefined), Jid = decode_muc_user_destroy_attrs(__TopXMLNS, _attrs, undefined), {muc_user_destroy, Reason, Jid}. decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls, [], Reason) -> Reason; decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"reason">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls, _els, decode_muc_user_reason(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls, [_ | _els], Reason) -> decode_muc_user_destroy_els(__TopXMLNS, __IgnoreEls, _els, Reason). decode_muc_user_destroy_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid) -> decode_muc_user_destroy_attrs(__TopXMLNS, _attrs, _val); decode_muc_user_destroy_attrs(__TopXMLNS, [_ | _attrs], Jid) -> decode_muc_user_destroy_attrs(__TopXMLNS, _attrs, Jid); decode_muc_user_destroy_attrs(__TopXMLNS, [], Jid) -> decode_muc_user_destroy_attr_jid(__TopXMLNS, Jid). encode_muc_user_destroy({muc_user_destroy, Reason, Jid}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_user_destroy_$reason'(Reason, [])), _attrs = encode_muc_user_destroy_attr_jid(Jid, _xmlns_attrs), {xmlel, <<"destroy">>, _attrs, _els}. 'encode_muc_user_destroy_$reason'(undefined, _acc) -> _acc; 'encode_muc_user_destroy_$reason'(Reason, _acc) -> [encode_muc_user_reason(Reason, []) | _acc]. decode_muc_user_destroy_attr_jid(__TopXMLNS, undefined) -> undefined; decode_muc_user_destroy_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"destroy">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_destroy_attr_jid(undefined, _acc) -> _acc; encode_muc_user_destroy_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_muc_user_decline(__TopXMLNS, __IgnoreEls, {xmlel, <<"decline">>, _attrs, _els}) -> Reason = decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls, _els, undefined), {To, From} = decode_muc_user_decline_attrs(__TopXMLNS, _attrs, undefined, undefined), {muc_decline, Reason, From, To}. decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls, [], Reason) -> Reason; decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"reason">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls, _els, decode_muc_user_reason(__TopXMLNS, __IgnoreEls, _el)); true -> decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls, [_ | _els], Reason) -> decode_muc_user_decline_els(__TopXMLNS, __IgnoreEls, _els, Reason). decode_muc_user_decline_attrs(__TopXMLNS, [{<<"to">>, _val} | _attrs], _To, From) -> decode_muc_user_decline_attrs(__TopXMLNS, _attrs, _val, From); decode_muc_user_decline_attrs(__TopXMLNS, [{<<"from">>, _val} | _attrs], To, _From) -> decode_muc_user_decline_attrs(__TopXMLNS, _attrs, To, _val); decode_muc_user_decline_attrs(__TopXMLNS, [_ | _attrs], To, From) -> decode_muc_user_decline_attrs(__TopXMLNS, _attrs, To, From); decode_muc_user_decline_attrs(__TopXMLNS, [], To, From) -> {decode_muc_user_decline_attr_to(__TopXMLNS, To), decode_muc_user_decline_attr_from(__TopXMLNS, From)}. encode_muc_user_decline({muc_decline, Reason, From, To}, _xmlns_attrs) -> _els = lists:reverse('encode_muc_user_decline_$reason'(Reason, [])), _attrs = encode_muc_user_decline_attr_from(From, encode_muc_user_decline_attr_to(To, _xmlns_attrs)), {xmlel, <<"decline">>, _attrs, _els}. 'encode_muc_user_decline_$reason'(undefined, _acc) -> _acc; 'encode_muc_user_decline_$reason'(Reason, _acc) -> [encode_muc_user_reason(Reason, []) | _acc]. decode_muc_user_decline_attr_to(__TopXMLNS, undefined) -> undefined; decode_muc_user_decline_attr_to(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"to">>, <<"decline">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_decline_attr_to(undefined, _acc) -> _acc; encode_muc_user_decline_attr_to(_val, _acc) -> [{<<"to">>, enc_jid(_val)} | _acc]. decode_muc_user_decline_attr_from(__TopXMLNS, undefined) -> undefined; decode_muc_user_decline_attr_from(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"from">>, <<"decline">>, __TopXMLNS}}); _res -> _res end. encode_muc_user_decline_attr_from(undefined, _acc) -> _acc; encode_muc_user_decline_attr_from(_val, _acc) -> [{<<"from">>, enc_jid(_val)} | _acc]. decode_muc_user_reason(__TopXMLNS, __IgnoreEls, {xmlel, <<"reason">>, _attrs, _els}) -> Cdata = decode_muc_user_reason_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_muc_user_reason_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_muc_user_reason_cdata(__TopXMLNS, Cdata); decode_muc_user_reason_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_muc_user_reason_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_muc_user_reason_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_muc_user_reason_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_muc_user_reason(Cdata, _xmlns_attrs) -> _els = encode_muc_user_reason_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"reason">>, _attrs, _els}. decode_muc_user_reason_cdata(__TopXMLNS, <<>>) -> undefined; decode_muc_user_reason_cdata(__TopXMLNS, _val) -> _val. encode_muc_user_reason_cdata(undefined, _acc) -> _acc; encode_muc_user_reason_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_muc_history(__TopXMLNS, __IgnoreEls, {xmlel, <<"history">>, _attrs, _els}) -> {Maxchars, Maxstanzas, Seconds, Since} = decode_muc_history_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined), {muc_history, Maxchars, Maxstanzas, Seconds, Since}. decode_muc_history_attrs(__TopXMLNS, [{<<"maxchars">>, _val} | _attrs], _Maxchars, Maxstanzas, Seconds, Since) -> decode_muc_history_attrs(__TopXMLNS, _attrs, _val, Maxstanzas, Seconds, Since); decode_muc_history_attrs(__TopXMLNS, [{<<"maxstanzas">>, _val} | _attrs], Maxchars, _Maxstanzas, Seconds, Since) -> decode_muc_history_attrs(__TopXMLNS, _attrs, Maxchars, _val, Seconds, Since); decode_muc_history_attrs(__TopXMLNS, [{<<"seconds">>, _val} | _attrs], Maxchars, Maxstanzas, _Seconds, Since) -> decode_muc_history_attrs(__TopXMLNS, _attrs, Maxchars, Maxstanzas, _val, Since); decode_muc_history_attrs(__TopXMLNS, [{<<"since">>, _val} | _attrs], Maxchars, Maxstanzas, Seconds, _Since) -> decode_muc_history_attrs(__TopXMLNS, _attrs, Maxchars, Maxstanzas, Seconds, _val); decode_muc_history_attrs(__TopXMLNS, [_ | _attrs], Maxchars, Maxstanzas, Seconds, Since) -> decode_muc_history_attrs(__TopXMLNS, _attrs, Maxchars, Maxstanzas, Seconds, Since); decode_muc_history_attrs(__TopXMLNS, [], Maxchars, Maxstanzas, Seconds, Since) -> {decode_muc_history_attr_maxchars(__TopXMLNS, Maxchars), decode_muc_history_attr_maxstanzas(__TopXMLNS, Maxstanzas), decode_muc_history_attr_seconds(__TopXMLNS, Seconds), decode_muc_history_attr_since(__TopXMLNS, Since)}. encode_muc_history({muc_history, Maxchars, Maxstanzas, Seconds, Since}, _xmlns_attrs) -> _els = [], _attrs = encode_muc_history_attr_since(Since, encode_muc_history_attr_seconds(Seconds, encode_muc_history_attr_maxstanzas(Maxstanzas, encode_muc_history_attr_maxchars(Maxchars, _xmlns_attrs)))), {xmlel, <<"history">>, _attrs, _els}. decode_muc_history_attr_maxchars(__TopXMLNS, undefined) -> undefined; decode_muc_history_attr_maxchars(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"maxchars">>, <<"history">>, __TopXMLNS}}); _res -> _res end. encode_muc_history_attr_maxchars(undefined, _acc) -> _acc; encode_muc_history_attr_maxchars(_val, _acc) -> [{<<"maxchars">>, enc_int(_val)} | _acc]. decode_muc_history_attr_maxstanzas(__TopXMLNS, undefined) -> undefined; decode_muc_history_attr_maxstanzas(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"maxstanzas">>, <<"history">>, __TopXMLNS}}); _res -> _res end. encode_muc_history_attr_maxstanzas(undefined, _acc) -> _acc; encode_muc_history_attr_maxstanzas(_val, _acc) -> [{<<"maxstanzas">>, enc_int(_val)} | _acc]. decode_muc_history_attr_seconds(__TopXMLNS, undefined) -> undefined; decode_muc_history_attr_seconds(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"seconds">>, <<"history">>, __TopXMLNS}}); _res -> _res end. encode_muc_history_attr_seconds(undefined, _acc) -> _acc; encode_muc_history_attr_seconds(_val, _acc) -> [{<<"seconds">>, enc_int(_val)} | _acc]. decode_muc_history_attr_since(__TopXMLNS, undefined) -> undefined; decode_muc_history_attr_since(__TopXMLNS, _val) -> case catch dec_utc(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"since">>, <<"history">>, __TopXMLNS}}); _res -> _res end. encode_muc_history_attr_since(undefined, _acc) -> _acc; encode_muc_history_attr_since(_val, _acc) -> [{<<"since">>, enc_utc(_val)} | _acc]. decode_bytestreams(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> {Hosts, Used, Activate} = decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els, [], undefined, undefined), {Dstaddr, Sid, Mode} = decode_bytestreams_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {bytestreams, Hosts, Used, Activate, Dstaddr, Mode, Sid}. decode_bytestreams_els(__TopXMLNS, __IgnoreEls, [], Hosts, Used, Activate) -> {lists:reverse(Hosts), Used, Activate}; decode_bytestreams_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"streamhost">>, _attrs, _} = _el | _els], Hosts, Used, Activate) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els, [decode_bytestreams_streamhost(__TopXMLNS, __IgnoreEls, _el) | Hosts], Used, Activate); true -> decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els, Hosts, Used, Activate) end; decode_bytestreams_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"streamhost-used">>, _attrs, _} = _el | _els], Hosts, Used, Activate) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els, Hosts, decode_bytestreams_streamhost_used(__TopXMLNS, __IgnoreEls, _el), Activate); true -> decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els, Hosts, Used, Activate) end; decode_bytestreams_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"activate">>, _attrs, _} = _el | _els], Hosts, Used, Activate) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els, Hosts, Used, decode_bytestreams_activate(__TopXMLNS, __IgnoreEls, _el)); true -> decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els, Hosts, Used, Activate) end; decode_bytestreams_els(__TopXMLNS, __IgnoreEls, [_ | _els], Hosts, Used, Activate) -> decode_bytestreams_els(__TopXMLNS, __IgnoreEls, _els, Hosts, Used, Activate). decode_bytestreams_attrs(__TopXMLNS, [{<<"dstaddr">>, _val} | _attrs], _Dstaddr, Sid, Mode) -> decode_bytestreams_attrs(__TopXMLNS, _attrs, _val, Sid, Mode); decode_bytestreams_attrs(__TopXMLNS, [{<<"sid">>, _val} | _attrs], Dstaddr, _Sid, Mode) -> decode_bytestreams_attrs(__TopXMLNS, _attrs, Dstaddr, _val, Mode); decode_bytestreams_attrs(__TopXMLNS, [{<<"mode">>, _val} | _attrs], Dstaddr, Sid, _Mode) -> decode_bytestreams_attrs(__TopXMLNS, _attrs, Dstaddr, Sid, _val); decode_bytestreams_attrs(__TopXMLNS, [_ | _attrs], Dstaddr, Sid, Mode) -> decode_bytestreams_attrs(__TopXMLNS, _attrs, Dstaddr, Sid, Mode); decode_bytestreams_attrs(__TopXMLNS, [], Dstaddr, Sid, Mode) -> {decode_bytestreams_attr_dstaddr(__TopXMLNS, Dstaddr), decode_bytestreams_attr_sid(__TopXMLNS, Sid), decode_bytestreams_attr_mode(__TopXMLNS, Mode)}. encode_bytestreams({bytestreams, Hosts, Used, Activate, Dstaddr, Mode, Sid}, _xmlns_attrs) -> _els = lists:reverse('encode_bytestreams_$hosts'(Hosts, 'encode_bytestreams_$used'(Used, 'encode_bytestreams_$activate'(Activate, [])))), _attrs = encode_bytestreams_attr_mode(Mode, encode_bytestreams_attr_sid(Sid, encode_bytestreams_attr_dstaddr(Dstaddr, _xmlns_attrs))), {xmlel, <<"query">>, _attrs, _els}. 'encode_bytestreams_$hosts'([], _acc) -> _acc; 'encode_bytestreams_$hosts'([Hosts | _els], _acc) -> 'encode_bytestreams_$hosts'(_els, [encode_bytestreams_streamhost(Hosts, []) | _acc]). 'encode_bytestreams_$used'(undefined, _acc) -> _acc; 'encode_bytestreams_$used'(Used, _acc) -> [encode_bytestreams_streamhost_used(Used, []) | _acc]. 'encode_bytestreams_$activate'(undefined, _acc) -> _acc; 'encode_bytestreams_$activate'(Activate, _acc) -> [encode_bytestreams_activate(Activate, []) | _acc]. decode_bytestreams_attr_dstaddr(__TopXMLNS, undefined) -> undefined; decode_bytestreams_attr_dstaddr(__TopXMLNS, _val) -> _val. encode_bytestreams_attr_dstaddr(undefined, _acc) -> _acc; encode_bytestreams_attr_dstaddr(_val, _acc) -> [{<<"dstaddr">>, _val} | _acc]. decode_bytestreams_attr_sid(__TopXMLNS, undefined) -> undefined; decode_bytestreams_attr_sid(__TopXMLNS, _val) -> _val. encode_bytestreams_attr_sid(undefined, _acc) -> _acc; encode_bytestreams_attr_sid(_val, _acc) -> [{<<"sid">>, _val} | _acc]. decode_bytestreams_attr_mode(__TopXMLNS, undefined) -> tcp; decode_bytestreams_attr_mode(__TopXMLNS, _val) -> case catch dec_enum(_val, [tcp, udp]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"mode">>, <<"query">>, __TopXMLNS}}); _res -> _res end. encode_bytestreams_attr_mode(tcp, _acc) -> _acc; encode_bytestreams_attr_mode(_val, _acc) -> [{<<"mode">>, enc_enum(_val)} | _acc]. decode_bytestreams_activate(__TopXMLNS, __IgnoreEls, {xmlel, <<"activate">>, _attrs, _els}) -> Cdata = decode_bytestreams_activate_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_bytestreams_activate_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_bytestreams_activate_cdata(__TopXMLNS, Cdata); decode_bytestreams_activate_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_bytestreams_activate_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_bytestreams_activate_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_bytestreams_activate_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_bytestreams_activate(Cdata, _xmlns_attrs) -> _els = encode_bytestreams_activate_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"activate">>, _attrs, _els}. decode_bytestreams_activate_cdata(__TopXMLNS, <<>>) -> undefined; decode_bytestreams_activate_cdata(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"activate">>, __TopXMLNS}}); _res -> _res end. encode_bytestreams_activate_cdata(undefined, _acc) -> _acc; encode_bytestreams_activate_cdata(_val, _acc) -> [{xmlcdata, enc_jid(_val)} | _acc]. decode_bytestreams_streamhost_used(__TopXMLNS, __IgnoreEls, {xmlel, <<"streamhost-used">>, _attrs, _els}) -> Jid = decode_bytestreams_streamhost_used_attrs(__TopXMLNS, _attrs, undefined), Jid. decode_bytestreams_streamhost_used_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid) -> decode_bytestreams_streamhost_used_attrs(__TopXMLNS, _attrs, _val); decode_bytestreams_streamhost_used_attrs(__TopXMLNS, [_ | _attrs], Jid) -> decode_bytestreams_streamhost_used_attrs(__TopXMLNS, _attrs, Jid); decode_bytestreams_streamhost_used_attrs(__TopXMLNS, [], Jid) -> decode_bytestreams_streamhost_used_attr_jid(__TopXMLNS, Jid). encode_bytestreams_streamhost_used(Jid, _xmlns_attrs) -> _els = [], _attrs = encode_bytestreams_streamhost_used_attr_jid(Jid, _xmlns_attrs), {xmlel, <<"streamhost-used">>, _attrs, _els}. decode_bytestreams_streamhost_used_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"streamhost-used">>, __TopXMLNS}}); decode_bytestreams_streamhost_used_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"streamhost-used">>, __TopXMLNS}}); _res -> _res end. encode_bytestreams_streamhost_used_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_bytestreams_streamhost(__TopXMLNS, __IgnoreEls, {xmlel, <<"streamhost">>, _attrs, _els}) -> {Jid, Host, Port} = decode_bytestreams_streamhost_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {streamhost, Jid, Host, Port}. decode_bytestreams_streamhost_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid, Host, Port) -> decode_bytestreams_streamhost_attrs(__TopXMLNS, _attrs, _val, Host, Port); decode_bytestreams_streamhost_attrs(__TopXMLNS, [{<<"host">>, _val} | _attrs], Jid, _Host, Port) -> decode_bytestreams_streamhost_attrs(__TopXMLNS, _attrs, Jid, _val, Port); decode_bytestreams_streamhost_attrs(__TopXMLNS, [{<<"port">>, _val} | _attrs], Jid, Host, _Port) -> decode_bytestreams_streamhost_attrs(__TopXMLNS, _attrs, Jid, Host, _val); decode_bytestreams_streamhost_attrs(__TopXMLNS, [_ | _attrs], Jid, Host, Port) -> decode_bytestreams_streamhost_attrs(__TopXMLNS, _attrs, Jid, Host, Port); decode_bytestreams_streamhost_attrs(__TopXMLNS, [], Jid, Host, Port) -> {decode_bytestreams_streamhost_attr_jid(__TopXMLNS, Jid), decode_bytestreams_streamhost_attr_host(__TopXMLNS, Host), decode_bytestreams_streamhost_attr_port(__TopXMLNS, Port)}. encode_bytestreams_streamhost({streamhost, Jid, Host, Port}, _xmlns_attrs) -> _els = [], _attrs = encode_bytestreams_streamhost_attr_port(Port, encode_bytestreams_streamhost_attr_host(Host, encode_bytestreams_streamhost_attr_jid(Jid, _xmlns_attrs))), {xmlel, <<"streamhost">>, _attrs, _els}. decode_bytestreams_streamhost_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"streamhost">>, __TopXMLNS}}); decode_bytestreams_streamhost_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"streamhost">>, __TopXMLNS}}); _res -> _res end. encode_bytestreams_streamhost_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_bytestreams_streamhost_attr_host(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"host">>, <<"streamhost">>, __TopXMLNS}}); decode_bytestreams_streamhost_attr_host(__TopXMLNS, _val) -> _val. encode_bytestreams_streamhost_attr_host(_val, _acc) -> [{<<"host">>, _val} | _acc]. decode_bytestreams_streamhost_attr_port(__TopXMLNS, undefined) -> 1080; decode_bytestreams_streamhost_attr_port(__TopXMLNS, _val) -> case catch dec_int(_val, 0, 65535) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"port">>, <<"streamhost">>, __TopXMLNS}}); _res -> _res end. encode_bytestreams_streamhost_attr_port(1080, _acc) -> _acc; encode_bytestreams_streamhost_attr_port(_val, _acc) -> [{<<"port">>, enc_int(_val)} | _acc]. decode_delay(__TopXMLNS, __IgnoreEls, {xmlel, <<"delay">>, _attrs, _els}) -> {Stamp, From} = decode_delay_attrs(__TopXMLNS, _attrs, undefined, undefined), {delay, Stamp, From}. decode_delay_attrs(__TopXMLNS, [{<<"stamp">>, _val} | _attrs], _Stamp, From) -> decode_delay_attrs(__TopXMLNS, _attrs, _val, From); decode_delay_attrs(__TopXMLNS, [{<<"from">>, _val} | _attrs], Stamp, _From) -> decode_delay_attrs(__TopXMLNS, _attrs, Stamp, _val); decode_delay_attrs(__TopXMLNS, [_ | _attrs], Stamp, From) -> decode_delay_attrs(__TopXMLNS, _attrs, Stamp, From); decode_delay_attrs(__TopXMLNS, [], Stamp, From) -> {decode_delay_attr_stamp(__TopXMLNS, Stamp), decode_delay_attr_from(__TopXMLNS, From)}. encode_delay({delay, Stamp, From}, _xmlns_attrs) -> _els = [], _attrs = encode_delay_attr_from(From, encode_delay_attr_stamp(Stamp, _xmlns_attrs)), {xmlel, <<"delay">>, _attrs, _els}. decode_delay_attr_stamp(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"stamp">>, <<"delay">>, __TopXMLNS}}); decode_delay_attr_stamp(__TopXMLNS, _val) -> case catch dec_utc(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"stamp">>, <<"delay">>, __TopXMLNS}}); _res -> _res end. encode_delay_attr_stamp(_val, _acc) -> [{<<"stamp">>, enc_utc(_val)} | _acc]. decode_delay_attr_from(__TopXMLNS, undefined) -> undefined; decode_delay_attr_from(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"from">>, <<"delay">>, __TopXMLNS}}); _res -> _res end. encode_delay_attr_from(undefined, _acc) -> _acc; encode_delay_attr_from(_val, _acc) -> [{<<"from">>, enc_jid(_val)} | _acc]. decode_chatstate_paused(__TopXMLNS, __IgnoreEls, {xmlel, <<"paused">>, _attrs, _els}) -> {chatstate, paused}. encode_chatstate_paused({chatstate, paused}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"paused">>, _attrs, _els}. decode_chatstate_inactive(__TopXMLNS, __IgnoreEls, {xmlel, <<"inactive">>, _attrs, _els}) -> {chatstate, inactive}. encode_chatstate_inactive({chatstate, inactive}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"inactive">>, _attrs, _els}. decode_chatstate_gone(__TopXMLNS, __IgnoreEls, {xmlel, <<"gone">>, _attrs, _els}) -> {chatstate, gone}. encode_chatstate_gone({chatstate, gone}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"gone">>, _attrs, _els}. decode_chatstate_composing(__TopXMLNS, __IgnoreEls, {xmlel, <<"composing">>, _attrs, _els}) -> {chatstate, composing}. encode_chatstate_composing({chatstate, composing}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"composing">>, _attrs, _els}. decode_chatstate_active(__TopXMLNS, __IgnoreEls, {xmlel, <<"active">>, _attrs, _els}) -> {chatstate, active}. encode_chatstate_active({chatstate, active}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"active">>, _attrs, _els}. decode_shim_headers(__TopXMLNS, __IgnoreEls, {xmlel, <<"headers">>, _attrs, _els}) -> Headers = decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els, []), {shim, Headers}. decode_shim_headers_els(__TopXMLNS, __IgnoreEls, [], Headers) -> lists:reverse(Headers); decode_shim_headers_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"header">>, _attrs, _} = _el | _els], Headers) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els, [decode_shim_header(__TopXMLNS, __IgnoreEls, _el) | Headers]); true -> decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els, Headers) end; decode_shim_headers_els(__TopXMLNS, __IgnoreEls, [_ | _els], Headers) -> decode_shim_headers_els(__TopXMLNS, __IgnoreEls, _els, Headers). encode_shim_headers({shim, Headers}, _xmlns_attrs) -> _els = lists:reverse('encode_shim_headers_$headers'(Headers, [])), _attrs = _xmlns_attrs, {xmlel, <<"headers">>, _attrs, _els}. 'encode_shim_headers_$headers'([], _acc) -> _acc; 'encode_shim_headers_$headers'([Headers | _els], _acc) -> 'encode_shim_headers_$headers'(_els, [encode_shim_header(Headers, []) | _acc]). decode_shim_header(__TopXMLNS, __IgnoreEls, {xmlel, <<"header">>, _attrs, _els}) -> Cdata = decode_shim_header_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Name = decode_shim_header_attrs(__TopXMLNS, _attrs, undefined), {Name, Cdata}. decode_shim_header_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_shim_header_cdata(__TopXMLNS, Cdata); decode_shim_header_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_shim_header_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_shim_header_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_shim_header_els(__TopXMLNS, __IgnoreEls, _els, Cdata). decode_shim_header_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], _Name) -> decode_shim_header_attrs(__TopXMLNS, _attrs, _val); decode_shim_header_attrs(__TopXMLNS, [_ | _attrs], Name) -> decode_shim_header_attrs(__TopXMLNS, _attrs, Name); decode_shim_header_attrs(__TopXMLNS, [], Name) -> decode_shim_header_attr_name(__TopXMLNS, Name). encode_shim_header({Name, Cdata}, _xmlns_attrs) -> _els = encode_shim_header_cdata(Cdata, []), _attrs = encode_shim_header_attr_name(Name, _xmlns_attrs), {xmlel, <<"header">>, _attrs, _els}. decode_shim_header_attr_name(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"name">>, <<"header">>, __TopXMLNS}}); decode_shim_header_attr_name(__TopXMLNS, _val) -> _val. encode_shim_header_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_shim_header_cdata(__TopXMLNS, <<>>) -> undefined; decode_shim_header_cdata(__TopXMLNS, _val) -> _val. encode_shim_header_cdata(undefined, _acc) -> _acc; encode_shim_header_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_pubsub(__TopXMLNS, __IgnoreEls, {xmlel, <<"pubsub">>, _attrs, _els}) -> {Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish} = decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), {pubsub, Subscriptions, Affiliations, Publish, Subscribe, Unsubscribe, Options, Items, Retract}. decode_pubsub_els(__TopXMLNS, __IgnoreEls, [], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> {Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish}; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"subscriptions">>, _attrs, _} = _el | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, decode_pubsub_subscriptions(__TopXMLNS, __IgnoreEls, _el), Retract, Unsubscribe, Subscribe, Publish); true -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"affiliations">>, _attrs, _} = _el | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, decode_pubsub_affiliations(__TopXMLNS, __IgnoreEls, _el), Subscriptions, Retract, Unsubscribe, Subscribe, Publish); true -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"subscribe">>, _attrs, _} = _el | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, decode_pubsub_subscribe(__TopXMLNS, __IgnoreEls, _el), Publish); true -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"unsubscribe">>, _attrs, _} = _el | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, decode_pubsub_unsubscribe(__TopXMLNS, __IgnoreEls, _el), Subscribe, Publish); true -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"options">>, _attrs, _} = _el | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, decode_pubsub_options(__TopXMLNS, __IgnoreEls, _el), Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish); true -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"items">>, _attrs, _} = _el | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, decode_pubsub_items(__TopXMLNS, __IgnoreEls, _el), Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish); true -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"retract">>, _attrs, _} = _el | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, decode_pubsub_retract(__TopXMLNS, __IgnoreEls, _el), Unsubscribe, Subscribe, Publish); true -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"publish">>, _attrs, _} = _el | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, decode_pubsub_publish(__TopXMLNS, __IgnoreEls, _el)); true -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) end; decode_pubsub_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish) -> decode_pubsub_els(__TopXMLNS, __IgnoreEls, _els, Items, Options, Affiliations, Subscriptions, Retract, Unsubscribe, Subscribe, Publish). encode_pubsub({pubsub, Subscriptions, Affiliations, Publish, Subscribe, Unsubscribe, Options, Items, Retract}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_$items'(Items, 'encode_pubsub_$options'(Options, 'encode_pubsub_$affiliations'(Affiliations, 'encode_pubsub_$subscriptions'(Subscriptions, 'encode_pubsub_$retract'(Retract, 'encode_pubsub_$unsubscribe'(Unsubscribe, 'encode_pubsub_$subscribe'(Subscribe, 'encode_pubsub_$publish'(Publish, []))))))))), _attrs = _xmlns_attrs, {xmlel, <<"pubsub">>, _attrs, _els}. 'encode_pubsub_$items'(undefined, _acc) -> _acc; 'encode_pubsub_$items'(Items, _acc) -> [encode_pubsub_items(Items, []) | _acc]. 'encode_pubsub_$options'(undefined, _acc) -> _acc; 'encode_pubsub_$options'(Options, _acc) -> [encode_pubsub_options(Options, []) | _acc]. 'encode_pubsub_$affiliations'(undefined, _acc) -> _acc; 'encode_pubsub_$affiliations'(Affiliations, _acc) -> [encode_pubsub_affiliations(Affiliations, []) | _acc]. 'encode_pubsub_$subscriptions'(undefined, _acc) -> _acc; 'encode_pubsub_$subscriptions'(Subscriptions, _acc) -> [encode_pubsub_subscriptions(Subscriptions, []) | _acc]. 'encode_pubsub_$retract'(undefined, _acc) -> _acc; 'encode_pubsub_$retract'(Retract, _acc) -> [encode_pubsub_retract(Retract, []) | _acc]. 'encode_pubsub_$unsubscribe'(undefined, _acc) -> _acc; 'encode_pubsub_$unsubscribe'(Unsubscribe, _acc) -> [encode_pubsub_unsubscribe(Unsubscribe, []) | _acc]. 'encode_pubsub_$subscribe'(undefined, _acc) -> _acc; 'encode_pubsub_$subscribe'(Subscribe, _acc) -> [encode_pubsub_subscribe(Subscribe, []) | _acc]. 'encode_pubsub_$publish'(undefined, _acc) -> _acc; 'encode_pubsub_$publish'(Publish, _acc) -> [encode_pubsub_publish(Publish, []) | _acc]. decode_pubsub_retract(__TopXMLNS, __IgnoreEls, {xmlel, <<"retract">>, _attrs, _els}) -> Items = decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els, []), {Node, Notify} = decode_pubsub_retract_attrs(__TopXMLNS, _attrs, undefined, undefined), {pubsub_retract, Node, Notify, Items}. decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_item(__TopXMLNS, __IgnoreEls, _el) | Items]); true -> decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_pubsub_retract_els(__TopXMLNS, __IgnoreEls, _els, Items). decode_pubsub_retract_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node, Notify) -> decode_pubsub_retract_attrs(__TopXMLNS, _attrs, _val, Notify); decode_pubsub_retract_attrs(__TopXMLNS, [{<<"notify">>, _val} | _attrs], Node, _Notify) -> decode_pubsub_retract_attrs(__TopXMLNS, _attrs, Node, _val); decode_pubsub_retract_attrs(__TopXMLNS, [_ | _attrs], Node, Notify) -> decode_pubsub_retract_attrs(__TopXMLNS, _attrs, Node, Notify); decode_pubsub_retract_attrs(__TopXMLNS, [], Node, Notify) -> {decode_pubsub_retract_attr_node(__TopXMLNS, Node), decode_pubsub_retract_attr_notify(__TopXMLNS, Notify)}. encode_pubsub_retract({pubsub_retract, Node, Notify, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_retract_$items'(Items, [])), _attrs = encode_pubsub_retract_attr_notify(Notify, encode_pubsub_retract_attr_node(Node, _xmlns_attrs)), {xmlel, <<"retract">>, _attrs, _els}. 'encode_pubsub_retract_$items'([], _acc) -> _acc; 'encode_pubsub_retract_$items'([Items | _els], _acc) -> 'encode_pubsub_retract_$items'(_els, [encode_pubsub_item(Items, []) | _acc]). decode_pubsub_retract_attr_node(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"node">>, <<"retract">>, __TopXMLNS}}); decode_pubsub_retract_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_retract_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_retract_attr_notify(__TopXMLNS, undefined) -> false; decode_pubsub_retract_attr_notify(__TopXMLNS, _val) -> case catch dec_bool(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"notify">>, <<"retract">>, __TopXMLNS}}); _res -> _res end. encode_pubsub_retract_attr_notify(false, _acc) -> _acc; encode_pubsub_retract_attr_notify(_val, _acc) -> [{<<"notify">>, enc_bool(_val)} | _acc]. decode_pubsub_options(__TopXMLNS, __IgnoreEls, {xmlel, <<"options">>, _attrs, _els}) -> Xdata = decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, _els, undefined), {Node, Subid, Jid} = decode_pubsub_options_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {pubsub_options, Node, Jid, Subid, Xdata}. decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, [], Xdata) -> Xdata; decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"jabber:x:data">> -> decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, _els, decode_xdata(_xmlns, __IgnoreEls, _el)); true -> decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, _els, Xdata) end; decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, [_ | _els], Xdata) -> decode_pubsub_options_els(__TopXMLNS, __IgnoreEls, _els, Xdata). decode_pubsub_options_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node, Subid, Jid) -> decode_pubsub_options_attrs(__TopXMLNS, _attrs, _val, Subid, Jid); decode_pubsub_options_attrs(__TopXMLNS, [{<<"subid">>, _val} | _attrs], Node, _Subid, Jid) -> decode_pubsub_options_attrs(__TopXMLNS, _attrs, Node, _val, Jid); decode_pubsub_options_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], Node, Subid, _Jid) -> decode_pubsub_options_attrs(__TopXMLNS, _attrs, Node, Subid, _val); decode_pubsub_options_attrs(__TopXMLNS, [_ | _attrs], Node, Subid, Jid) -> decode_pubsub_options_attrs(__TopXMLNS, _attrs, Node, Subid, Jid); decode_pubsub_options_attrs(__TopXMLNS, [], Node, Subid, Jid) -> {decode_pubsub_options_attr_node(__TopXMLNS, Node), decode_pubsub_options_attr_subid(__TopXMLNS, Subid), decode_pubsub_options_attr_jid(__TopXMLNS, Jid)}. encode_pubsub_options({pubsub_options, Node, Jid, Subid, Xdata}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_options_$xdata'(Xdata, [])), _attrs = encode_pubsub_options_attr_jid(Jid, encode_pubsub_options_attr_subid(Subid, encode_pubsub_options_attr_node(Node, _xmlns_attrs))), {xmlel, <<"options">>, _attrs, _els}. 'encode_pubsub_options_$xdata'(undefined, _acc) -> _acc; 'encode_pubsub_options_$xdata'(Xdata, _acc) -> [encode_xdata(Xdata, [{<<"xmlns">>, <<"jabber:x:data">>}]) | _acc]. decode_pubsub_options_attr_node(__TopXMLNS, undefined) -> undefined; decode_pubsub_options_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_options_attr_node(undefined, _acc) -> _acc; encode_pubsub_options_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_options_attr_subid(__TopXMLNS, undefined) -> undefined; decode_pubsub_options_attr_subid(__TopXMLNS, _val) -> _val. encode_pubsub_options_attr_subid(undefined, _acc) -> _acc; encode_pubsub_options_attr_subid(_val, _acc) -> [{<<"subid">>, _val} | _acc]. decode_pubsub_options_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"options">>, __TopXMLNS}}); decode_pubsub_options_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"options">>, __TopXMLNS}}); _res -> _res end. encode_pubsub_options_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_pubsub_publish(__TopXMLNS, __IgnoreEls, {xmlel, <<"publish">>, _attrs, _els}) -> Items = decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els, []), Node = decode_pubsub_publish_attrs(__TopXMLNS, _attrs, undefined), {pubsub_publish, Node, Items}. decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_item(__TopXMLNS, __IgnoreEls, _el) | Items]); true -> decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_pubsub_publish_els(__TopXMLNS, __IgnoreEls, _els, Items). decode_pubsub_publish_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node) -> decode_pubsub_publish_attrs(__TopXMLNS, _attrs, _val); decode_pubsub_publish_attrs(__TopXMLNS, [_ | _attrs], Node) -> decode_pubsub_publish_attrs(__TopXMLNS, _attrs, Node); decode_pubsub_publish_attrs(__TopXMLNS, [], Node) -> decode_pubsub_publish_attr_node(__TopXMLNS, Node). encode_pubsub_publish({pubsub_publish, Node, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_publish_$items'(Items, [])), _attrs = encode_pubsub_publish_attr_node(Node, _xmlns_attrs), {xmlel, <<"publish">>, _attrs, _els}. 'encode_pubsub_publish_$items'([], _acc) -> _acc; 'encode_pubsub_publish_$items'([Items | _els], _acc) -> 'encode_pubsub_publish_$items'(_els, [encode_pubsub_item(Items, []) | _acc]). decode_pubsub_publish_attr_node(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"node">>, <<"publish">>, __TopXMLNS}}); decode_pubsub_publish_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_publish_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_unsubscribe(__TopXMLNS, __IgnoreEls, {xmlel, <<"unsubscribe">>, _attrs, _els}) -> {Node, Subid, Jid} = decode_pubsub_unsubscribe_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {pubsub_unsubscribe, Node, Jid, Subid}. decode_pubsub_unsubscribe_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node, Subid, Jid) -> decode_pubsub_unsubscribe_attrs(__TopXMLNS, _attrs, _val, Subid, Jid); decode_pubsub_unsubscribe_attrs(__TopXMLNS, [{<<"subid">>, _val} | _attrs], Node, _Subid, Jid) -> decode_pubsub_unsubscribe_attrs(__TopXMLNS, _attrs, Node, _val, Jid); decode_pubsub_unsubscribe_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], Node, Subid, _Jid) -> decode_pubsub_unsubscribe_attrs(__TopXMLNS, _attrs, Node, Subid, _val); decode_pubsub_unsubscribe_attrs(__TopXMLNS, [_ | _attrs], Node, Subid, Jid) -> decode_pubsub_unsubscribe_attrs(__TopXMLNS, _attrs, Node, Subid, Jid); decode_pubsub_unsubscribe_attrs(__TopXMLNS, [], Node, Subid, Jid) -> {decode_pubsub_unsubscribe_attr_node(__TopXMLNS, Node), decode_pubsub_unsubscribe_attr_subid(__TopXMLNS, Subid), decode_pubsub_unsubscribe_attr_jid(__TopXMLNS, Jid)}. encode_pubsub_unsubscribe({pubsub_unsubscribe, Node, Jid, Subid}, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_unsubscribe_attr_jid(Jid, encode_pubsub_unsubscribe_attr_subid(Subid, encode_pubsub_unsubscribe_attr_node(Node, _xmlns_attrs))), {xmlel, <<"unsubscribe">>, _attrs, _els}. decode_pubsub_unsubscribe_attr_node(__TopXMLNS, undefined) -> undefined; decode_pubsub_unsubscribe_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_unsubscribe_attr_node(undefined, _acc) -> _acc; encode_pubsub_unsubscribe_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_unsubscribe_attr_subid(__TopXMLNS, undefined) -> undefined; decode_pubsub_unsubscribe_attr_subid(__TopXMLNS, _val) -> _val. encode_pubsub_unsubscribe_attr_subid(undefined, _acc) -> _acc; encode_pubsub_unsubscribe_attr_subid(_val, _acc) -> [{<<"subid">>, _val} | _acc]. decode_pubsub_unsubscribe_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"unsubscribe">>, __TopXMLNS}}); decode_pubsub_unsubscribe_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"unsubscribe">>, __TopXMLNS}}); _res -> _res end. encode_pubsub_unsubscribe_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_pubsub_subscribe(__TopXMLNS, __IgnoreEls, {xmlel, <<"subscribe">>, _attrs, _els}) -> {Node, Jid} = decode_pubsub_subscribe_attrs(__TopXMLNS, _attrs, undefined, undefined), {pubsub_subscribe, Node, Jid}. decode_pubsub_subscribe_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node, Jid) -> decode_pubsub_subscribe_attrs(__TopXMLNS, _attrs, _val, Jid); decode_pubsub_subscribe_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], Node, _Jid) -> decode_pubsub_subscribe_attrs(__TopXMLNS, _attrs, Node, _val); decode_pubsub_subscribe_attrs(__TopXMLNS, [_ | _attrs], Node, Jid) -> decode_pubsub_subscribe_attrs(__TopXMLNS, _attrs, Node, Jid); decode_pubsub_subscribe_attrs(__TopXMLNS, [], Node, Jid) -> {decode_pubsub_subscribe_attr_node(__TopXMLNS, Node), decode_pubsub_subscribe_attr_jid(__TopXMLNS, Jid)}. encode_pubsub_subscribe({pubsub_subscribe, Node, Jid}, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_subscribe_attr_jid(Jid, encode_pubsub_subscribe_attr_node(Node, _xmlns_attrs)), {xmlel, <<"subscribe">>, _attrs, _els}. decode_pubsub_subscribe_attr_node(__TopXMLNS, undefined) -> undefined; decode_pubsub_subscribe_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_subscribe_attr_node(undefined, _acc) -> _acc; encode_pubsub_subscribe_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_subscribe_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"subscribe">>, __TopXMLNS}}); decode_pubsub_subscribe_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"subscribe">>, __TopXMLNS}}); _res -> _res end. encode_pubsub_subscribe_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_pubsub_affiliations(__TopXMLNS, __IgnoreEls, {xmlel, <<"affiliations">>, _attrs, _els}) -> Affiliations = decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, _els, []), Affiliations. decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, [], Affiliations) -> lists:reverse(Affiliations); decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"affiliation">>, _attrs, _} = _el | _els], Affiliations) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_affiliation(__TopXMLNS, __IgnoreEls, _el) | Affiliations]); true -> decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, _els, Affiliations) end; decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, [_ | _els], Affiliations) -> decode_pubsub_affiliations_els(__TopXMLNS, __IgnoreEls, _els, Affiliations). encode_pubsub_affiliations(Affiliations, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_affiliations_$affiliations'(Affiliations, [])), _attrs = _xmlns_attrs, {xmlel, <<"affiliations">>, _attrs, _els}. 'encode_pubsub_affiliations_$affiliations'([], _acc) -> _acc; 'encode_pubsub_affiliations_$affiliations'([Affiliations | _els], _acc) -> 'encode_pubsub_affiliations_$affiliations'(_els, [encode_pubsub_affiliation(Affiliations, []) | _acc]). decode_pubsub_subscriptions(__TopXMLNS, __IgnoreEls, {xmlel, <<"subscriptions">>, _attrs, _els}) -> Subscriptions = decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, _els, []), Node = decode_pubsub_subscriptions_attrs(__TopXMLNS, _attrs, undefined), {Node, Subscriptions}. decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, [], Subscriptions) -> lists:reverse(Subscriptions); decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"subscription">>, _attrs, _} = _el | _els], Subscriptions) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_subscription(__TopXMLNS, __IgnoreEls, _el) | Subscriptions]); true -> decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, _els, Subscriptions) end; decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, [_ | _els], Subscriptions) -> decode_pubsub_subscriptions_els(__TopXMLNS, __IgnoreEls, _els, Subscriptions). decode_pubsub_subscriptions_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node) -> decode_pubsub_subscriptions_attrs(__TopXMLNS, _attrs, _val); decode_pubsub_subscriptions_attrs(__TopXMLNS, [_ | _attrs], Node) -> decode_pubsub_subscriptions_attrs(__TopXMLNS, _attrs, Node); decode_pubsub_subscriptions_attrs(__TopXMLNS, [], Node) -> decode_pubsub_subscriptions_attr_node(__TopXMLNS, Node). encode_pubsub_subscriptions({Node, Subscriptions}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_subscriptions_$subscriptions'(Subscriptions, [])), _attrs = encode_pubsub_subscriptions_attr_node(Node, _xmlns_attrs), {xmlel, <<"subscriptions">>, _attrs, _els}. 'encode_pubsub_subscriptions_$subscriptions'([], _acc) -> _acc; 'encode_pubsub_subscriptions_$subscriptions'([Subscriptions | _els], _acc) -> 'encode_pubsub_subscriptions_$subscriptions'(_els, [encode_pubsub_subscription(Subscriptions, []) | _acc]). decode_pubsub_subscriptions_attr_node(__TopXMLNS, undefined) -> none; decode_pubsub_subscriptions_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_subscriptions_attr_node(none, _acc) -> _acc; encode_pubsub_subscriptions_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_event(__TopXMLNS, __IgnoreEls, {xmlel, <<"event">>, _attrs, _els}) -> Items = decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, []), {pubsub_event, Items}. decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"items">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_event_items(__TopXMLNS, __IgnoreEls, _el) | Items]); true -> decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_pubsub_event_els(__TopXMLNS, __IgnoreEls, _els, Items). encode_pubsub_event({pubsub_event, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_event_$items'(Items, [])), _attrs = _xmlns_attrs, {xmlel, <<"event">>, _attrs, _els}. 'encode_pubsub_event_$items'([], _acc) -> _acc; 'encode_pubsub_event_$items'([Items | _els], _acc) -> 'encode_pubsub_event_$items'(_els, [encode_pubsub_event_items(Items, []) | _acc]). decode_pubsub_event_items(__TopXMLNS, __IgnoreEls, {xmlel, <<"items">>, _attrs, _els}) -> {Items, Retract} = decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, _els, [], []), Node = decode_pubsub_event_items_attrs(__TopXMLNS, _attrs, undefined), {pubsub_event_items, Node, Retract, Items}. decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, [], Items, Retract) -> {lists:reverse(Items), lists:reverse(Retract)}; decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"retract">>, _attrs, _} = _el | _els], Items, Retract) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, _els, Items, [decode_pubsub_event_retract(__TopXMLNS, __IgnoreEls, _el) | Retract]); true -> decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, _els, Items, Retract) end; decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items, Retract) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_event_item(__TopXMLNS, __IgnoreEls, _el) | Items], Retract); true -> decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, _els, Items, Retract) end; decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items, Retract) -> decode_pubsub_event_items_els(__TopXMLNS, __IgnoreEls, _els, Items, Retract). decode_pubsub_event_items_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node) -> decode_pubsub_event_items_attrs(__TopXMLNS, _attrs, _val); decode_pubsub_event_items_attrs(__TopXMLNS, [_ | _attrs], Node) -> decode_pubsub_event_items_attrs(__TopXMLNS, _attrs, Node); decode_pubsub_event_items_attrs(__TopXMLNS, [], Node) -> decode_pubsub_event_items_attr_node(__TopXMLNS, Node). encode_pubsub_event_items({pubsub_event_items, Node, Retract, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_event_items_$items'(Items, 'encode_pubsub_event_items_$retract'(Retract, []))), _attrs = encode_pubsub_event_items_attr_node(Node, _xmlns_attrs), {xmlel, <<"items">>, _attrs, _els}. 'encode_pubsub_event_items_$items'([], _acc) -> _acc; 'encode_pubsub_event_items_$items'([Items | _els], _acc) -> 'encode_pubsub_event_items_$items'(_els, [encode_pubsub_event_item(Items, []) | _acc]). 'encode_pubsub_event_items_$retract'([], _acc) -> _acc; 'encode_pubsub_event_items_$retract'([Retract | _els], _acc) -> 'encode_pubsub_event_items_$retract'(_els, [encode_pubsub_event_retract(Retract, []) | _acc]). decode_pubsub_event_items_attr_node(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"node">>, <<"items">>, __TopXMLNS}}); decode_pubsub_event_items_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_event_items_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_event_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> {Id, Node, Publisher} = decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {pubsub_event_item, Id, Node, Publisher}. decode_pubsub_event_item_attrs(__TopXMLNS, [{<<"id">>, _val} | _attrs], _Id, Node, Publisher) -> decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, _val, Node, Publisher); decode_pubsub_event_item_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], Id, _Node, Publisher) -> decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, Id, _val, Publisher); decode_pubsub_event_item_attrs(__TopXMLNS, [{<<"publisher">>, _val} | _attrs], Id, Node, _Publisher) -> decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, Id, Node, _val); decode_pubsub_event_item_attrs(__TopXMLNS, [_ | _attrs], Id, Node, Publisher) -> decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, Id, Node, Publisher); decode_pubsub_event_item_attrs(__TopXMLNS, [], Id, Node, Publisher) -> {decode_pubsub_event_item_attr_id(__TopXMLNS, Id), decode_pubsub_event_item_attr_node(__TopXMLNS, Node), decode_pubsub_event_item_attr_publisher(__TopXMLNS, Publisher)}. encode_pubsub_event_item({pubsub_event_item, Id, Node, Publisher}, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_event_item_attr_publisher(Publisher, encode_pubsub_event_item_attr_node(Node, encode_pubsub_event_item_attr_id(Id, _xmlns_attrs))), {xmlel, <<"item">>, _attrs, _els}. decode_pubsub_event_item_attr_id(__TopXMLNS, undefined) -> undefined; decode_pubsub_event_item_attr_id(__TopXMLNS, _val) -> _val. encode_pubsub_event_item_attr_id(undefined, _acc) -> _acc; encode_pubsub_event_item_attr_id(_val, _acc) -> [{<<"id">>, _val} | _acc]. decode_pubsub_event_item_attr_node(__TopXMLNS, undefined) -> undefined; decode_pubsub_event_item_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_event_item_attr_node(undefined, _acc) -> _acc; encode_pubsub_event_item_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_event_item_attr_publisher(__TopXMLNS, undefined) -> undefined; decode_pubsub_event_item_attr_publisher(__TopXMLNS, _val) -> _val. encode_pubsub_event_item_attr_publisher(undefined, _acc) -> _acc; encode_pubsub_event_item_attr_publisher(_val, _acc) -> [{<<"publisher">>, _val} | _acc]. decode_pubsub_event_retract(__TopXMLNS, __IgnoreEls, {xmlel, <<"retract">>, _attrs, _els}) -> Id = decode_pubsub_event_retract_attrs(__TopXMLNS, _attrs, undefined), Id. decode_pubsub_event_retract_attrs(__TopXMLNS, [{<<"id">>, _val} | _attrs], _Id) -> decode_pubsub_event_retract_attrs(__TopXMLNS, _attrs, _val); decode_pubsub_event_retract_attrs(__TopXMLNS, [_ | _attrs], Id) -> decode_pubsub_event_retract_attrs(__TopXMLNS, _attrs, Id); decode_pubsub_event_retract_attrs(__TopXMLNS, [], Id) -> decode_pubsub_event_retract_attr_id(__TopXMLNS, Id). encode_pubsub_event_retract(Id, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_event_retract_attr_id(Id, _xmlns_attrs), {xmlel, <<"retract">>, _attrs, _els}. decode_pubsub_event_retract_attr_id(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"id">>, <<"retract">>, __TopXMLNS}}); decode_pubsub_event_retract_attr_id(__TopXMLNS, _val) -> _val. encode_pubsub_event_retract_attr_id(_val, _acc) -> [{<<"id">>, _val} | _acc]. decode_pubsub_items(__TopXMLNS, __IgnoreEls, {xmlel, <<"items">>, _attrs, _els}) -> Items = decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, []), {Max_items, Node, Subid} = decode_pubsub_items_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {pubsub_items, Node, Max_items, Subid, Items}. decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, [decode_pubsub_item(__TopXMLNS, __IgnoreEls, _el) | Items]); true -> decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_pubsub_items_els(__TopXMLNS, __IgnoreEls, _els, Items). decode_pubsub_items_attrs(__TopXMLNS, [{<<"max_items">>, _val} | _attrs], _Max_items, Node, Subid) -> decode_pubsub_items_attrs(__TopXMLNS, _attrs, _val, Node, Subid); decode_pubsub_items_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], Max_items, _Node, Subid) -> decode_pubsub_items_attrs(__TopXMLNS, _attrs, Max_items, _val, Subid); decode_pubsub_items_attrs(__TopXMLNS, [{<<"subid">>, _val} | _attrs], Max_items, Node, _Subid) -> decode_pubsub_items_attrs(__TopXMLNS, _attrs, Max_items, Node, _val); decode_pubsub_items_attrs(__TopXMLNS, [_ | _attrs], Max_items, Node, Subid) -> decode_pubsub_items_attrs(__TopXMLNS, _attrs, Max_items, Node, Subid); decode_pubsub_items_attrs(__TopXMLNS, [], Max_items, Node, Subid) -> {decode_pubsub_items_attr_max_items(__TopXMLNS, Max_items), decode_pubsub_items_attr_node(__TopXMLNS, Node), decode_pubsub_items_attr_subid(__TopXMLNS, Subid)}. encode_pubsub_items({pubsub_items, Node, Max_items, Subid, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_pubsub_items_$items'(Items, [])), _attrs = encode_pubsub_items_attr_subid(Subid, encode_pubsub_items_attr_node(Node, encode_pubsub_items_attr_max_items(Max_items, _xmlns_attrs))), {xmlel, <<"items">>, _attrs, _els}. 'encode_pubsub_items_$items'([], _acc) -> _acc; 'encode_pubsub_items_$items'([Items | _els], _acc) -> 'encode_pubsub_items_$items'(_els, [encode_pubsub_item(Items, []) | _acc]). decode_pubsub_items_attr_max_items(__TopXMLNS, undefined) -> undefined; decode_pubsub_items_attr_max_items(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"max_items">>, <<"items">>, __TopXMLNS}}); _res -> _res end. encode_pubsub_items_attr_max_items(undefined, _acc) -> _acc; encode_pubsub_items_attr_max_items(_val, _acc) -> [{<<"max_items">>, enc_int(_val)} | _acc]. decode_pubsub_items_attr_node(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"node">>, <<"items">>, __TopXMLNS}}); decode_pubsub_items_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_items_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_items_attr_subid(__TopXMLNS, undefined) -> undefined; decode_pubsub_items_attr_subid(__TopXMLNS, _val) -> _val. encode_pubsub_items_attr_subid(undefined, _acc) -> _acc; encode_pubsub_items_attr_subid(_val, _acc) -> [{<<"subid">>, _val} | _acc]. decode_pubsub_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> __Xmls = decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, _els, []), Id = decode_pubsub_item_attrs(__TopXMLNS, _attrs, undefined), {pubsub_item, Id, __Xmls}. decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, [], __Xmls) -> lists:reverse(__Xmls); decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, _, _, _} = _el | _els], __Xmls) -> decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, _els, [_el | __Xmls]); decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, [_ | _els], __Xmls) -> decode_pubsub_item_els(__TopXMLNS, __IgnoreEls, _els, __Xmls). decode_pubsub_item_attrs(__TopXMLNS, [{<<"id">>, _val} | _attrs], _Id) -> decode_pubsub_item_attrs(__TopXMLNS, _attrs, _val); decode_pubsub_item_attrs(__TopXMLNS, [_ | _attrs], Id) -> decode_pubsub_item_attrs(__TopXMLNS, _attrs, Id); decode_pubsub_item_attrs(__TopXMLNS, [], Id) -> decode_pubsub_item_attr_id(__TopXMLNS, Id). encode_pubsub_item({pubsub_item, Id, __Xmls}, _xmlns_attrs) -> _els = __Xmls, _attrs = encode_pubsub_item_attr_id(Id, _xmlns_attrs), {xmlel, <<"item">>, _attrs, _els}. decode_pubsub_item_attr_id(__TopXMLNS, undefined) -> undefined; decode_pubsub_item_attr_id(__TopXMLNS, _val) -> _val. encode_pubsub_item_attr_id(undefined, _acc) -> _acc; encode_pubsub_item_attr_id(_val, _acc) -> [{<<"id">>, _val} | _acc]. decode_pubsub_affiliation(__TopXMLNS, __IgnoreEls, {xmlel, <<"affiliation">>, _attrs, _els}) -> {Node, Type} = decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, undefined, undefined), {pubsub_affiliation, Node, Type}. decode_pubsub_affiliation_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node, Type) -> decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, _val, Type); decode_pubsub_affiliation_attrs(__TopXMLNS, [{<<"affiliation">>, _val} | _attrs], Node, _Type) -> decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, Node, _val); decode_pubsub_affiliation_attrs(__TopXMLNS, [_ | _attrs], Node, Type) -> decode_pubsub_affiliation_attrs(__TopXMLNS, _attrs, Node, Type); decode_pubsub_affiliation_attrs(__TopXMLNS, [], Node, Type) -> {decode_pubsub_affiliation_attr_node(__TopXMLNS, Node), decode_pubsub_affiliation_attr_affiliation(__TopXMLNS, Type)}. encode_pubsub_affiliation({pubsub_affiliation, Node, Type}, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_affiliation_attr_affiliation(Type, encode_pubsub_affiliation_attr_node(Node, _xmlns_attrs)), {xmlel, <<"affiliation">>, _attrs, _els}. decode_pubsub_affiliation_attr_node(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"node">>, <<"affiliation">>, __TopXMLNS}}); decode_pubsub_affiliation_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_affiliation_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_affiliation_attr_affiliation(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"affiliation">>, <<"affiliation">>, __TopXMLNS}}); decode_pubsub_affiliation_attr_affiliation(__TopXMLNS, _val) -> case catch dec_enum(_val, [member, none, outcast, owner, publisher, 'publish-only']) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"affiliation">>, <<"affiliation">>, __TopXMLNS}}); _res -> _res end. encode_pubsub_affiliation_attr_affiliation(_val, _acc) -> [{<<"affiliation">>, enc_enum(_val)} | _acc]. decode_pubsub_subscription(__TopXMLNS, __IgnoreEls, {xmlel, <<"subscription">>, _attrs, _els}) -> {Jid, Node, Subid, Type} = decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined), {pubsub_subscription, Jid, Node, Subid, Type}. decode_pubsub_subscription_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid, Node, Subid, Type) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, _val, Node, Subid, Type); decode_pubsub_subscription_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], Jid, _Node, Subid, Type) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, Jid, _val, Subid, Type); decode_pubsub_subscription_attrs(__TopXMLNS, [{<<"subid">>, _val} | _attrs], Jid, Node, _Subid, Type) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, Jid, Node, _val, Type); decode_pubsub_subscription_attrs(__TopXMLNS, [{<<"subscription">>, _val} | _attrs], Jid, Node, Subid, _Type) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, Jid, Node, Subid, _val); decode_pubsub_subscription_attrs(__TopXMLNS, [_ | _attrs], Jid, Node, Subid, Type) -> decode_pubsub_subscription_attrs(__TopXMLNS, _attrs, Jid, Node, Subid, Type); decode_pubsub_subscription_attrs(__TopXMLNS, [], Jid, Node, Subid, Type) -> {decode_pubsub_subscription_attr_jid(__TopXMLNS, Jid), decode_pubsub_subscription_attr_node(__TopXMLNS, Node), decode_pubsub_subscription_attr_subid(__TopXMLNS, Subid), decode_pubsub_subscription_attr_subscription(__TopXMLNS, Type)}. encode_pubsub_subscription({pubsub_subscription, Jid, Node, Subid, Type}, _xmlns_attrs) -> _els = [], _attrs = encode_pubsub_subscription_attr_subscription(Type, encode_pubsub_subscription_attr_subid(Subid, encode_pubsub_subscription_attr_node(Node, encode_pubsub_subscription_attr_jid(Jid, _xmlns_attrs)))), {xmlel, <<"subscription">>, _attrs, _els}. decode_pubsub_subscription_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"subscription">>, __TopXMLNS}}); decode_pubsub_subscription_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"subscription">>, __TopXMLNS}}); _res -> _res end. encode_pubsub_subscription_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_pubsub_subscription_attr_node(__TopXMLNS, undefined) -> undefined; decode_pubsub_subscription_attr_node(__TopXMLNS, _val) -> _val. encode_pubsub_subscription_attr_node(undefined, _acc) -> _acc; encode_pubsub_subscription_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_pubsub_subscription_attr_subid(__TopXMLNS, undefined) -> undefined; decode_pubsub_subscription_attr_subid(__TopXMLNS, _val) -> _val. encode_pubsub_subscription_attr_subid(undefined, _acc) -> _acc; encode_pubsub_subscription_attr_subid(_val, _acc) -> [{<<"subid">>, _val} | _acc]. decode_pubsub_subscription_attr_subscription(__TopXMLNS, undefined) -> undefined; decode_pubsub_subscription_attr_subscription(__TopXMLNS, _val) -> case catch dec_enum(_val, [none, pending, subscribed, unconfigured]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"subscription">>, <<"subscription">>, __TopXMLNS}}); _res -> _res end. encode_pubsub_subscription_attr_subscription(undefined, _acc) -> _acc; encode_pubsub_subscription_attr_subscription(_val, _acc) -> [{<<"subscription">>, enc_enum(_val)} | _acc]. decode_xdata(__TopXMLNS, __IgnoreEls, {xmlel, <<"x">>, _attrs, _els}) -> {Fields, Items, Instructions, Reported, Title} = decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, [], [], [], undefined, undefined), Type = decode_xdata_attrs(__TopXMLNS, _attrs, undefined), {xdata, Type, Instructions, Title, Reported, Items, Fields}. decode_xdata_els(__TopXMLNS, __IgnoreEls, [], Fields, Items, Instructions, Reported, Title) -> {lists:reverse(Fields), lists:reverse(Items), lists:reverse(Instructions), Reported, Title}; decode_xdata_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"instructions">>, _attrs, _} = _el | _els], Fields, Items, Instructions, Reported, Title) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, case decode_xdata_instructions(__TopXMLNS, __IgnoreEls, _el) of undefined -> Instructions; _new_el -> [_new_el | Instructions] end, Reported, Title); true -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, Instructions, Reported, Title) end; decode_xdata_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"title">>, _attrs, _} = _el | _els], Fields, Items, Instructions, Reported, Title) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, Instructions, Reported, decode_xdata_title(__TopXMLNS, __IgnoreEls, _el)); true -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, Instructions, Reported, Title) end; decode_xdata_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"reported">>, _attrs, _} = _el | _els], Fields, Items, Instructions, Reported, Title) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, Instructions, decode_xdata_reported(__TopXMLNS, __IgnoreEls, _el), Title); true -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, Instructions, Reported, Title) end; decode_xdata_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Fields, Items, Instructions, Reported, Title) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, [decode_xdata_item(__TopXMLNS, __IgnoreEls, _el) | Items], Instructions, Reported, Title); true -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, Instructions, Reported, Title) end; decode_xdata_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"field">>, _attrs, _} = _el | _els], Fields, Items, Instructions, Reported, Title) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, [decode_xdata_field(__TopXMLNS, __IgnoreEls, _el) | Fields], Items, Instructions, Reported, Title); true -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, Instructions, Reported, Title) end; decode_xdata_els(__TopXMLNS, __IgnoreEls, [_ | _els], Fields, Items, Instructions, Reported, Title) -> decode_xdata_els(__TopXMLNS, __IgnoreEls, _els, Fields, Items, Instructions, Reported, Title). decode_xdata_attrs(__TopXMLNS, [{<<"type">>, _val} | _attrs], _Type) -> decode_xdata_attrs(__TopXMLNS, _attrs, _val); decode_xdata_attrs(__TopXMLNS, [_ | _attrs], Type) -> decode_xdata_attrs(__TopXMLNS, _attrs, Type); decode_xdata_attrs(__TopXMLNS, [], Type) -> decode_xdata_attr_type(__TopXMLNS, Type). encode_xdata({xdata, Type, Instructions, Title, Reported, Items, Fields}, _xmlns_attrs) -> _els = lists:reverse('encode_xdata_$fields'(Fields, 'encode_xdata_$items'(Items, 'encode_xdata_$instructions'(Instructions, 'encode_xdata_$reported'(Reported, 'encode_xdata_$title'(Title, [])))))), _attrs = encode_xdata_attr_type(Type, _xmlns_attrs), {xmlel, <<"x">>, _attrs, _els}. 'encode_xdata_$fields'([], _acc) -> _acc; 'encode_xdata_$fields'([Fields | _els], _acc) -> 'encode_xdata_$fields'(_els, [encode_xdata_field(Fields, []) | _acc]). 'encode_xdata_$items'([], _acc) -> _acc; 'encode_xdata_$items'([Items | _els], _acc) -> 'encode_xdata_$items'(_els, [encode_xdata_item(Items, []) | _acc]). 'encode_xdata_$instructions'([], _acc) -> _acc; 'encode_xdata_$instructions'([Instructions | _els], _acc) -> 'encode_xdata_$instructions'(_els, [encode_xdata_instructions(Instructions, []) | _acc]). 'encode_xdata_$reported'(undefined, _acc) -> _acc; 'encode_xdata_$reported'(Reported, _acc) -> [encode_xdata_reported(Reported, []) | _acc]. 'encode_xdata_$title'(undefined, _acc) -> _acc; 'encode_xdata_$title'(Title, _acc) -> [encode_xdata_title(Title, []) | _acc]. decode_xdata_attr_type(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"type">>, <<"x">>, __TopXMLNS}}); decode_xdata_attr_type(__TopXMLNS, _val) -> case catch dec_enum(_val, [cancel, form, result, submit]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"type">>, <<"x">>, __TopXMLNS}}); _res -> _res end. encode_xdata_attr_type(_val, _acc) -> [{<<"type">>, enc_enum(_val)} | _acc]. decode_xdata_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> Fields = decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els, []), Fields. decode_xdata_item_els(__TopXMLNS, __IgnoreEls, [], Fields) -> lists:reverse(Fields); decode_xdata_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"field">>, _attrs, _} = _el | _els], Fields) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els, [decode_xdata_field(__TopXMLNS, __IgnoreEls, _el) | Fields]); true -> decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els, Fields) end; decode_xdata_item_els(__TopXMLNS, __IgnoreEls, [_ | _els], Fields) -> decode_xdata_item_els(__TopXMLNS, __IgnoreEls, _els, Fields). encode_xdata_item(Fields, _xmlns_attrs) -> _els = lists:reverse('encode_xdata_item_$fields'(Fields, [])), _attrs = _xmlns_attrs, {xmlel, <<"item">>, _attrs, _els}. 'encode_xdata_item_$fields'([], _acc) -> _acc; 'encode_xdata_item_$fields'([Fields | _els], _acc) -> 'encode_xdata_item_$fields'(_els, [encode_xdata_field(Fields, []) | _acc]). decode_xdata_reported(__TopXMLNS, __IgnoreEls, {xmlel, <<"reported">>, _attrs, _els}) -> Fields = decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els, []), Fields. decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, [], Fields) -> lists:reverse(Fields); decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"field">>, _attrs, _} = _el | _els], Fields) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els, [decode_xdata_field(__TopXMLNS, __IgnoreEls, _el) | Fields]); true -> decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els, Fields) end; decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, [_ | _els], Fields) -> decode_xdata_reported_els(__TopXMLNS, __IgnoreEls, _els, Fields). encode_xdata_reported(Fields, _xmlns_attrs) -> _els = lists:reverse('encode_xdata_reported_$fields'(Fields, [])), _attrs = _xmlns_attrs, {xmlel, <<"reported">>, _attrs, _els}. 'encode_xdata_reported_$fields'([], _acc) -> _acc; 'encode_xdata_reported_$fields'([Fields | _els], _acc) -> 'encode_xdata_reported_$fields'(_els, [encode_xdata_field(Fields, []) | _acc]). decode_xdata_title(__TopXMLNS, __IgnoreEls, {xmlel, <<"title">>, _attrs, _els}) -> Cdata = decode_xdata_title_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_xdata_title_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_xdata_title_cdata(__TopXMLNS, Cdata); decode_xdata_title_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_xdata_title_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_xdata_title_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_xdata_title_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_xdata_title(Cdata, _xmlns_attrs) -> _els = encode_xdata_title_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"title">>, _attrs, _els}. decode_xdata_title_cdata(__TopXMLNS, <<>>) -> undefined; decode_xdata_title_cdata(__TopXMLNS, _val) -> _val. encode_xdata_title_cdata(undefined, _acc) -> _acc; encode_xdata_title_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_xdata_instructions(__TopXMLNS, __IgnoreEls, {xmlel, <<"instructions">>, _attrs, _els}) -> Cdata = decode_xdata_instructions_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_xdata_instructions_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_xdata_instructions_cdata(__TopXMLNS, Cdata); decode_xdata_instructions_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_xdata_instructions_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_xdata_instructions_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_xdata_instructions_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_xdata_instructions(Cdata, _xmlns_attrs) -> _els = encode_xdata_instructions_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"instructions">>, _attrs, _els}. decode_xdata_instructions_cdata(__TopXMLNS, <<>>) -> undefined; decode_xdata_instructions_cdata(__TopXMLNS, _val) -> _val. encode_xdata_instructions_cdata(undefined, _acc) -> _acc; encode_xdata_instructions_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_xdata_field(__TopXMLNS, __IgnoreEls, {xmlel, <<"field">>, _attrs, _els}) -> {Options, Values, Desc, Required} = decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, [], [], undefined, false), {Label, Type, Var} = decode_xdata_field_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {xdata_field, Label, Type, Var, Required, Desc, Values, Options}. decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [], Options, Values, Desc, Required) -> {lists:reverse(Options), lists:reverse(Values), Desc, Required}; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"required">>, _attrs, _} = _el | _els], Options, Values, Desc, Required) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, Desc, decode_xdata_field_required(__TopXMLNS, __IgnoreEls, _el)); true -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, Desc, Required) end; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"desc">>, _attrs, _} = _el | _els], Options, Values, Desc, Required) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, decode_xdata_field_desc(__TopXMLNS, __IgnoreEls, _el), Required); true -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, Desc, Required) end; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"value">>, _attrs, _} = _el | _els], Options, Values, Desc, Required) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, case decode_xdata_field_value(__TopXMLNS, __IgnoreEls, _el) of undefined -> Values; _new_el -> [_new_el | Values] end, Desc, Required); true -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, Desc, Required) end; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"option">>, _attrs, _} = _el | _els], Options, Values, Desc, Required) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, case decode_xdata_field_option(__TopXMLNS, __IgnoreEls, _el) of undefined -> Options; _new_el -> [_new_el | Options] end, Values, Desc, Required); true -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, Desc, Required) end; decode_xdata_field_els(__TopXMLNS, __IgnoreEls, [_ | _els], Options, Values, Desc, Required) -> decode_xdata_field_els(__TopXMLNS, __IgnoreEls, _els, Options, Values, Desc, Required). decode_xdata_field_attrs(__TopXMLNS, [{<<"label">>, _val} | _attrs], _Label, Type, Var) -> decode_xdata_field_attrs(__TopXMLNS, _attrs, _val, Type, Var); decode_xdata_field_attrs(__TopXMLNS, [{<<"type">>, _val} | _attrs], Label, _Type, Var) -> decode_xdata_field_attrs(__TopXMLNS, _attrs, Label, _val, Var); decode_xdata_field_attrs(__TopXMLNS, [{<<"var">>, _val} | _attrs], Label, Type, _Var) -> decode_xdata_field_attrs(__TopXMLNS, _attrs, Label, Type, _val); decode_xdata_field_attrs(__TopXMLNS, [_ | _attrs], Label, Type, Var) -> decode_xdata_field_attrs(__TopXMLNS, _attrs, Label, Type, Var); decode_xdata_field_attrs(__TopXMLNS, [], Label, Type, Var) -> {decode_xdata_field_attr_label(__TopXMLNS, Label), decode_xdata_field_attr_type(__TopXMLNS, Type), decode_xdata_field_attr_var(__TopXMLNS, Var)}. encode_xdata_field({xdata_field, Label, Type, Var, Required, Desc, Values, Options}, _xmlns_attrs) -> _els = lists:reverse('encode_xdata_field_$options'(Options, 'encode_xdata_field_$values'(Values, 'encode_xdata_field_$desc'(Desc, 'encode_xdata_field_$required'(Required, []))))), _attrs = encode_xdata_field_attr_var(Var, encode_xdata_field_attr_type(Type, encode_xdata_field_attr_label(Label, _xmlns_attrs))), {xmlel, <<"field">>, _attrs, _els}. 'encode_xdata_field_$options'([], _acc) -> _acc; 'encode_xdata_field_$options'([Options | _els], _acc) -> 'encode_xdata_field_$options'(_els, [encode_xdata_field_option(Options, []) | _acc]). 'encode_xdata_field_$values'([], _acc) -> _acc; 'encode_xdata_field_$values'([Values | _els], _acc) -> 'encode_xdata_field_$values'(_els, [encode_xdata_field_value(Values, []) | _acc]). 'encode_xdata_field_$desc'(undefined, _acc) -> _acc; 'encode_xdata_field_$desc'(Desc, _acc) -> [encode_xdata_field_desc(Desc, []) | _acc]. 'encode_xdata_field_$required'(false, _acc) -> _acc; 'encode_xdata_field_$required'(Required, _acc) -> [encode_xdata_field_required(Required, []) | _acc]. decode_xdata_field_attr_label(__TopXMLNS, undefined) -> undefined; decode_xdata_field_attr_label(__TopXMLNS, _val) -> _val. encode_xdata_field_attr_label(undefined, _acc) -> _acc; encode_xdata_field_attr_label(_val, _acc) -> [{<<"label">>, _val} | _acc]. decode_xdata_field_attr_type(__TopXMLNS, undefined) -> undefined; decode_xdata_field_attr_type(__TopXMLNS, _val) -> case catch dec_enum(_val, [boolean, fixed, hidden, 'jid-multi', 'jid-single', 'list-multi', 'list-single', 'text-multi', 'text-private', 'text-single']) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"type">>, <<"field">>, __TopXMLNS}}); _res -> _res end. encode_xdata_field_attr_type(undefined, _acc) -> _acc; encode_xdata_field_attr_type(_val, _acc) -> [{<<"type">>, enc_enum(_val)} | _acc]. decode_xdata_field_attr_var(__TopXMLNS, undefined) -> undefined; decode_xdata_field_attr_var(__TopXMLNS, _val) -> _val. encode_xdata_field_attr_var(undefined, _acc) -> _acc; encode_xdata_field_attr_var(_val, _acc) -> [{<<"var">>, _val} | _acc]. decode_xdata_field_option(__TopXMLNS, __IgnoreEls, {xmlel, <<"option">>, _attrs, _els}) -> Value = decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls, _els, error), Value. decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls, [], Value) -> case Value of error -> erlang:error({xmpp_codec, {missing_tag, <<"value">>, __TopXMLNS}}); {value, Value1} -> Value1 end; decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"value">>, _attrs, _} = _el | _els], Value) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls, _els, {value, decode_xdata_field_value(__TopXMLNS, __IgnoreEls, _el)}); true -> decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls, _els, Value) end; decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls, [_ | _els], Value) -> decode_xdata_field_option_els(__TopXMLNS, __IgnoreEls, _els, Value). encode_xdata_field_option(Value, _xmlns_attrs) -> _els = lists:reverse('encode_xdata_field_option_$value'(Value, [])), _attrs = _xmlns_attrs, {xmlel, <<"option">>, _attrs, _els}. 'encode_xdata_field_option_$value'(Value, _acc) -> [encode_xdata_field_value(Value, []) | _acc]. decode_xdata_field_value(__TopXMLNS, __IgnoreEls, {xmlel, <<"value">>, _attrs, _els}) -> Cdata = decode_xdata_field_value_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_xdata_field_value_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_xdata_field_value_cdata(__TopXMLNS, Cdata); decode_xdata_field_value_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_xdata_field_value_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_xdata_field_value_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_xdata_field_value_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_xdata_field_value(Cdata, _xmlns_attrs) -> _els = encode_xdata_field_value_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"value">>, _attrs, _els}. decode_xdata_field_value_cdata(__TopXMLNS, <<>>) -> undefined; decode_xdata_field_value_cdata(__TopXMLNS, _val) -> _val. encode_xdata_field_value_cdata(undefined, _acc) -> _acc; encode_xdata_field_value_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_xdata_field_desc(__TopXMLNS, __IgnoreEls, {xmlel, <<"desc">>, _attrs, _els}) -> Cdata = decode_xdata_field_desc_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_xdata_field_desc_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_xdata_field_desc_cdata(__TopXMLNS, Cdata); decode_xdata_field_desc_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_xdata_field_desc_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_xdata_field_desc_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_xdata_field_desc_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_xdata_field_desc(Cdata, _xmlns_attrs) -> _els = encode_xdata_field_desc_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"desc">>, _attrs, _els}. decode_xdata_field_desc_cdata(__TopXMLNS, <<>>) -> undefined; decode_xdata_field_desc_cdata(__TopXMLNS, _val) -> _val. encode_xdata_field_desc_cdata(undefined, _acc) -> _acc; encode_xdata_field_desc_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_xdata_field_required(__TopXMLNS, __IgnoreEls, {xmlel, <<"required">>, _attrs, _els}) -> true. encode_xdata_field_required(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"required">>, _attrs, _els}. decode_vcard_xupdate(__TopXMLNS, __IgnoreEls, {xmlel, <<"x">>, _attrs, _els}) -> Photo = decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els, undefined), {vcard_xupdate, Photo}. decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, [], Photo) -> Photo; decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"photo">>, _attrs, _} = _el | _els], Photo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_xupdate_photo(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els, Photo) end; decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, [_ | _els], Photo) -> decode_vcard_xupdate_els(__TopXMLNS, __IgnoreEls, _els, Photo). encode_vcard_xupdate({vcard_xupdate, Photo}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_xupdate_$photo'(Photo, [])), _attrs = _xmlns_attrs, {xmlel, <<"x">>, _attrs, _els}. 'encode_vcard_xupdate_$photo'(undefined, _acc) -> _acc; 'encode_vcard_xupdate_$photo'(Photo, _acc) -> [encode_vcard_xupdate_photo(Photo, []) | _acc]. decode_vcard_xupdate_photo(__TopXMLNS, __IgnoreEls, {xmlel, <<"photo">>, _attrs, _els}) -> Cdata = decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_xupdate_photo_cdata(__TopXMLNS, Cdata); decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_xupdate_photo_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_xupdate_photo(Cdata, _xmlns_attrs) -> _els = encode_vcard_xupdate_photo_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"photo">>, _attrs, _els}. decode_vcard_xupdate_photo_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_xupdate_photo_cdata(__TopXMLNS, _val) -> _val. encode_vcard_xupdate_photo_cdata(undefined, _acc) -> _acc; encode_vcard_xupdate_photo_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard(__TopXMLNS, __IgnoreEls, {xmlel, <<"vCard">>, _attrs, _els}) -> {Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo} = decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, undefined, [], undefined, [], undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, [], [], [], undefined, undefined, undefined, undefined, undefined, undefined), {vcard, Version, Fn, N, Nickname, Photo, Bday, Adr, Label, Tel, Email, Jabberid, Mailer, Tz, Geo, Title, Role, Logo, Org, Categories, Note, Prodid, Rev, Sort_string, Sound, Uid, Url, Class, Key, Desc}. decode_vcard_els(__TopXMLNS, __IgnoreEls, [], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> {Mailer, lists:reverse(Adr), Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, lists:reverse(Email), lists:reverse(Tel), lists:reverse(Label), Fn, Version, N, Photo, Logo, Geo}; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"N">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, decode_vcard_N(__TopXMLNS, __IgnoreEls, _el), Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"ADR">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, [decode_vcard_ADR(__TopXMLNS, __IgnoreEls, _el) | Adr], Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"LABEL">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, [decode_vcard_LABEL(__TopXMLNS, __IgnoreEls, _el) | Label], Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"TEL">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, [decode_vcard_TEL(__TopXMLNS, __IgnoreEls, _el) | Tel], Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"EMAIL">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, [decode_vcard_EMAIL(__TopXMLNS, __IgnoreEls, _el) | Email], Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"GEO">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, decode_vcard_GEO(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"LOGO">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, decode_vcard_LOGO(__TopXMLNS, __IgnoreEls, _el), Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PHOTO">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, decode_vcard_PHOTO(__TopXMLNS, __IgnoreEls, _el), Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"ORG">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, decode_vcard_ORG(__TopXMLNS, __IgnoreEls, _el), Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"SOUND">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, decode_vcard_SOUND(__TopXMLNS, __IgnoreEls, _el), Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"KEY">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, decode_vcard_KEY(__TopXMLNS, __IgnoreEls, _el), Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"VERSION">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, decode_vcard_VERSION(__TopXMLNS, __IgnoreEls, _el), N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"FN">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, decode_vcard_FN(__TopXMLNS, __IgnoreEls, _el), Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"NICKNAME">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, decode_vcard_NICKNAME(__TopXMLNS, __IgnoreEls, _el), Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"BDAY">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, decode_vcard_BDAY(__TopXMLNS, __IgnoreEls, _el), Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"JABBERID">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, decode_vcard_JABBERID(__TopXMLNS, __IgnoreEls, _el), Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"MAILER">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_MAILER(__TopXMLNS, __IgnoreEls, _el), Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"TZ">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, decode_vcard_TZ(__TopXMLNS, __IgnoreEls, _el), Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"TITLE">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, decode_vcard_TITLE(__TopXMLNS, __IgnoreEls, _el), Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"ROLE">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, decode_vcard_ROLE(__TopXMLNS, __IgnoreEls, _el), Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"NOTE">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, decode_vcard_NOTE(__TopXMLNS, __IgnoreEls, _el), Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PRODID">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, decode_vcard_PRODID(__TopXMLNS, __IgnoreEls, _el), Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"REV">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, decode_vcard_REV(__TopXMLNS, __IgnoreEls, _el), Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"SORT-STRING">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, decode_vcard_SORT_STRING(__TopXMLNS, __IgnoreEls, _el), Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"UID">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, decode_vcard_UID(__TopXMLNS, __IgnoreEls, _el), Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"URL">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, decode_vcard_URL(__TopXMLNS, __IgnoreEls, _el), Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"DESC">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, decode_vcard_DESC(__TopXMLNS, __IgnoreEls, _el), Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"CATEGORIES">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, decode_vcard_CATEGORIES(__TopXMLNS, __IgnoreEls, _el), Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"CLASS">>, _attrs, _} = _el | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, decode_vcard_CLASS(__TopXMLNS, __IgnoreEls, _el), Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo); true -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) end; decode_vcard_els(__TopXMLNS, __IgnoreEls, [_ | _els], Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo) -> decode_vcard_els(__TopXMLNS, __IgnoreEls, _els, Mailer, Adr, Class, Categories, Desc, Uid, Prodid, Jabberid, Sound, Note, Role, Title, Nickname, Rev, Sort_string, Org, Bday, Key, Tz, Url, Email, Tel, Label, Fn, Version, N, Photo, Logo, Geo). encode_vcard({vcard, Version, Fn, N, Nickname, Photo, Bday, Adr, Label, Tel, Email, Jabberid, Mailer, Tz, Geo, Title, Role, Logo, Org, Categories, Note, Prodid, Rev, Sort_string, Sound, Uid, Url, Class, Key, Desc}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_$mailer'(Mailer, 'encode_vcard_$adr'(Adr, 'encode_vcard_$class'(Class, 'encode_vcard_$categories'(Categories, 'encode_vcard_$desc'(Desc, 'encode_vcard_$uid'(Uid, 'encode_vcard_$prodid'(Prodid, 'encode_vcard_$jabberid'(Jabberid, 'encode_vcard_$sound'(Sound, 'encode_vcard_$note'(Note, 'encode_vcard_$role'(Role, 'encode_vcard_$title'(Title, 'encode_vcard_$nickname'(Nickname, 'encode_vcard_$rev'(Rev, 'encode_vcard_$sort_string'(Sort_string, 'encode_vcard_$org'(Org, 'encode_vcard_$bday'(Bday, 'encode_vcard_$key'(Key, 'encode_vcard_$tz'(Tz, 'encode_vcard_$url'(Url, 'encode_vcard_$email'(Email, 'encode_vcard_$tel'(Tel, 'encode_vcard_$label'(Label, 'encode_vcard_$fn'(Fn, 'encode_vcard_$version'(Version, 'encode_vcard_$n'(N, 'encode_vcard_$photo'(Photo, 'encode_vcard_$logo'(Logo, 'encode_vcard_$geo'(Geo, [])))))))))))))))))))))))))))))), _attrs = _xmlns_attrs, {xmlel, <<"vCard">>, _attrs, _els}. 'encode_vcard_$mailer'(undefined, _acc) -> _acc; 'encode_vcard_$mailer'(Mailer, _acc) -> [encode_vcard_MAILER(Mailer, []) | _acc]. 'encode_vcard_$adr'([], _acc) -> _acc; 'encode_vcard_$adr'([Adr | _els], _acc) -> 'encode_vcard_$adr'(_els, [encode_vcard_ADR(Adr, []) | _acc]). 'encode_vcard_$class'(undefined, _acc) -> _acc; 'encode_vcard_$class'(Class, _acc) -> [encode_vcard_CLASS(Class, []) | _acc]. 'encode_vcard_$categories'([], _acc) -> _acc; 'encode_vcard_$categories'(Categories, _acc) -> [encode_vcard_CATEGORIES(Categories, []) | _acc]. 'encode_vcard_$desc'(undefined, _acc) -> _acc; 'encode_vcard_$desc'(Desc, _acc) -> [encode_vcard_DESC(Desc, []) | _acc]. 'encode_vcard_$uid'(undefined, _acc) -> _acc; 'encode_vcard_$uid'(Uid, _acc) -> [encode_vcard_UID(Uid, []) | _acc]. 'encode_vcard_$prodid'(undefined, _acc) -> _acc; 'encode_vcard_$prodid'(Prodid, _acc) -> [encode_vcard_PRODID(Prodid, []) | _acc]. 'encode_vcard_$jabberid'(undefined, _acc) -> _acc; 'encode_vcard_$jabberid'(Jabberid, _acc) -> [encode_vcard_JABBERID(Jabberid, []) | _acc]. 'encode_vcard_$sound'(undefined, _acc) -> _acc; 'encode_vcard_$sound'(Sound, _acc) -> [encode_vcard_SOUND(Sound, []) | _acc]. 'encode_vcard_$note'(undefined, _acc) -> _acc; 'encode_vcard_$note'(Note, _acc) -> [encode_vcard_NOTE(Note, []) | _acc]. 'encode_vcard_$role'(undefined, _acc) -> _acc; 'encode_vcard_$role'(Role, _acc) -> [encode_vcard_ROLE(Role, []) | _acc]. 'encode_vcard_$title'(undefined, _acc) -> _acc; 'encode_vcard_$title'(Title, _acc) -> [encode_vcard_TITLE(Title, []) | _acc]. 'encode_vcard_$nickname'(undefined, _acc) -> _acc; 'encode_vcard_$nickname'(Nickname, _acc) -> [encode_vcard_NICKNAME(Nickname, []) | _acc]. 'encode_vcard_$rev'(undefined, _acc) -> _acc; 'encode_vcard_$rev'(Rev, _acc) -> [encode_vcard_REV(Rev, []) | _acc]. 'encode_vcard_$sort_string'(undefined, _acc) -> _acc; 'encode_vcard_$sort_string'(Sort_string, _acc) -> [encode_vcard_SORT_STRING(Sort_string, []) | _acc]. 'encode_vcard_$org'(undefined, _acc) -> _acc; 'encode_vcard_$org'(Org, _acc) -> [encode_vcard_ORG(Org, []) | _acc]. 'encode_vcard_$bday'(undefined, _acc) -> _acc; 'encode_vcard_$bday'(Bday, _acc) -> [encode_vcard_BDAY(Bday, []) | _acc]. 'encode_vcard_$key'(undefined, _acc) -> _acc; 'encode_vcard_$key'(Key, _acc) -> [encode_vcard_KEY(Key, []) | _acc]. 'encode_vcard_$tz'(undefined, _acc) -> _acc; 'encode_vcard_$tz'(Tz, _acc) -> [encode_vcard_TZ(Tz, []) | _acc]. 'encode_vcard_$url'(undefined, _acc) -> _acc; 'encode_vcard_$url'(Url, _acc) -> [encode_vcard_URL(Url, []) | _acc]. 'encode_vcard_$email'([], _acc) -> _acc; 'encode_vcard_$email'([Email | _els], _acc) -> 'encode_vcard_$email'(_els, [encode_vcard_EMAIL(Email, []) | _acc]). 'encode_vcard_$tel'([], _acc) -> _acc; 'encode_vcard_$tel'([Tel | _els], _acc) -> 'encode_vcard_$tel'(_els, [encode_vcard_TEL(Tel, []) | _acc]). 'encode_vcard_$label'([], _acc) -> _acc; 'encode_vcard_$label'([Label | _els], _acc) -> 'encode_vcard_$label'(_els, [encode_vcard_LABEL(Label, []) | _acc]). 'encode_vcard_$fn'(undefined, _acc) -> _acc; 'encode_vcard_$fn'(Fn, _acc) -> [encode_vcard_FN(Fn, []) | _acc]. 'encode_vcard_$version'(undefined, _acc) -> _acc; 'encode_vcard_$version'(Version, _acc) -> [encode_vcard_VERSION(Version, []) | _acc]. 'encode_vcard_$n'(undefined, _acc) -> _acc; 'encode_vcard_$n'(N, _acc) -> [encode_vcard_N(N, []) | _acc]. 'encode_vcard_$photo'(undefined, _acc) -> _acc; 'encode_vcard_$photo'(Photo, _acc) -> [encode_vcard_PHOTO(Photo, []) | _acc]. 'encode_vcard_$logo'(undefined, _acc) -> _acc; 'encode_vcard_$logo'(Logo, _acc) -> [encode_vcard_LOGO(Logo, []) | _acc]. 'encode_vcard_$geo'(undefined, _acc) -> _acc; 'encode_vcard_$geo'(Geo, _acc) -> [encode_vcard_GEO(Geo, []) | _acc]. decode_vcard_CLASS(__TopXMLNS, __IgnoreEls, {xmlel, <<"CLASS">>, _attrs, _els}) -> Class = decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els, undefined), Class. decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, [], Class) -> Class; decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PUBLIC">>, _attrs, _} = _el | _els], Class) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_PUBLIC(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els, Class) end; decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PRIVATE">>, _attrs, _} = _el | _els], Class) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_PRIVATE(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els, Class) end; decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"CONFIDENTIAL">>, _attrs, _} = _el | _els], Class) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_CONFIDENTIAL(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els, Class) end; decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, [_ | _els], Class) -> decode_vcard_CLASS_els(__TopXMLNS, __IgnoreEls, _els, Class). encode_vcard_CLASS(Class, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_CLASS_$class'(Class, [])), _attrs = _xmlns_attrs, {xmlel, <<"CLASS">>, _attrs, _els}. 'encode_vcard_CLASS_$class'(undefined, _acc) -> _acc; 'encode_vcard_CLASS_$class'(public = Class, _acc) -> [encode_vcard_PUBLIC(Class, []) | _acc]; 'encode_vcard_CLASS_$class'(private = Class, _acc) -> [encode_vcard_PRIVATE(Class, []) | _acc]; 'encode_vcard_CLASS_$class'(confidential = Class, _acc) -> [encode_vcard_CONFIDENTIAL(Class, []) | _acc]. decode_vcard_CATEGORIES(__TopXMLNS, __IgnoreEls, {xmlel, <<"CATEGORIES">>, _attrs, _els}) -> Keywords = decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls, _els, []), Keywords. decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls, [], Keywords) -> lists:reverse(Keywords); decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"KEYWORD">>, _attrs, _} = _el | _els], Keywords) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls, _els, case decode_vcard_KEYWORD(__TopXMLNS, __IgnoreEls, _el) of undefined -> Keywords; _new_el -> [_new_el | Keywords] end); true -> decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls, _els, Keywords) end; decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls, [_ | _els], Keywords) -> decode_vcard_CATEGORIES_els(__TopXMLNS, __IgnoreEls, _els, Keywords). encode_vcard_CATEGORIES(Keywords, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_CATEGORIES_$keywords'(Keywords, [])), _attrs = _xmlns_attrs, {xmlel, <<"CATEGORIES">>, _attrs, _els}. 'encode_vcard_CATEGORIES_$keywords'([], _acc) -> _acc; 'encode_vcard_CATEGORIES_$keywords'([Keywords | _els], _acc) -> 'encode_vcard_CATEGORIES_$keywords'(_els, [encode_vcard_KEYWORD(Keywords, []) | _acc]). decode_vcard_KEY(__TopXMLNS, __IgnoreEls, {xmlel, <<"KEY">>, _attrs, _els}) -> {Cred, Type} = decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), {vcard_key, Type, Cred}. decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, [], Cred, Type) -> {Cred, Type}; decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"TYPE">>, _attrs, _} = _el | _els], Cred, Type) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els, Cred, decode_vcard_TYPE(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els, Cred, Type) end; decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"CRED">>, _attrs, _} = _el | _els], Cred, Type) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_CRED(__TopXMLNS, __IgnoreEls, _el), Type); true -> decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els, Cred, Type) end; decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cred, Type) -> decode_vcard_KEY_els(__TopXMLNS, __IgnoreEls, _els, Cred, Type). encode_vcard_KEY({vcard_key, Type, Cred}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_KEY_$cred'(Cred, 'encode_vcard_KEY_$type'(Type, []))), _attrs = _xmlns_attrs, {xmlel, <<"KEY">>, _attrs, _els}. 'encode_vcard_KEY_$cred'(undefined, _acc) -> _acc; 'encode_vcard_KEY_$cred'(Cred, _acc) -> [encode_vcard_CRED(Cred, []) | _acc]. 'encode_vcard_KEY_$type'(undefined, _acc) -> _acc; 'encode_vcard_KEY_$type'(Type, _acc) -> [encode_vcard_TYPE(Type, []) | _acc]. decode_vcard_SOUND(__TopXMLNS, __IgnoreEls, {xmlel, <<"SOUND">>, _attrs, _els}) -> {Phonetic, Extval, Binval} = decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined), {vcard_sound, Phonetic, Binval, Extval}. decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, [], Phonetic, Extval, Binval) -> {Phonetic, Extval, Binval}; decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"BINVAL">>, _attrs, _} = _el | _els], Phonetic, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els, Phonetic, Extval, decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els, Phonetic, Extval, Binval) end; decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"EXTVAL">>, _attrs, _} = _el | _els], Phonetic, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els, Phonetic, decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls, _el), Binval); true -> decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els, Phonetic, Extval, Binval) end; decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PHONETIC">>, _attrs, _} = _el | _els], Phonetic, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_PHONETIC(__TopXMLNS, __IgnoreEls, _el), Extval, Binval); true -> decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els, Phonetic, Extval, Binval) end; decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, [_ | _els], Phonetic, Extval, Binval) -> decode_vcard_SOUND_els(__TopXMLNS, __IgnoreEls, _els, Phonetic, Extval, Binval). encode_vcard_SOUND({vcard_sound, Phonetic, Binval, Extval}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_SOUND_$phonetic'(Phonetic, 'encode_vcard_SOUND_$extval'(Extval, 'encode_vcard_SOUND_$binval'(Binval, [])))), _attrs = _xmlns_attrs, {xmlel, <<"SOUND">>, _attrs, _els}. 'encode_vcard_SOUND_$phonetic'(undefined, _acc) -> _acc; 'encode_vcard_SOUND_$phonetic'(Phonetic, _acc) -> [encode_vcard_PHONETIC(Phonetic, []) | _acc]. 'encode_vcard_SOUND_$extval'(undefined, _acc) -> _acc; 'encode_vcard_SOUND_$extval'(Extval, _acc) -> [encode_vcard_EXTVAL(Extval, []) | _acc]. 'encode_vcard_SOUND_$binval'(undefined, _acc) -> _acc; 'encode_vcard_SOUND_$binval'(Binval, _acc) -> [encode_vcard_BINVAL(Binval, []) | _acc]. decode_vcard_ORG(__TopXMLNS, __IgnoreEls, {xmlel, <<"ORG">>, _attrs, _els}) -> {Units, Name} = decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els, [], undefined), {vcard_org, Name, Units}. decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, [], Units, Name) -> {lists:reverse(Units), Name}; decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"ORGNAME">>, _attrs, _} = _el | _els], Units, Name) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els, Units, decode_vcard_ORGNAME(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els, Units, Name) end; decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"ORGUNIT">>, _attrs, _} = _el | _els], Units, Name) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els, case decode_vcard_ORGUNIT(__TopXMLNS, __IgnoreEls, _el) of undefined -> Units; _new_el -> [_new_el | Units] end, Name); true -> decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els, Units, Name) end; decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, [_ | _els], Units, Name) -> decode_vcard_ORG_els(__TopXMLNS, __IgnoreEls, _els, Units, Name). encode_vcard_ORG({vcard_org, Name, Units}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_ORG_$units'(Units, 'encode_vcard_ORG_$name'(Name, []))), _attrs = _xmlns_attrs, {xmlel, <<"ORG">>, _attrs, _els}. 'encode_vcard_ORG_$units'([], _acc) -> _acc; 'encode_vcard_ORG_$units'([Units | _els], _acc) -> 'encode_vcard_ORG_$units'(_els, [encode_vcard_ORGUNIT(Units, []) | _acc]). 'encode_vcard_ORG_$name'(undefined, _acc) -> _acc; 'encode_vcard_ORG_$name'(Name, _acc) -> [encode_vcard_ORGNAME(Name, []) | _acc]. decode_vcard_PHOTO(__TopXMLNS, __IgnoreEls, {xmlel, <<"PHOTO">>, _attrs, _els}) -> {Type, Extval, Binval} = decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined), {vcard_photo, Type, Binval, Extval}. decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, [], Type, Extval, Binval) -> {Type, Extval, Binval}; decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"TYPE">>, _attrs, _} = _el | _els], Type, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_TYPE(__TopXMLNS, __IgnoreEls, _el), Extval, Binval); true -> decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, Binval) end; decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"BINVAL">>, _attrs, _} = _el | _els], Type, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, Binval) end; decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"EXTVAL">>, _attrs, _} = _el | _els], Type, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els, Type, decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls, _el), Binval); true -> decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, Binval) end; decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, [_ | _els], Type, Extval, Binval) -> decode_vcard_PHOTO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, Binval). encode_vcard_PHOTO({vcard_photo, Type, Binval, Extval}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_PHOTO_$type'(Type, 'encode_vcard_PHOTO_$extval'(Extval, 'encode_vcard_PHOTO_$binval'(Binval, [])))), _attrs = _xmlns_attrs, {xmlel, <<"PHOTO">>, _attrs, _els}. 'encode_vcard_PHOTO_$type'(undefined, _acc) -> _acc; 'encode_vcard_PHOTO_$type'(Type, _acc) -> [encode_vcard_TYPE(Type, []) | _acc]. 'encode_vcard_PHOTO_$extval'(undefined, _acc) -> _acc; 'encode_vcard_PHOTO_$extval'(Extval, _acc) -> [encode_vcard_EXTVAL(Extval, []) | _acc]. 'encode_vcard_PHOTO_$binval'(undefined, _acc) -> _acc; 'encode_vcard_PHOTO_$binval'(Binval, _acc) -> [encode_vcard_BINVAL(Binval, []) | _acc]. decode_vcard_LOGO(__TopXMLNS, __IgnoreEls, {xmlel, <<"LOGO">>, _attrs, _els}) -> {Type, Extval, Binval} = decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined), {vcard_logo, Type, Binval, Extval}. decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, [], Type, Extval, Binval) -> {Type, Extval, Binval}; decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"TYPE">>, _attrs, _} = _el | _els], Type, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_TYPE(__TopXMLNS, __IgnoreEls, _el), Extval, Binval); true -> decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, Binval) end; decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"BINVAL">>, _attrs, _} = _el | _els], Type, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, Binval) end; decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"EXTVAL">>, _attrs, _} = _el | _els], Type, Extval, Binval) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els, Type, decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls, _el), Binval); true -> decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, Binval) end; decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, [_ | _els], Type, Extval, Binval) -> decode_vcard_LOGO_els(__TopXMLNS, __IgnoreEls, _els, Type, Extval, Binval). encode_vcard_LOGO({vcard_logo, Type, Binval, Extval}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_LOGO_$type'(Type, 'encode_vcard_LOGO_$extval'(Extval, 'encode_vcard_LOGO_$binval'(Binval, [])))), _attrs = _xmlns_attrs, {xmlel, <<"LOGO">>, _attrs, _els}. 'encode_vcard_LOGO_$type'(undefined, _acc) -> _acc; 'encode_vcard_LOGO_$type'(Type, _acc) -> [encode_vcard_TYPE(Type, []) | _acc]. 'encode_vcard_LOGO_$extval'(undefined, _acc) -> _acc; 'encode_vcard_LOGO_$extval'(Extval, _acc) -> [encode_vcard_EXTVAL(Extval, []) | _acc]. 'encode_vcard_LOGO_$binval'(undefined, _acc) -> _acc; 'encode_vcard_LOGO_$binval'(Binval, _acc) -> [encode_vcard_BINVAL(Binval, []) | _acc]. decode_vcard_BINVAL(__TopXMLNS, __IgnoreEls, {xmlel, <<"BINVAL">>, _attrs, _els}) -> Cdata = decode_vcard_BINVAL_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_BINVAL_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_BINVAL_cdata(__TopXMLNS, Cdata); decode_vcard_BINVAL_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_BINVAL_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_BINVAL_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_BINVAL_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_BINVAL(Cdata, _xmlns_attrs) -> _els = encode_vcard_BINVAL_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"BINVAL">>, _attrs, _els}. decode_vcard_BINVAL_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_BINVAL_cdata(__TopXMLNS, _val) -> case catch base64:decode(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"BINVAL">>, __TopXMLNS}}); _res -> _res end. encode_vcard_BINVAL_cdata(undefined, _acc) -> _acc; encode_vcard_BINVAL_cdata(_val, _acc) -> [{xmlcdata, base64:encode(_val)} | _acc]. decode_vcard_GEO(__TopXMLNS, __IgnoreEls, {xmlel, <<"GEO">>, _attrs, _els}) -> {Lat, Lon} = decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), {vcard_geo, Lat, Lon}. decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, [], Lat, Lon) -> {Lat, Lon}; decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"LAT">>, _attrs, _} = _el | _els], Lat, Lon) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_LAT(__TopXMLNS, __IgnoreEls, _el), Lon); true -> decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat, Lon) end; decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"LON">>, _attrs, _} = _el | _els], Lat, Lon) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat, decode_vcard_LON(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat, Lon) end; decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, [_ | _els], Lat, Lon) -> decode_vcard_GEO_els(__TopXMLNS, __IgnoreEls, _els, Lat, Lon). encode_vcard_GEO({vcard_geo, Lat, Lon}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_GEO_$lat'(Lat, 'encode_vcard_GEO_$lon'(Lon, []))), _attrs = _xmlns_attrs, {xmlel, <<"GEO">>, _attrs, _els}. 'encode_vcard_GEO_$lat'(undefined, _acc) -> _acc; 'encode_vcard_GEO_$lat'(Lat, _acc) -> [encode_vcard_LAT(Lat, []) | _acc]. 'encode_vcard_GEO_$lon'(undefined, _acc) -> _acc; 'encode_vcard_GEO_$lon'(Lon, _acc) -> [encode_vcard_LON(Lon, []) | _acc]. decode_vcard_EMAIL(__TopXMLNS, __IgnoreEls, {xmlel, <<"EMAIL">>, _attrs, _els}) -> {X400, Userid, Internet, Home, Pref, Work} = decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, false, undefined, false, false, false, false), {vcard_email, Home, Work, Internet, Pref, X400, Userid}. decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [], X400, Userid, Internet, Home, Pref, Work) -> {X400, Userid, Internet, Home, Pref, Work}; decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"HOME">>, _attrs, _} = _el | _els], X400, Userid, Internet, Home, Pref, Work) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, decode_vcard_HOME(__TopXMLNS, __IgnoreEls, _el), Pref, Work); true -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, Pref, Work) end; decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"WORK">>, _attrs, _} = _el | _els], X400, Userid, Internet, Home, Pref, Work) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, Pref, decode_vcard_WORK(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, Pref, Work) end; decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"INTERNET">>, _attrs, _} = _el | _els], X400, Userid, Internet, Home, Pref, Work) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, decode_vcard_INTERNET(__TopXMLNS, __IgnoreEls, _el), Home, Pref, Work); true -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, Pref, Work) end; decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PREF">>, _attrs, _} = _el | _els], X400, Userid, Internet, Home, Pref, Work) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, decode_vcard_PREF(__TopXMLNS, __IgnoreEls, _el), Work); true -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, Pref, Work) end; decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"X400">>, _attrs, _} = _el | _els], X400, Userid, Internet, Home, Pref, Work) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_X400(__TopXMLNS, __IgnoreEls, _el), Userid, Internet, Home, Pref, Work); true -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, Pref, Work) end; decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"USERID">>, _attrs, _} = _el | _els], X400, Userid, Internet, Home, Pref, Work) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, decode_vcard_USERID(__TopXMLNS, __IgnoreEls, _el), Internet, Home, Pref, Work); true -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, Pref, Work) end; decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, [_ | _els], X400, Userid, Internet, Home, Pref, Work) -> decode_vcard_EMAIL_els(__TopXMLNS, __IgnoreEls, _els, X400, Userid, Internet, Home, Pref, Work). encode_vcard_EMAIL({vcard_email, Home, Work, Internet, Pref, X400, Userid}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_EMAIL_$x400'(X400, 'encode_vcard_EMAIL_$userid'(Userid, 'encode_vcard_EMAIL_$internet'(Internet, 'encode_vcard_EMAIL_$home'(Home, 'encode_vcard_EMAIL_$pref'(Pref, 'encode_vcard_EMAIL_$work'(Work, []))))))), _attrs = _xmlns_attrs, {xmlel, <<"EMAIL">>, _attrs, _els}. 'encode_vcard_EMAIL_$x400'(false, _acc) -> _acc; 'encode_vcard_EMAIL_$x400'(X400, _acc) -> [encode_vcard_X400(X400, []) | _acc]. 'encode_vcard_EMAIL_$userid'(undefined, _acc) -> _acc; 'encode_vcard_EMAIL_$userid'(Userid, _acc) -> [encode_vcard_USERID(Userid, []) | _acc]. 'encode_vcard_EMAIL_$internet'(false, _acc) -> _acc; 'encode_vcard_EMAIL_$internet'(Internet, _acc) -> [encode_vcard_INTERNET(Internet, []) | _acc]. 'encode_vcard_EMAIL_$home'(false, _acc) -> _acc; 'encode_vcard_EMAIL_$home'(Home, _acc) -> [encode_vcard_HOME(Home, []) | _acc]. 'encode_vcard_EMAIL_$pref'(false, _acc) -> _acc; 'encode_vcard_EMAIL_$pref'(Pref, _acc) -> [encode_vcard_PREF(Pref, []) | _acc]. 'encode_vcard_EMAIL_$work'(false, _acc) -> _acc; 'encode_vcard_EMAIL_$work'(Work, _acc) -> [encode_vcard_WORK(Work, []) | _acc]. decode_vcard_TEL(__TopXMLNS, __IgnoreEls, {xmlel, <<"TEL">>, _attrs, _els}) -> {Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video} = decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, undefined, false, false, false, false, false, false, false, false, false, false, false, false, false), {vcard_tel, Home, Work, Voice, Fax, Pager, Msg, Cell, Video, Bbs, Modem, Isdn, Pcs, Pref, Number}. decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> {Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video}; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"HOME">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, decode_vcard_HOME(__TopXMLNS, __IgnoreEls, _el), Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"WORK">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, decode_vcard_WORK(__TopXMLNS, __IgnoreEls, _el), Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"VOICE">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, decode_vcard_VOICE(__TopXMLNS, __IgnoreEls, _el), Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"FAX">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, decode_vcard_FAX(__TopXMLNS, __IgnoreEls, _el), Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PAGER">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, decode_vcard_PAGER(__TopXMLNS, __IgnoreEls, _el), Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"MSG">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, decode_vcard_MSG(__TopXMLNS, __IgnoreEls, _el), Fax, Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"CELL">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, decode_vcard_CELL(__TopXMLNS, __IgnoreEls, _el), Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"VIDEO">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, decode_vcard_VIDEO(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"BBS">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, decode_vcard_BBS(__TopXMLNS, __IgnoreEls, _el), Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"MODEM">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, decode_vcard_MODEM(__TopXMLNS, __IgnoreEls, _el), Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"ISDN">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, decode_vcard_ISDN(__TopXMLNS, __IgnoreEls, _el), Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PCS">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, decode_vcard_PCS(__TopXMLNS, __IgnoreEls, _el), Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PREF">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, decode_vcard_PREF(__TopXMLNS, __IgnoreEls, _el), Msg, Fax, Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"NUMBER">>, _attrs, _} = _el | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_NUMBER(__TopXMLNS, __IgnoreEls, _el), Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video); true -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) end; decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, [_ | _els], Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video) -> decode_vcard_TEL_els(__TopXMLNS, __IgnoreEls, _els, Number, Pager, Pcs, Bbs, Voice, Home, Pref, Msg, Fax, Work, Cell, Modem, Isdn, Video). encode_vcard_TEL({vcard_tel, Home, Work, Voice, Fax, Pager, Msg, Cell, Video, Bbs, Modem, Isdn, Pcs, Pref, Number}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_TEL_$number'(Number, 'encode_vcard_TEL_$pager'(Pager, 'encode_vcard_TEL_$pcs'(Pcs, 'encode_vcard_TEL_$bbs'(Bbs, 'encode_vcard_TEL_$voice'(Voice, 'encode_vcard_TEL_$home'(Home, 'encode_vcard_TEL_$pref'(Pref, 'encode_vcard_TEL_$msg'(Msg, 'encode_vcard_TEL_$fax'(Fax, 'encode_vcard_TEL_$work'(Work, 'encode_vcard_TEL_$cell'(Cell, 'encode_vcard_TEL_$modem'(Modem, 'encode_vcard_TEL_$isdn'(Isdn, 'encode_vcard_TEL_$video'(Video, []))))))))))))))), _attrs = _xmlns_attrs, {xmlel, <<"TEL">>, _attrs, _els}. 'encode_vcard_TEL_$number'(undefined, _acc) -> _acc; 'encode_vcard_TEL_$number'(Number, _acc) -> [encode_vcard_NUMBER(Number, []) | _acc]. 'encode_vcard_TEL_$pager'(false, _acc) -> _acc; 'encode_vcard_TEL_$pager'(Pager, _acc) -> [encode_vcard_PAGER(Pager, []) | _acc]. 'encode_vcard_TEL_$pcs'(false, _acc) -> _acc; 'encode_vcard_TEL_$pcs'(Pcs, _acc) -> [encode_vcard_PCS(Pcs, []) | _acc]. 'encode_vcard_TEL_$bbs'(false, _acc) -> _acc; 'encode_vcard_TEL_$bbs'(Bbs, _acc) -> [encode_vcard_BBS(Bbs, []) | _acc]. 'encode_vcard_TEL_$voice'(false, _acc) -> _acc; 'encode_vcard_TEL_$voice'(Voice, _acc) -> [encode_vcard_VOICE(Voice, []) | _acc]. 'encode_vcard_TEL_$home'(false, _acc) -> _acc; 'encode_vcard_TEL_$home'(Home, _acc) -> [encode_vcard_HOME(Home, []) | _acc]. 'encode_vcard_TEL_$pref'(false, _acc) -> _acc; 'encode_vcard_TEL_$pref'(Pref, _acc) -> [encode_vcard_PREF(Pref, []) | _acc]. 'encode_vcard_TEL_$msg'(false, _acc) -> _acc; 'encode_vcard_TEL_$msg'(Msg, _acc) -> [encode_vcard_MSG(Msg, []) | _acc]. 'encode_vcard_TEL_$fax'(false, _acc) -> _acc; 'encode_vcard_TEL_$fax'(Fax, _acc) -> [encode_vcard_FAX(Fax, []) | _acc]. 'encode_vcard_TEL_$work'(false, _acc) -> _acc; 'encode_vcard_TEL_$work'(Work, _acc) -> [encode_vcard_WORK(Work, []) | _acc]. 'encode_vcard_TEL_$cell'(false, _acc) -> _acc; 'encode_vcard_TEL_$cell'(Cell, _acc) -> [encode_vcard_CELL(Cell, []) | _acc]. 'encode_vcard_TEL_$modem'(false, _acc) -> _acc; 'encode_vcard_TEL_$modem'(Modem, _acc) -> [encode_vcard_MODEM(Modem, []) | _acc]. 'encode_vcard_TEL_$isdn'(false, _acc) -> _acc; 'encode_vcard_TEL_$isdn'(Isdn, _acc) -> [encode_vcard_ISDN(Isdn, []) | _acc]. 'encode_vcard_TEL_$video'(false, _acc) -> _acc; 'encode_vcard_TEL_$video'(Video, _acc) -> [encode_vcard_VIDEO(Video, []) | _acc]. decode_vcard_LABEL(__TopXMLNS, __IgnoreEls, {xmlel, <<"LABEL">>, _attrs, _els}) -> {Line, Home, Pref, Work, Intl, Parcel, Postal, Dom} = decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, [], false, false, false, false, false, false, false), {vcard_label, Home, Work, Postal, Parcel, Dom, Intl, Pref, Line}. decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> {lists:reverse(Line), Home, Pref, Work, Intl, Parcel, Postal, Dom}; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"HOME">>, _attrs, _} = _el | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, decode_vcard_HOME(__TopXMLNS, __IgnoreEls, _el), Pref, Work, Intl, Parcel, Postal, Dom); true -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) end; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"WORK">>, _attrs, _} = _el | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, decode_vcard_WORK(__TopXMLNS, __IgnoreEls, _el), Intl, Parcel, Postal, Dom); true -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) end; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"POSTAL">>, _attrs, _} = _el | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, decode_vcard_POSTAL(__TopXMLNS, __IgnoreEls, _el), Dom); true -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) end; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PARCEL">>, _attrs, _} = _el | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, decode_vcard_PARCEL(__TopXMLNS, __IgnoreEls, _el), Postal, Dom); true -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) end; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"DOM">>, _attrs, _} = _el | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, decode_vcard_DOM(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) end; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"INTL">>, _attrs, _} = _el | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, decode_vcard_INTL(__TopXMLNS, __IgnoreEls, _el), Parcel, Postal, Dom); true -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) end; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PREF">>, _attrs, _} = _el | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, decode_vcard_PREF(__TopXMLNS, __IgnoreEls, _el), Work, Intl, Parcel, Postal, Dom); true -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) end; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"LINE">>, _attrs, _} = _el | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, case decode_vcard_LINE(__TopXMLNS, __IgnoreEls, _el) of undefined -> Line; _new_el -> [_new_el | Line] end, Home, Pref, Work, Intl, Parcel, Postal, Dom); true -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) end; decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, [_ | _els], Line, Home, Pref, Work, Intl, Parcel, Postal, Dom) -> decode_vcard_LABEL_els(__TopXMLNS, __IgnoreEls, _els, Line, Home, Pref, Work, Intl, Parcel, Postal, Dom). encode_vcard_LABEL({vcard_label, Home, Work, Postal, Parcel, Dom, Intl, Pref, Line}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_LABEL_$line'(Line, 'encode_vcard_LABEL_$home'(Home, 'encode_vcard_LABEL_$pref'(Pref, 'encode_vcard_LABEL_$work'(Work, 'encode_vcard_LABEL_$intl'(Intl, 'encode_vcard_LABEL_$parcel'(Parcel, 'encode_vcard_LABEL_$postal'(Postal, 'encode_vcard_LABEL_$dom'(Dom, []))))))))), _attrs = _xmlns_attrs, {xmlel, <<"LABEL">>, _attrs, _els}. 'encode_vcard_LABEL_$line'([], _acc) -> _acc; 'encode_vcard_LABEL_$line'([Line | _els], _acc) -> 'encode_vcard_LABEL_$line'(_els, [encode_vcard_LINE(Line, []) | _acc]). 'encode_vcard_LABEL_$home'(false, _acc) -> _acc; 'encode_vcard_LABEL_$home'(Home, _acc) -> [encode_vcard_HOME(Home, []) | _acc]. 'encode_vcard_LABEL_$pref'(false, _acc) -> _acc; 'encode_vcard_LABEL_$pref'(Pref, _acc) -> [encode_vcard_PREF(Pref, []) | _acc]. 'encode_vcard_LABEL_$work'(false, _acc) -> _acc; 'encode_vcard_LABEL_$work'(Work, _acc) -> [encode_vcard_WORK(Work, []) | _acc]. 'encode_vcard_LABEL_$intl'(false, _acc) -> _acc; 'encode_vcard_LABEL_$intl'(Intl, _acc) -> [encode_vcard_INTL(Intl, []) | _acc]. 'encode_vcard_LABEL_$parcel'(false, _acc) -> _acc; 'encode_vcard_LABEL_$parcel'(Parcel, _acc) -> [encode_vcard_PARCEL(Parcel, []) | _acc]. 'encode_vcard_LABEL_$postal'(false, _acc) -> _acc; 'encode_vcard_LABEL_$postal'(Postal, _acc) -> [encode_vcard_POSTAL(Postal, []) | _acc]. 'encode_vcard_LABEL_$dom'(false, _acc) -> _acc; 'encode_vcard_LABEL_$dom'(Dom, _acc) -> [encode_vcard_DOM(Dom, []) | _acc]. decode_vcard_ADR(__TopXMLNS, __IgnoreEls, {xmlel, <<"ADR">>, _attrs, _els}) -> {Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region} = decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined, false, false, undefined, undefined, undefined, false, false, false, false, false, undefined), {vcard_adr, Home, Work, Postal, Parcel, Dom, Intl, Pref, Pobox, Extadd, Street, Locality, Region, Pcode, Ctry}. decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> {Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region}; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"HOME">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, decode_vcard_HOME(__TopXMLNS, __IgnoreEls, _el), Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"WORK">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, decode_vcard_WORK(__TopXMLNS, __IgnoreEls, _el), Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"POSTAL">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, decode_vcard_POSTAL(__TopXMLNS, __IgnoreEls, _el), Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PARCEL">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, decode_vcard_PARCEL(__TopXMLNS, __IgnoreEls, _el), Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"DOM">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, decode_vcard_DOM(__TopXMLNS, __IgnoreEls, _el), Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"INTL">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, decode_vcard_INTL(__TopXMLNS, __IgnoreEls, _el), Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PREF">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, decode_vcard_PREF(__TopXMLNS, __IgnoreEls, _el), Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"POBOX">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, decode_vcard_POBOX(__TopXMLNS, __IgnoreEls, _el), Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"EXTADD">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, decode_vcard_EXTADD(__TopXMLNS, __IgnoreEls, _el), Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"STREET">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_STREET(__TopXMLNS, __IgnoreEls, _el), Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"LOCALITY">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, decode_vcard_LOCALITY(__TopXMLNS, __IgnoreEls, _el), Work, Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"REGION">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, decode_vcard_REGION(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PCODE">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, decode_vcard_PCODE(__TopXMLNS, __IgnoreEls, _el), Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"CTRY">>, _attrs, _} = _el | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, decode_vcard_CTRY(__TopXMLNS, __IgnoreEls, _el), Locality, Work, Intl, Parcel, Postal, Dom, Region); true -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) end; decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, [_ | _els], Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region) -> decode_vcard_ADR_els(__TopXMLNS, __IgnoreEls, _els, Street, Extadd, Pcode, Home, Pref, Pobox, Ctry, Locality, Work, Intl, Parcel, Postal, Dom, Region). encode_vcard_ADR({vcard_adr, Home, Work, Postal, Parcel, Dom, Intl, Pref, Pobox, Extadd, Street, Locality, Region, Pcode, Ctry}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_ADR_$street'(Street, 'encode_vcard_ADR_$extadd'(Extadd, 'encode_vcard_ADR_$pcode'(Pcode, 'encode_vcard_ADR_$home'(Home, 'encode_vcard_ADR_$pref'(Pref, 'encode_vcard_ADR_$pobox'(Pobox, 'encode_vcard_ADR_$ctry'(Ctry, 'encode_vcard_ADR_$locality'(Locality, 'encode_vcard_ADR_$work'(Work, 'encode_vcard_ADR_$intl'(Intl, 'encode_vcard_ADR_$parcel'(Parcel, 'encode_vcard_ADR_$postal'(Postal, 'encode_vcard_ADR_$dom'(Dom, 'encode_vcard_ADR_$region'(Region, []))))))))))))))), _attrs = _xmlns_attrs, {xmlel, <<"ADR">>, _attrs, _els}. 'encode_vcard_ADR_$street'(undefined, _acc) -> _acc; 'encode_vcard_ADR_$street'(Street, _acc) -> [encode_vcard_STREET(Street, []) | _acc]. 'encode_vcard_ADR_$extadd'(undefined, _acc) -> _acc; 'encode_vcard_ADR_$extadd'(Extadd, _acc) -> [encode_vcard_EXTADD(Extadd, []) | _acc]. 'encode_vcard_ADR_$pcode'(undefined, _acc) -> _acc; 'encode_vcard_ADR_$pcode'(Pcode, _acc) -> [encode_vcard_PCODE(Pcode, []) | _acc]. 'encode_vcard_ADR_$home'(false, _acc) -> _acc; 'encode_vcard_ADR_$home'(Home, _acc) -> [encode_vcard_HOME(Home, []) | _acc]. 'encode_vcard_ADR_$pref'(false, _acc) -> _acc; 'encode_vcard_ADR_$pref'(Pref, _acc) -> [encode_vcard_PREF(Pref, []) | _acc]. 'encode_vcard_ADR_$pobox'(undefined, _acc) -> _acc; 'encode_vcard_ADR_$pobox'(Pobox, _acc) -> [encode_vcard_POBOX(Pobox, []) | _acc]. 'encode_vcard_ADR_$ctry'(undefined, _acc) -> _acc; 'encode_vcard_ADR_$ctry'(Ctry, _acc) -> [encode_vcard_CTRY(Ctry, []) | _acc]. 'encode_vcard_ADR_$locality'(undefined, _acc) -> _acc; 'encode_vcard_ADR_$locality'(Locality, _acc) -> [encode_vcard_LOCALITY(Locality, []) | _acc]. 'encode_vcard_ADR_$work'(false, _acc) -> _acc; 'encode_vcard_ADR_$work'(Work, _acc) -> [encode_vcard_WORK(Work, []) | _acc]. 'encode_vcard_ADR_$intl'(false, _acc) -> _acc; 'encode_vcard_ADR_$intl'(Intl, _acc) -> [encode_vcard_INTL(Intl, []) | _acc]. 'encode_vcard_ADR_$parcel'(false, _acc) -> _acc; 'encode_vcard_ADR_$parcel'(Parcel, _acc) -> [encode_vcard_PARCEL(Parcel, []) | _acc]. 'encode_vcard_ADR_$postal'(false, _acc) -> _acc; 'encode_vcard_ADR_$postal'(Postal, _acc) -> [encode_vcard_POSTAL(Postal, []) | _acc]. 'encode_vcard_ADR_$dom'(false, _acc) -> _acc; 'encode_vcard_ADR_$dom'(Dom, _acc) -> [encode_vcard_DOM(Dom, []) | _acc]. 'encode_vcard_ADR_$region'(undefined, _acc) -> _acc; 'encode_vcard_ADR_$region'(Region, _acc) -> [encode_vcard_REGION(Region, []) | _acc]. decode_vcard_N(__TopXMLNS, __IgnoreEls, {xmlel, <<"N">>, _attrs, _els}) -> {Middle, Suffix, Prefix, Family, Given} = decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined, undefined, undefined), {vcard_name, Family, Given, Middle, Prefix, Suffix}. decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [], Middle, Suffix, Prefix, Family, Given) -> {Middle, Suffix, Prefix, Family, Given}; decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"FAMILY">>, _attrs, _} = _el | _els], Middle, Suffix, Prefix, Family, Given) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, Prefix, decode_vcard_FAMILY(__TopXMLNS, __IgnoreEls, _el), Given); true -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, Prefix, Family, Given) end; decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"GIVEN">>, _attrs, _} = _el | _els], Middle, Suffix, Prefix, Family, Given) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, Prefix, Family, decode_vcard_GIVEN(__TopXMLNS, __IgnoreEls, _el)); true -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, Prefix, Family, Given) end; decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"MIDDLE">>, _attrs, _} = _el | _els], Middle, Suffix, Prefix, Family, Given) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, decode_vcard_MIDDLE(__TopXMLNS, __IgnoreEls, _el), Suffix, Prefix, Family, Given); true -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, Prefix, Family, Given) end; decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"PREFIX">>, _attrs, _} = _el | _els], Middle, Suffix, Prefix, Family, Given) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, decode_vcard_PREFIX(__TopXMLNS, __IgnoreEls, _el), Family, Given); true -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, Prefix, Family, Given) end; decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"SUFFIX">>, _attrs, _} = _el | _els], Middle, Suffix, Prefix, Family, Given) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, decode_vcard_SUFFIX(__TopXMLNS, __IgnoreEls, _el), Prefix, Family, Given); true -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, Prefix, Family, Given) end; decode_vcard_N_els(__TopXMLNS, __IgnoreEls, [_ | _els], Middle, Suffix, Prefix, Family, Given) -> decode_vcard_N_els(__TopXMLNS, __IgnoreEls, _els, Middle, Suffix, Prefix, Family, Given). encode_vcard_N({vcard_name, Family, Given, Middle, Prefix, Suffix}, _xmlns_attrs) -> _els = lists:reverse('encode_vcard_N_$middle'(Middle, 'encode_vcard_N_$suffix'(Suffix, 'encode_vcard_N_$prefix'(Prefix, 'encode_vcard_N_$family'(Family, 'encode_vcard_N_$given'(Given, [])))))), _attrs = _xmlns_attrs, {xmlel, <<"N">>, _attrs, _els}. 'encode_vcard_N_$middle'(undefined, _acc) -> _acc; 'encode_vcard_N_$middle'(Middle, _acc) -> [encode_vcard_MIDDLE(Middle, []) | _acc]. 'encode_vcard_N_$suffix'(undefined, _acc) -> _acc; 'encode_vcard_N_$suffix'(Suffix, _acc) -> [encode_vcard_SUFFIX(Suffix, []) | _acc]. 'encode_vcard_N_$prefix'(undefined, _acc) -> _acc; 'encode_vcard_N_$prefix'(Prefix, _acc) -> [encode_vcard_PREFIX(Prefix, []) | _acc]. 'encode_vcard_N_$family'(undefined, _acc) -> _acc; 'encode_vcard_N_$family'(Family, _acc) -> [encode_vcard_FAMILY(Family, []) | _acc]. 'encode_vcard_N_$given'(undefined, _acc) -> _acc; 'encode_vcard_N_$given'(Given, _acc) -> [encode_vcard_GIVEN(Given, []) | _acc]. decode_vcard_CONFIDENTIAL(__TopXMLNS, __IgnoreEls, {xmlel, <<"CONFIDENTIAL">>, _attrs, _els}) -> confidential. encode_vcard_CONFIDENTIAL(confidential, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"CONFIDENTIAL">>, _attrs, _els}. decode_vcard_PRIVATE(__TopXMLNS, __IgnoreEls, {xmlel, <<"PRIVATE">>, _attrs, _els}) -> private. encode_vcard_PRIVATE(private, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"PRIVATE">>, _attrs, _els}. decode_vcard_PUBLIC(__TopXMLNS, __IgnoreEls, {xmlel, <<"PUBLIC">>, _attrs, _els}) -> public. encode_vcard_PUBLIC(public, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"PUBLIC">>, _attrs, _els}. decode_vcard_EXTVAL(__TopXMLNS, __IgnoreEls, {xmlel, <<"EXTVAL">>, _attrs, _els}) -> Cdata = decode_vcard_EXTVAL_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_EXTVAL_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_EXTVAL_cdata(__TopXMLNS, Cdata); decode_vcard_EXTVAL_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_EXTVAL_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_EXTVAL_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_EXTVAL_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_EXTVAL(Cdata, _xmlns_attrs) -> _els = encode_vcard_EXTVAL_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"EXTVAL">>, _attrs, _els}. decode_vcard_EXTVAL_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_EXTVAL_cdata(__TopXMLNS, _val) -> _val. encode_vcard_EXTVAL_cdata(undefined, _acc) -> _acc; encode_vcard_EXTVAL_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_TYPE(__TopXMLNS, __IgnoreEls, {xmlel, <<"TYPE">>, _attrs, _els}) -> Cdata = decode_vcard_TYPE_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_TYPE_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_TYPE_cdata(__TopXMLNS, Cdata); decode_vcard_TYPE_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_TYPE_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_TYPE_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_TYPE_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_TYPE(Cdata, _xmlns_attrs) -> _els = encode_vcard_TYPE_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"TYPE">>, _attrs, _els}. decode_vcard_TYPE_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_TYPE_cdata(__TopXMLNS, _val) -> _val. encode_vcard_TYPE_cdata(undefined, _acc) -> _acc; encode_vcard_TYPE_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_DESC(__TopXMLNS, __IgnoreEls, {xmlel, <<"DESC">>, _attrs, _els}) -> Cdata = decode_vcard_DESC_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_DESC_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_DESC_cdata(__TopXMLNS, Cdata); decode_vcard_DESC_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_DESC_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_DESC_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_DESC_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_DESC(Cdata, _xmlns_attrs) -> _els = encode_vcard_DESC_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"DESC">>, _attrs, _els}. decode_vcard_DESC_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_DESC_cdata(__TopXMLNS, _val) -> _val. encode_vcard_DESC_cdata(undefined, _acc) -> _acc; encode_vcard_DESC_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_URL(__TopXMLNS, __IgnoreEls, {xmlel, <<"URL">>, _attrs, _els}) -> Cdata = decode_vcard_URL_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_URL_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_URL_cdata(__TopXMLNS, Cdata); decode_vcard_URL_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_URL_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_URL_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_URL_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_URL(Cdata, _xmlns_attrs) -> _els = encode_vcard_URL_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"URL">>, _attrs, _els}. decode_vcard_URL_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_URL_cdata(__TopXMLNS, _val) -> _val. encode_vcard_URL_cdata(undefined, _acc) -> _acc; encode_vcard_URL_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_UID(__TopXMLNS, __IgnoreEls, {xmlel, <<"UID">>, _attrs, _els}) -> Cdata = decode_vcard_UID_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_UID_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_UID_cdata(__TopXMLNS, Cdata); decode_vcard_UID_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_UID_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_UID_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_UID_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_UID(Cdata, _xmlns_attrs) -> _els = encode_vcard_UID_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"UID">>, _attrs, _els}. decode_vcard_UID_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_UID_cdata(__TopXMLNS, _val) -> _val. encode_vcard_UID_cdata(undefined, _acc) -> _acc; encode_vcard_UID_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_SORT_STRING(__TopXMLNS, __IgnoreEls, {xmlel, <<"SORT-STRING">>, _attrs, _els}) -> Cdata = decode_vcard_SORT_STRING_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_SORT_STRING_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_SORT_STRING_cdata(__TopXMLNS, Cdata); decode_vcard_SORT_STRING_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_SORT_STRING_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_SORT_STRING_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_SORT_STRING_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_SORT_STRING(Cdata, _xmlns_attrs) -> _els = encode_vcard_SORT_STRING_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"SORT-STRING">>, _attrs, _els}. decode_vcard_SORT_STRING_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_SORT_STRING_cdata(__TopXMLNS, _val) -> _val. encode_vcard_SORT_STRING_cdata(undefined, _acc) -> _acc; encode_vcard_SORT_STRING_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_REV(__TopXMLNS, __IgnoreEls, {xmlel, <<"REV">>, _attrs, _els}) -> Cdata = decode_vcard_REV_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_REV_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_REV_cdata(__TopXMLNS, Cdata); decode_vcard_REV_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_REV_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_REV_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_REV_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_REV(Cdata, _xmlns_attrs) -> _els = encode_vcard_REV_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"REV">>, _attrs, _els}. decode_vcard_REV_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_REV_cdata(__TopXMLNS, _val) -> _val. encode_vcard_REV_cdata(undefined, _acc) -> _acc; encode_vcard_REV_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_PRODID(__TopXMLNS, __IgnoreEls, {xmlel, <<"PRODID">>, _attrs, _els}) -> Cdata = decode_vcard_PRODID_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_PRODID_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_PRODID_cdata(__TopXMLNS, Cdata); decode_vcard_PRODID_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_PRODID_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_PRODID_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_PRODID_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_PRODID(Cdata, _xmlns_attrs) -> _els = encode_vcard_PRODID_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"PRODID">>, _attrs, _els}. decode_vcard_PRODID_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_PRODID_cdata(__TopXMLNS, _val) -> _val. encode_vcard_PRODID_cdata(undefined, _acc) -> _acc; encode_vcard_PRODID_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_NOTE(__TopXMLNS, __IgnoreEls, {xmlel, <<"NOTE">>, _attrs, _els}) -> Cdata = decode_vcard_NOTE_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_NOTE_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_NOTE_cdata(__TopXMLNS, Cdata); decode_vcard_NOTE_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_NOTE_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_NOTE_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_NOTE_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_NOTE(Cdata, _xmlns_attrs) -> _els = encode_vcard_NOTE_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"NOTE">>, _attrs, _els}. decode_vcard_NOTE_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_NOTE_cdata(__TopXMLNS, _val) -> _val. encode_vcard_NOTE_cdata(undefined, _acc) -> _acc; encode_vcard_NOTE_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_KEYWORD(__TopXMLNS, __IgnoreEls, {xmlel, <<"KEYWORD">>, _attrs, _els}) -> Cdata = decode_vcard_KEYWORD_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_KEYWORD_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_KEYWORD_cdata(__TopXMLNS, Cdata); decode_vcard_KEYWORD_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_KEYWORD_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_KEYWORD_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_KEYWORD_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_KEYWORD(Cdata, _xmlns_attrs) -> _els = encode_vcard_KEYWORD_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"KEYWORD">>, _attrs, _els}. decode_vcard_KEYWORD_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_KEYWORD_cdata(__TopXMLNS, _val) -> _val. encode_vcard_KEYWORD_cdata(undefined, _acc) -> _acc; encode_vcard_KEYWORD_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_ROLE(__TopXMLNS, __IgnoreEls, {xmlel, <<"ROLE">>, _attrs, _els}) -> Cdata = decode_vcard_ROLE_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_ROLE_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_ROLE_cdata(__TopXMLNS, Cdata); decode_vcard_ROLE_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_ROLE_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_ROLE_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_ROLE_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_ROLE(Cdata, _xmlns_attrs) -> _els = encode_vcard_ROLE_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"ROLE">>, _attrs, _els}. decode_vcard_ROLE_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_ROLE_cdata(__TopXMLNS, _val) -> _val. encode_vcard_ROLE_cdata(undefined, _acc) -> _acc; encode_vcard_ROLE_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_TITLE(__TopXMLNS, __IgnoreEls, {xmlel, <<"TITLE">>, _attrs, _els}) -> Cdata = decode_vcard_TITLE_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_TITLE_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_TITLE_cdata(__TopXMLNS, Cdata); decode_vcard_TITLE_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_TITLE_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_TITLE_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_TITLE_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_TITLE(Cdata, _xmlns_attrs) -> _els = encode_vcard_TITLE_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"TITLE">>, _attrs, _els}. decode_vcard_TITLE_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_TITLE_cdata(__TopXMLNS, _val) -> _val. encode_vcard_TITLE_cdata(undefined, _acc) -> _acc; encode_vcard_TITLE_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_TZ(__TopXMLNS, __IgnoreEls, {xmlel, <<"TZ">>, _attrs, _els}) -> Cdata = decode_vcard_TZ_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_TZ_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_TZ_cdata(__TopXMLNS, Cdata); decode_vcard_TZ_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_TZ_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_TZ_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_TZ_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_TZ(Cdata, _xmlns_attrs) -> _els = encode_vcard_TZ_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"TZ">>, _attrs, _els}. decode_vcard_TZ_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_TZ_cdata(__TopXMLNS, _val) -> _val. encode_vcard_TZ_cdata(undefined, _acc) -> _acc; encode_vcard_TZ_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_MAILER(__TopXMLNS, __IgnoreEls, {xmlel, <<"MAILER">>, _attrs, _els}) -> Cdata = decode_vcard_MAILER_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_MAILER_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_MAILER_cdata(__TopXMLNS, Cdata); decode_vcard_MAILER_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_MAILER_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_MAILER_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_MAILER_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_MAILER(Cdata, _xmlns_attrs) -> _els = encode_vcard_MAILER_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"MAILER">>, _attrs, _els}. decode_vcard_MAILER_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_MAILER_cdata(__TopXMLNS, _val) -> _val. encode_vcard_MAILER_cdata(undefined, _acc) -> _acc; encode_vcard_MAILER_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_JABBERID(__TopXMLNS, __IgnoreEls, {xmlel, <<"JABBERID">>, _attrs, _els}) -> Cdata = decode_vcard_JABBERID_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_JABBERID_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_JABBERID_cdata(__TopXMLNS, Cdata); decode_vcard_JABBERID_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_JABBERID_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_JABBERID_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_JABBERID_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_JABBERID(Cdata, _xmlns_attrs) -> _els = encode_vcard_JABBERID_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"JABBERID">>, _attrs, _els}. decode_vcard_JABBERID_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_JABBERID_cdata(__TopXMLNS, _val) -> _val. encode_vcard_JABBERID_cdata(undefined, _acc) -> _acc; encode_vcard_JABBERID_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_BDAY(__TopXMLNS, __IgnoreEls, {xmlel, <<"BDAY">>, _attrs, _els}) -> Cdata = decode_vcard_BDAY_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_BDAY_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_BDAY_cdata(__TopXMLNS, Cdata); decode_vcard_BDAY_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_BDAY_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_BDAY_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_BDAY_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_BDAY(Cdata, _xmlns_attrs) -> _els = encode_vcard_BDAY_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"BDAY">>, _attrs, _els}. decode_vcard_BDAY_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_BDAY_cdata(__TopXMLNS, _val) -> _val. encode_vcard_BDAY_cdata(undefined, _acc) -> _acc; encode_vcard_BDAY_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_NICKNAME(__TopXMLNS, __IgnoreEls, {xmlel, <<"NICKNAME">>, _attrs, _els}) -> Cdata = decode_vcard_NICKNAME_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_NICKNAME_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_NICKNAME_cdata(__TopXMLNS, Cdata); decode_vcard_NICKNAME_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_NICKNAME_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_NICKNAME_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_NICKNAME_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_NICKNAME(Cdata, _xmlns_attrs) -> _els = encode_vcard_NICKNAME_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"NICKNAME">>, _attrs, _els}. decode_vcard_NICKNAME_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_NICKNAME_cdata(__TopXMLNS, _val) -> _val. encode_vcard_NICKNAME_cdata(undefined, _acc) -> _acc; encode_vcard_NICKNAME_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_FN(__TopXMLNS, __IgnoreEls, {xmlel, <<"FN">>, _attrs, _els}) -> Cdata = decode_vcard_FN_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_FN_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_FN_cdata(__TopXMLNS, Cdata); decode_vcard_FN_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_FN_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_FN_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_FN_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_FN(Cdata, _xmlns_attrs) -> _els = encode_vcard_FN_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"FN">>, _attrs, _els}. decode_vcard_FN_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_FN_cdata(__TopXMLNS, _val) -> _val. encode_vcard_FN_cdata(undefined, _acc) -> _acc; encode_vcard_FN_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_VERSION(__TopXMLNS, __IgnoreEls, {xmlel, <<"VERSION">>, _attrs, _els}) -> Cdata = decode_vcard_VERSION_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_VERSION_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_VERSION_cdata(__TopXMLNS, Cdata); decode_vcard_VERSION_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_VERSION_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_VERSION_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_VERSION_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_VERSION(Cdata, _xmlns_attrs) -> _els = encode_vcard_VERSION_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"VERSION">>, _attrs, _els}. decode_vcard_VERSION_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_VERSION_cdata(__TopXMLNS, _val) -> _val. encode_vcard_VERSION_cdata(undefined, _acc) -> _acc; encode_vcard_VERSION_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_CRED(__TopXMLNS, __IgnoreEls, {xmlel, <<"CRED">>, _attrs, _els}) -> Cdata = decode_vcard_CRED_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_CRED_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_CRED_cdata(__TopXMLNS, Cdata); decode_vcard_CRED_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_CRED_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_CRED_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_CRED_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_CRED(Cdata, _xmlns_attrs) -> _els = encode_vcard_CRED_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"CRED">>, _attrs, _els}. decode_vcard_CRED_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_CRED_cdata(__TopXMLNS, _val) -> _val. encode_vcard_CRED_cdata(undefined, _acc) -> _acc; encode_vcard_CRED_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_PHONETIC(__TopXMLNS, __IgnoreEls, {xmlel, <<"PHONETIC">>, _attrs, _els}) -> Cdata = decode_vcard_PHONETIC_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_PHONETIC_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_PHONETIC_cdata(__TopXMLNS, Cdata); decode_vcard_PHONETIC_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_PHONETIC_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_PHONETIC_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_PHONETIC_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_PHONETIC(Cdata, _xmlns_attrs) -> _els = encode_vcard_PHONETIC_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"PHONETIC">>, _attrs, _els}. decode_vcard_PHONETIC_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_PHONETIC_cdata(__TopXMLNS, _val) -> _val. encode_vcard_PHONETIC_cdata(undefined, _acc) -> _acc; encode_vcard_PHONETIC_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_ORGUNIT(__TopXMLNS, __IgnoreEls, {xmlel, <<"ORGUNIT">>, _attrs, _els}) -> Cdata = decode_vcard_ORGUNIT_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_ORGUNIT_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_ORGUNIT_cdata(__TopXMLNS, Cdata); decode_vcard_ORGUNIT_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_ORGUNIT_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_ORGUNIT_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_ORGUNIT_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_ORGUNIT(Cdata, _xmlns_attrs) -> _els = encode_vcard_ORGUNIT_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"ORGUNIT">>, _attrs, _els}. decode_vcard_ORGUNIT_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_ORGUNIT_cdata(__TopXMLNS, _val) -> _val. encode_vcard_ORGUNIT_cdata(undefined, _acc) -> _acc; encode_vcard_ORGUNIT_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_ORGNAME(__TopXMLNS, __IgnoreEls, {xmlel, <<"ORGNAME">>, _attrs, _els}) -> Cdata = decode_vcard_ORGNAME_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_ORGNAME_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_ORGNAME_cdata(__TopXMLNS, Cdata); decode_vcard_ORGNAME_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_ORGNAME_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_ORGNAME_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_ORGNAME_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_ORGNAME(Cdata, _xmlns_attrs) -> _els = encode_vcard_ORGNAME_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"ORGNAME">>, _attrs, _els}. decode_vcard_ORGNAME_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_ORGNAME_cdata(__TopXMLNS, _val) -> _val. encode_vcard_ORGNAME_cdata(undefined, _acc) -> _acc; encode_vcard_ORGNAME_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_LON(__TopXMLNS, __IgnoreEls, {xmlel, <<"LON">>, _attrs, _els}) -> Cdata = decode_vcard_LON_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_LON_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_LON_cdata(__TopXMLNS, Cdata); decode_vcard_LON_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_LON_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_LON_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_LON_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_LON(Cdata, _xmlns_attrs) -> _els = encode_vcard_LON_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"LON">>, _attrs, _els}. decode_vcard_LON_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_LON_cdata(__TopXMLNS, _val) -> _val. encode_vcard_LON_cdata(undefined, _acc) -> _acc; encode_vcard_LON_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_LAT(__TopXMLNS, __IgnoreEls, {xmlel, <<"LAT">>, _attrs, _els}) -> Cdata = decode_vcard_LAT_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_LAT_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_LAT_cdata(__TopXMLNS, Cdata); decode_vcard_LAT_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_LAT_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_LAT_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_LAT_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_LAT(Cdata, _xmlns_attrs) -> _els = encode_vcard_LAT_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"LAT">>, _attrs, _els}. decode_vcard_LAT_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_LAT_cdata(__TopXMLNS, _val) -> _val. encode_vcard_LAT_cdata(undefined, _acc) -> _acc; encode_vcard_LAT_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_USERID(__TopXMLNS, __IgnoreEls, {xmlel, <<"USERID">>, _attrs, _els}) -> Cdata = decode_vcard_USERID_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_USERID_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_USERID_cdata(__TopXMLNS, Cdata); decode_vcard_USERID_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_USERID_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_USERID_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_USERID_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_USERID(Cdata, _xmlns_attrs) -> _els = encode_vcard_USERID_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"USERID">>, _attrs, _els}. decode_vcard_USERID_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_USERID_cdata(__TopXMLNS, _val) -> _val. encode_vcard_USERID_cdata(undefined, _acc) -> _acc; encode_vcard_USERID_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_NUMBER(__TopXMLNS, __IgnoreEls, {xmlel, <<"NUMBER">>, _attrs, _els}) -> Cdata = decode_vcard_NUMBER_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_NUMBER_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_NUMBER_cdata(__TopXMLNS, Cdata); decode_vcard_NUMBER_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_NUMBER_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_NUMBER_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_NUMBER_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_NUMBER(Cdata, _xmlns_attrs) -> _els = encode_vcard_NUMBER_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"NUMBER">>, _attrs, _els}. decode_vcard_NUMBER_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_NUMBER_cdata(__TopXMLNS, _val) -> _val. encode_vcard_NUMBER_cdata(undefined, _acc) -> _acc; encode_vcard_NUMBER_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_LINE(__TopXMLNS, __IgnoreEls, {xmlel, <<"LINE">>, _attrs, _els}) -> Cdata = decode_vcard_LINE_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_LINE_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_LINE_cdata(__TopXMLNS, Cdata); decode_vcard_LINE_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_LINE_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_LINE_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_LINE_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_LINE(Cdata, _xmlns_attrs) -> _els = encode_vcard_LINE_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"LINE">>, _attrs, _els}. decode_vcard_LINE_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_LINE_cdata(__TopXMLNS, _val) -> _val. encode_vcard_LINE_cdata(undefined, _acc) -> _acc; encode_vcard_LINE_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_CTRY(__TopXMLNS, __IgnoreEls, {xmlel, <<"CTRY">>, _attrs, _els}) -> Cdata = decode_vcard_CTRY_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_CTRY_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_CTRY_cdata(__TopXMLNS, Cdata); decode_vcard_CTRY_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_CTRY_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_CTRY_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_CTRY_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_CTRY(Cdata, _xmlns_attrs) -> _els = encode_vcard_CTRY_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"CTRY">>, _attrs, _els}. decode_vcard_CTRY_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_CTRY_cdata(__TopXMLNS, _val) -> _val. encode_vcard_CTRY_cdata(undefined, _acc) -> _acc; encode_vcard_CTRY_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_PCODE(__TopXMLNS, __IgnoreEls, {xmlel, <<"PCODE">>, _attrs, _els}) -> Cdata = decode_vcard_PCODE_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_PCODE_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_PCODE_cdata(__TopXMLNS, Cdata); decode_vcard_PCODE_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_PCODE_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_PCODE_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_PCODE_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_PCODE(Cdata, _xmlns_attrs) -> _els = encode_vcard_PCODE_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"PCODE">>, _attrs, _els}. decode_vcard_PCODE_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_PCODE_cdata(__TopXMLNS, _val) -> _val. encode_vcard_PCODE_cdata(undefined, _acc) -> _acc; encode_vcard_PCODE_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_REGION(__TopXMLNS, __IgnoreEls, {xmlel, <<"REGION">>, _attrs, _els}) -> Cdata = decode_vcard_REGION_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_REGION_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_REGION_cdata(__TopXMLNS, Cdata); decode_vcard_REGION_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_REGION_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_REGION_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_REGION_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_REGION(Cdata, _xmlns_attrs) -> _els = encode_vcard_REGION_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"REGION">>, _attrs, _els}. decode_vcard_REGION_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_REGION_cdata(__TopXMLNS, _val) -> _val. encode_vcard_REGION_cdata(undefined, _acc) -> _acc; encode_vcard_REGION_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_LOCALITY(__TopXMLNS, __IgnoreEls, {xmlel, <<"LOCALITY">>, _attrs, _els}) -> Cdata = decode_vcard_LOCALITY_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_LOCALITY_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_LOCALITY_cdata(__TopXMLNS, Cdata); decode_vcard_LOCALITY_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_LOCALITY_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_LOCALITY_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_LOCALITY_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_LOCALITY(Cdata, _xmlns_attrs) -> _els = encode_vcard_LOCALITY_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"LOCALITY">>, _attrs, _els}. decode_vcard_LOCALITY_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_LOCALITY_cdata(__TopXMLNS, _val) -> _val. encode_vcard_LOCALITY_cdata(undefined, _acc) -> _acc; encode_vcard_LOCALITY_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_STREET(__TopXMLNS, __IgnoreEls, {xmlel, <<"STREET">>, _attrs, _els}) -> Cdata = decode_vcard_STREET_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_STREET_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_STREET_cdata(__TopXMLNS, Cdata); decode_vcard_STREET_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_STREET_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_STREET_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_STREET_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_STREET(Cdata, _xmlns_attrs) -> _els = encode_vcard_STREET_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"STREET">>, _attrs, _els}. decode_vcard_STREET_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_STREET_cdata(__TopXMLNS, _val) -> _val. encode_vcard_STREET_cdata(undefined, _acc) -> _acc; encode_vcard_STREET_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_EXTADD(__TopXMLNS, __IgnoreEls, {xmlel, <<"EXTADD">>, _attrs, _els}) -> Cdata = decode_vcard_EXTADD_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_EXTADD_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_EXTADD_cdata(__TopXMLNS, Cdata); decode_vcard_EXTADD_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_EXTADD_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_EXTADD_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_EXTADD_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_EXTADD(Cdata, _xmlns_attrs) -> _els = encode_vcard_EXTADD_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"EXTADD">>, _attrs, _els}. decode_vcard_EXTADD_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_EXTADD_cdata(__TopXMLNS, _val) -> _val. encode_vcard_EXTADD_cdata(undefined, _acc) -> _acc; encode_vcard_EXTADD_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_POBOX(__TopXMLNS, __IgnoreEls, {xmlel, <<"POBOX">>, _attrs, _els}) -> Cdata = decode_vcard_POBOX_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_POBOX_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_POBOX_cdata(__TopXMLNS, Cdata); decode_vcard_POBOX_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_POBOX_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_POBOX_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_POBOX_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_POBOX(Cdata, _xmlns_attrs) -> _els = encode_vcard_POBOX_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"POBOX">>, _attrs, _els}. decode_vcard_POBOX_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_POBOX_cdata(__TopXMLNS, _val) -> _val. encode_vcard_POBOX_cdata(undefined, _acc) -> _acc; encode_vcard_POBOX_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_SUFFIX(__TopXMLNS, __IgnoreEls, {xmlel, <<"SUFFIX">>, _attrs, _els}) -> Cdata = decode_vcard_SUFFIX_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_SUFFIX_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_SUFFIX_cdata(__TopXMLNS, Cdata); decode_vcard_SUFFIX_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_SUFFIX_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_SUFFIX_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_SUFFIX_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_SUFFIX(Cdata, _xmlns_attrs) -> _els = encode_vcard_SUFFIX_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"SUFFIX">>, _attrs, _els}. decode_vcard_SUFFIX_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_SUFFIX_cdata(__TopXMLNS, _val) -> _val. encode_vcard_SUFFIX_cdata(undefined, _acc) -> _acc; encode_vcard_SUFFIX_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_PREFIX(__TopXMLNS, __IgnoreEls, {xmlel, <<"PREFIX">>, _attrs, _els}) -> Cdata = decode_vcard_PREFIX_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_PREFIX_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_PREFIX_cdata(__TopXMLNS, Cdata); decode_vcard_PREFIX_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_PREFIX_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_PREFIX_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_PREFIX_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_PREFIX(Cdata, _xmlns_attrs) -> _els = encode_vcard_PREFIX_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"PREFIX">>, _attrs, _els}. decode_vcard_PREFIX_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_PREFIX_cdata(__TopXMLNS, _val) -> _val. encode_vcard_PREFIX_cdata(undefined, _acc) -> _acc; encode_vcard_PREFIX_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_MIDDLE(__TopXMLNS, __IgnoreEls, {xmlel, <<"MIDDLE">>, _attrs, _els}) -> Cdata = decode_vcard_MIDDLE_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_MIDDLE_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_MIDDLE_cdata(__TopXMLNS, Cdata); decode_vcard_MIDDLE_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_MIDDLE_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_MIDDLE_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_MIDDLE_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_MIDDLE(Cdata, _xmlns_attrs) -> _els = encode_vcard_MIDDLE_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"MIDDLE">>, _attrs, _els}. decode_vcard_MIDDLE_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_MIDDLE_cdata(__TopXMLNS, _val) -> _val. encode_vcard_MIDDLE_cdata(undefined, _acc) -> _acc; encode_vcard_MIDDLE_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_GIVEN(__TopXMLNS, __IgnoreEls, {xmlel, <<"GIVEN">>, _attrs, _els}) -> Cdata = decode_vcard_GIVEN_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_GIVEN_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_GIVEN_cdata(__TopXMLNS, Cdata); decode_vcard_GIVEN_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_GIVEN_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_GIVEN_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_GIVEN_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_GIVEN(Cdata, _xmlns_attrs) -> _els = encode_vcard_GIVEN_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"GIVEN">>, _attrs, _els}. decode_vcard_GIVEN_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_GIVEN_cdata(__TopXMLNS, _val) -> _val. encode_vcard_GIVEN_cdata(undefined, _acc) -> _acc; encode_vcard_GIVEN_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_FAMILY(__TopXMLNS, __IgnoreEls, {xmlel, <<"FAMILY">>, _attrs, _els}) -> Cdata = decode_vcard_FAMILY_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_vcard_FAMILY_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_vcard_FAMILY_cdata(__TopXMLNS, Cdata); decode_vcard_FAMILY_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_vcard_FAMILY_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_vcard_FAMILY_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_vcard_FAMILY_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_vcard_FAMILY(Cdata, _xmlns_attrs) -> _els = encode_vcard_FAMILY_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"FAMILY">>, _attrs, _els}. decode_vcard_FAMILY_cdata(__TopXMLNS, <<>>) -> undefined; decode_vcard_FAMILY_cdata(__TopXMLNS, _val) -> _val. encode_vcard_FAMILY_cdata(undefined, _acc) -> _acc; encode_vcard_FAMILY_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_vcard_X400(__TopXMLNS, __IgnoreEls, {xmlel, <<"X400">>, _attrs, _els}) -> true. encode_vcard_X400(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"X400">>, _attrs, _els}. decode_vcard_INTERNET(__TopXMLNS, __IgnoreEls, {xmlel, <<"INTERNET">>, _attrs, _els}) -> true. encode_vcard_INTERNET(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"INTERNET">>, _attrs, _els}. decode_vcard_PREF(__TopXMLNS, __IgnoreEls, {xmlel, <<"PREF">>, _attrs, _els}) -> true. encode_vcard_PREF(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"PREF">>, _attrs, _els}. decode_vcard_INTL(__TopXMLNS, __IgnoreEls, {xmlel, <<"INTL">>, _attrs, _els}) -> true. encode_vcard_INTL(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"INTL">>, _attrs, _els}. decode_vcard_DOM(__TopXMLNS, __IgnoreEls, {xmlel, <<"DOM">>, _attrs, _els}) -> true. encode_vcard_DOM(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"DOM">>, _attrs, _els}. decode_vcard_PARCEL(__TopXMLNS, __IgnoreEls, {xmlel, <<"PARCEL">>, _attrs, _els}) -> true. encode_vcard_PARCEL(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"PARCEL">>, _attrs, _els}. decode_vcard_POSTAL(__TopXMLNS, __IgnoreEls, {xmlel, <<"POSTAL">>, _attrs, _els}) -> true. encode_vcard_POSTAL(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"POSTAL">>, _attrs, _els}. decode_vcard_PCS(__TopXMLNS, __IgnoreEls, {xmlel, <<"PCS">>, _attrs, _els}) -> true. encode_vcard_PCS(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"PCS">>, _attrs, _els}. decode_vcard_ISDN(__TopXMLNS, __IgnoreEls, {xmlel, <<"ISDN">>, _attrs, _els}) -> true. encode_vcard_ISDN(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"ISDN">>, _attrs, _els}. decode_vcard_MODEM(__TopXMLNS, __IgnoreEls, {xmlel, <<"MODEM">>, _attrs, _els}) -> true. encode_vcard_MODEM(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"MODEM">>, _attrs, _els}. decode_vcard_BBS(__TopXMLNS, __IgnoreEls, {xmlel, <<"BBS">>, _attrs, _els}) -> true. encode_vcard_BBS(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"BBS">>, _attrs, _els}. decode_vcard_VIDEO(__TopXMLNS, __IgnoreEls, {xmlel, <<"VIDEO">>, _attrs, _els}) -> true. encode_vcard_VIDEO(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"VIDEO">>, _attrs, _els}. decode_vcard_CELL(__TopXMLNS, __IgnoreEls, {xmlel, <<"CELL">>, _attrs, _els}) -> true. encode_vcard_CELL(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"CELL">>, _attrs, _els}. decode_vcard_MSG(__TopXMLNS, __IgnoreEls, {xmlel, <<"MSG">>, _attrs, _els}) -> true. encode_vcard_MSG(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"MSG">>, _attrs, _els}. decode_vcard_PAGER(__TopXMLNS, __IgnoreEls, {xmlel, <<"PAGER">>, _attrs, _els}) -> true. encode_vcard_PAGER(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"PAGER">>, _attrs, _els}. decode_vcard_FAX(__TopXMLNS, __IgnoreEls, {xmlel, <<"FAX">>, _attrs, _els}) -> true. encode_vcard_FAX(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"FAX">>, _attrs, _els}. decode_vcard_VOICE(__TopXMLNS, __IgnoreEls, {xmlel, <<"VOICE">>, _attrs, _els}) -> true. encode_vcard_VOICE(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"VOICE">>, _attrs, _els}. decode_vcard_WORK(__TopXMLNS, __IgnoreEls, {xmlel, <<"WORK">>, _attrs, _els}) -> true. encode_vcard_WORK(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"WORK">>, _attrs, _els}. decode_vcard_HOME(__TopXMLNS, __IgnoreEls, {xmlel, <<"HOME">>, _attrs, _els}) -> true. encode_vcard_HOME(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"HOME">>, _attrs, _els}. decode_stream_error(__TopXMLNS, __IgnoreEls, {xmlel, <<"stream:error">>, _attrs, _els}) -> {Text, Reason} = decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), {stream_error, Reason, Text}. decode_stream_error_els(__TopXMLNS, __IgnoreEls, [], Text, Reason) -> {Text, Reason}; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"text">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, decode_stream_error_text(_xmlns, __IgnoreEls, _el), Reason); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"bad-format">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_bad_format(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"bad-namespace-prefix">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_bad_namespace_prefix(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"conflict">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_conflict(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"connection-timeout">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_connection_timeout(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"host-gone">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_host_gone(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"host-unknown">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_host_unknown(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"improper-addressing">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_improper_addressing(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"internal-server-error">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_internal_server_error(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"invalid-from">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_invalid_from(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"invalid-id">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_invalid_id(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"invalid-namespace">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_invalid_namespace(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"invalid-xml">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_invalid_xml(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-authorized">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_not_authorized(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-well-formed">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_not_well_formed(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"policy-violation">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_policy_violation(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"remote-connection-failed">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_remote_connection_failed(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"reset">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_reset(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"resource-constraint">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_resource_constraint(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"restricted-xml">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_restricted_xml(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"see-other-host">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_see_other_host(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"system-shutdown">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_system_shutdown(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"undefined-condition">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_undefined_condition(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"unsupported-encoding">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_unsupported_encoding(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"unsupported-stanza-type">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_unsupported_stanza_type(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"unsupported-version">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-streams">> -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_stream_error_unsupported_version(_xmlns, __IgnoreEls, _el)); true -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_stream_error_els(__TopXMLNS, __IgnoreEls, [_ | _els], Text, Reason) -> decode_stream_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason). encode_stream_error({stream_error, Reason, Text}, _xmlns_attrs) -> _els = lists:reverse('encode_stream_error_$text'(Text, 'encode_stream_error_$reason'(Reason, []))), _attrs = _xmlns_attrs, {xmlel, <<"stream:error">>, _attrs, _els}. 'encode_stream_error_$text'(undefined, _acc) -> _acc; 'encode_stream_error_$text'(Text, _acc) -> [encode_stream_error_text(Text, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]. 'encode_stream_error_$reason'(undefined, _acc) -> _acc; 'encode_stream_error_$reason'('bad-format' = Reason, _acc) -> [encode_stream_error_bad_format(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('bad-namespace-prefix' = Reason, _acc) -> [encode_stream_error_bad_namespace_prefix(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'(conflict = Reason, _acc) -> [encode_stream_error_conflict(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('connection-timeout' = Reason, _acc) -> [encode_stream_error_connection_timeout(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('host-gone' = Reason, _acc) -> [encode_stream_error_host_gone(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('host-unknown' = Reason, _acc) -> [encode_stream_error_host_unknown(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('improper-addressing' = Reason, _acc) -> [encode_stream_error_improper_addressing(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('internal-server-error' = Reason, _acc) -> [encode_stream_error_internal_server_error(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('invalid-from' = Reason, _acc) -> [encode_stream_error_invalid_from(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('invalid-id' = Reason, _acc) -> [encode_stream_error_invalid_id(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('invalid-namespace' = Reason, _acc) -> [encode_stream_error_invalid_namespace(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('invalid-xml' = Reason, _acc) -> [encode_stream_error_invalid_xml(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('not-authorized' = Reason, _acc) -> [encode_stream_error_not_authorized(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('not-well-formed' = Reason, _acc) -> [encode_stream_error_not_well_formed(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('policy-violation' = Reason, _acc) -> [encode_stream_error_policy_violation(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('remote-connection-failed' = Reason, _acc) -> [encode_stream_error_remote_connection_failed(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'(reset = Reason, _acc) -> [encode_stream_error_reset(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('resource-constraint' = Reason, _acc) -> [encode_stream_error_resource_constraint(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('restricted-xml' = Reason, _acc) -> [encode_stream_error_restricted_xml(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'({'see-other-host', _} = Reason, _acc) -> [encode_stream_error_see_other_host(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('system-shutdown' = Reason, _acc) -> [encode_stream_error_system_shutdown(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('undefined-condition' = Reason, _acc) -> [encode_stream_error_undefined_condition(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('unsupported-encoding' = Reason, _acc) -> [encode_stream_error_unsupported_encoding(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('unsupported-stanza-type' = Reason, _acc) -> [encode_stream_error_unsupported_stanza_type(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]; 'encode_stream_error_$reason'('unsupported-version' = Reason, _acc) -> [encode_stream_error_unsupported_version(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-streams">>}]) | _acc]. decode_stream_error_unsupported_version(__TopXMLNS, __IgnoreEls, {xmlel, <<"unsupported-version">>, _attrs, _els}) -> 'unsupported-version'. encode_stream_error_unsupported_version('unsupported-version', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"unsupported-version">>, _attrs, _els}. decode_stream_error_unsupported_stanza_type(__TopXMLNS, __IgnoreEls, {xmlel, <<"unsupported-stanza-type">>, _attrs, _els}) -> 'unsupported-stanza-type'. encode_stream_error_unsupported_stanza_type('unsupported-stanza-type', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"unsupported-stanza-type">>, _attrs, _els}. decode_stream_error_unsupported_encoding(__TopXMLNS, __IgnoreEls, {xmlel, <<"unsupported-encoding">>, _attrs, _els}) -> 'unsupported-encoding'. encode_stream_error_unsupported_encoding('unsupported-encoding', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"unsupported-encoding">>, _attrs, _els}. decode_stream_error_undefined_condition(__TopXMLNS, __IgnoreEls, {xmlel, <<"undefined-condition">>, _attrs, _els}) -> 'undefined-condition'. encode_stream_error_undefined_condition('undefined-condition', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"undefined-condition">>, _attrs, _els}. decode_stream_error_system_shutdown(__TopXMLNS, __IgnoreEls, {xmlel, <<"system-shutdown">>, _attrs, _els}) -> 'system-shutdown'. encode_stream_error_system_shutdown('system-shutdown', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"system-shutdown">>, _attrs, _els}. decode_stream_error_see_other_host(__TopXMLNS, __IgnoreEls, {xmlel, <<"see-other-host">>, _attrs, _els}) -> Host = decode_stream_error_see_other_host_els(__TopXMLNS, __IgnoreEls, _els, <<>>), {'see-other-host', Host}. decode_stream_error_see_other_host_els(__TopXMLNS, __IgnoreEls, [], Host) -> decode_stream_error_see_other_host_cdata(__TopXMLNS, Host); decode_stream_error_see_other_host_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Host) -> decode_stream_error_see_other_host_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_stream_error_see_other_host_els(__TopXMLNS, __IgnoreEls, [_ | _els], Host) -> decode_stream_error_see_other_host_els(__TopXMLNS, __IgnoreEls, _els, Host). encode_stream_error_see_other_host({'see-other-host', Host}, _xmlns_attrs) -> _els = encode_stream_error_see_other_host_cdata(Host, []), _attrs = _xmlns_attrs, {xmlel, <<"see-other-host">>, _attrs, _els}. decode_stream_error_see_other_host_cdata(__TopXMLNS, <<>>) -> erlang:error({xmpp_codec, {missing_cdata, <<>>, <<"see-other-host">>, __TopXMLNS}}); decode_stream_error_see_other_host_cdata(__TopXMLNS, _val) -> _val. encode_stream_error_see_other_host_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_stream_error_restricted_xml(__TopXMLNS, __IgnoreEls, {xmlel, <<"restricted-xml">>, _attrs, _els}) -> 'restricted-xml'. encode_stream_error_restricted_xml('restricted-xml', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"restricted-xml">>, _attrs, _els}. decode_stream_error_resource_constraint(__TopXMLNS, __IgnoreEls, {xmlel, <<"resource-constraint">>, _attrs, _els}) -> 'resource-constraint'. encode_stream_error_resource_constraint('resource-constraint', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"resource-constraint">>, _attrs, _els}. decode_stream_error_reset(__TopXMLNS, __IgnoreEls, {xmlel, <<"reset">>, _attrs, _els}) -> reset. encode_stream_error_reset(reset, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"reset">>, _attrs, _els}. decode_stream_error_remote_connection_failed(__TopXMLNS, __IgnoreEls, {xmlel, <<"remote-connection-failed">>, _attrs, _els}) -> 'remote-connection-failed'. encode_stream_error_remote_connection_failed('remote-connection-failed', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"remote-connection-failed">>, _attrs, _els}. decode_stream_error_policy_violation(__TopXMLNS, __IgnoreEls, {xmlel, <<"policy-violation">>, _attrs, _els}) -> 'policy-violation'. encode_stream_error_policy_violation('policy-violation', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"policy-violation">>, _attrs, _els}. decode_stream_error_not_well_formed(__TopXMLNS, __IgnoreEls, {xmlel, <<"not-well-formed">>, _attrs, _els}) -> 'not-well-formed'. encode_stream_error_not_well_formed('not-well-formed', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"not-well-formed">>, _attrs, _els}. decode_stream_error_not_authorized(__TopXMLNS, __IgnoreEls, {xmlel, <<"not-authorized">>, _attrs, _els}) -> 'not-authorized'. encode_stream_error_not_authorized('not-authorized', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"not-authorized">>, _attrs, _els}. decode_stream_error_invalid_xml(__TopXMLNS, __IgnoreEls, {xmlel, <<"invalid-xml">>, _attrs, _els}) -> 'invalid-xml'. encode_stream_error_invalid_xml('invalid-xml', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"invalid-xml">>, _attrs, _els}. decode_stream_error_invalid_namespace(__TopXMLNS, __IgnoreEls, {xmlel, <<"invalid-namespace">>, _attrs, _els}) -> 'invalid-namespace'. encode_stream_error_invalid_namespace('invalid-namespace', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"invalid-namespace">>, _attrs, _els}. decode_stream_error_invalid_id(__TopXMLNS, __IgnoreEls, {xmlel, <<"invalid-id">>, _attrs, _els}) -> 'invalid-id'. encode_stream_error_invalid_id('invalid-id', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"invalid-id">>, _attrs, _els}. decode_stream_error_invalid_from(__TopXMLNS, __IgnoreEls, {xmlel, <<"invalid-from">>, _attrs, _els}) -> 'invalid-from'. encode_stream_error_invalid_from('invalid-from', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"invalid-from">>, _attrs, _els}. decode_stream_error_internal_server_error(__TopXMLNS, __IgnoreEls, {xmlel, <<"internal-server-error">>, _attrs, _els}) -> 'internal-server-error'. encode_stream_error_internal_server_error('internal-server-error', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"internal-server-error">>, _attrs, _els}. decode_stream_error_improper_addressing(__TopXMLNS, __IgnoreEls, {xmlel, <<"improper-addressing">>, _attrs, _els}) -> 'improper-addressing'. encode_stream_error_improper_addressing('improper-addressing', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"improper-addressing">>, _attrs, _els}. decode_stream_error_host_unknown(__TopXMLNS, __IgnoreEls, {xmlel, <<"host-unknown">>, _attrs, _els}) -> 'host-unknown'. encode_stream_error_host_unknown('host-unknown', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"host-unknown">>, _attrs, _els}. decode_stream_error_host_gone(__TopXMLNS, __IgnoreEls, {xmlel, <<"host-gone">>, _attrs, _els}) -> 'host-gone'. encode_stream_error_host_gone('host-gone', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"host-gone">>, _attrs, _els}. decode_stream_error_connection_timeout(__TopXMLNS, __IgnoreEls, {xmlel, <<"connection-timeout">>, _attrs, _els}) -> 'connection-timeout'. encode_stream_error_connection_timeout('connection-timeout', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"connection-timeout">>, _attrs, _els}. decode_stream_error_conflict(__TopXMLNS, __IgnoreEls, {xmlel, <<"conflict">>, _attrs, _els}) -> conflict. encode_stream_error_conflict(conflict, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"conflict">>, _attrs, _els}. decode_stream_error_bad_namespace_prefix(__TopXMLNS, __IgnoreEls, {xmlel, <<"bad-namespace-prefix">>, _attrs, _els}) -> 'bad-namespace-prefix'. encode_stream_error_bad_namespace_prefix('bad-namespace-prefix', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"bad-namespace-prefix">>, _attrs, _els}. decode_stream_error_bad_format(__TopXMLNS, __IgnoreEls, {xmlel, <<"bad-format">>, _attrs, _els}) -> 'bad-format'. encode_stream_error_bad_format('bad-format', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"bad-format">>, _attrs, _els}. decode_stream_error_text(__TopXMLNS, __IgnoreEls, {xmlel, <<"text">>, _attrs, _els}) -> Data = decode_stream_error_text_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Lang = decode_stream_error_text_attrs(__TopXMLNS, _attrs, undefined), {text, Lang, Data}. decode_stream_error_text_els(__TopXMLNS, __IgnoreEls, [], Data) -> decode_stream_error_text_cdata(__TopXMLNS, Data); decode_stream_error_text_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Data) -> decode_stream_error_text_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_stream_error_text_els(__TopXMLNS, __IgnoreEls, [_ | _els], Data) -> decode_stream_error_text_els(__TopXMLNS, __IgnoreEls, _els, Data). decode_stream_error_text_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], _Lang) -> decode_stream_error_text_attrs(__TopXMLNS, _attrs, _val); decode_stream_error_text_attrs(__TopXMLNS, [_ | _attrs], Lang) -> decode_stream_error_text_attrs(__TopXMLNS, _attrs, Lang); decode_stream_error_text_attrs(__TopXMLNS, [], Lang) -> 'decode_stream_error_text_attr_xml:lang'(__TopXMLNS, Lang). encode_stream_error_text({text, Lang, Data}, _xmlns_attrs) -> _els = encode_stream_error_text_cdata(Data, []), _attrs = 'encode_stream_error_text_attr_xml:lang'(Lang, _xmlns_attrs), {xmlel, <<"text">>, _attrs, _els}. 'decode_stream_error_text_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_stream_error_text_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_stream_error_text_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_stream_error_text_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_stream_error_text_cdata(__TopXMLNS, <<>>) -> undefined; decode_stream_error_text_cdata(__TopXMLNS, _val) -> _val. encode_stream_error_text_cdata(undefined, _acc) -> _acc; encode_stream_error_text_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_time(__TopXMLNS, __IgnoreEls, {xmlel, <<"time">>, _attrs, _els}) -> {Utc, Tzo} = decode_time_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), {time, Tzo, Utc}. decode_time_els(__TopXMLNS, __IgnoreEls, [], Utc, Tzo) -> {Utc, Tzo}; decode_time_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"tzo">>, _attrs, _} = _el | _els], Utc, Tzo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc, decode_time_tzo(__TopXMLNS, __IgnoreEls, _el)); true -> decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc, Tzo) end; decode_time_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"utc">>, _attrs, _} = _el | _els], Utc, Tzo) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_time_els(__TopXMLNS, __IgnoreEls, _els, decode_time_utc(__TopXMLNS, __IgnoreEls, _el), Tzo); true -> decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc, Tzo) end; decode_time_els(__TopXMLNS, __IgnoreEls, [_ | _els], Utc, Tzo) -> decode_time_els(__TopXMLNS, __IgnoreEls, _els, Utc, Tzo). encode_time({time, Tzo, Utc}, _xmlns_attrs) -> _els = lists:reverse('encode_time_$utc'(Utc, 'encode_time_$tzo'(Tzo, []))), _attrs = _xmlns_attrs, {xmlel, <<"time">>, _attrs, _els}. 'encode_time_$utc'(undefined, _acc) -> _acc; 'encode_time_$utc'(Utc, _acc) -> [encode_time_utc(Utc, []) | _acc]. 'encode_time_$tzo'(undefined, _acc) -> _acc; 'encode_time_$tzo'(Tzo, _acc) -> [encode_time_tzo(Tzo, []) | _acc]. decode_time_tzo(__TopXMLNS, __IgnoreEls, {xmlel, <<"tzo">>, _attrs, _els}) -> Cdata = decode_time_tzo_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_time_tzo_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_time_tzo_cdata(__TopXMLNS, Cdata); decode_time_tzo_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_time_tzo_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_time_tzo_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_time_tzo_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_time_tzo(Cdata, _xmlns_attrs) -> _els = encode_time_tzo_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"tzo">>, _attrs, _els}. decode_time_tzo_cdata(__TopXMLNS, <<>>) -> undefined; decode_time_tzo_cdata(__TopXMLNS, _val) -> case catch dec_tzo(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"tzo">>, __TopXMLNS}}); _res -> _res end. encode_time_tzo_cdata(undefined, _acc) -> _acc; encode_time_tzo_cdata(_val, _acc) -> [{xmlcdata, enc_tzo(_val)} | _acc]. decode_time_utc(__TopXMLNS, __IgnoreEls, {xmlel, <<"utc">>, _attrs, _els}) -> Cdata = decode_time_utc_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_time_utc_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_time_utc_cdata(__TopXMLNS, Cdata); decode_time_utc_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_time_utc_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_time_utc_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_time_utc_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_time_utc(Cdata, _xmlns_attrs) -> _els = encode_time_utc_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"utc">>, _attrs, _els}. decode_time_utc_cdata(__TopXMLNS, <<>>) -> undefined; decode_time_utc_cdata(__TopXMLNS, _val) -> case catch dec_utc(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"utc">>, __TopXMLNS}}); _res -> _res end. encode_time_utc_cdata(undefined, _acc) -> _acc; encode_time_utc_cdata(_val, _acc) -> [{xmlcdata, enc_utc(_val)} | _acc]. decode_ping(__TopXMLNS, __IgnoreEls, {xmlel, <<"ping">>, _attrs, _els}) -> {ping}. encode_ping({ping}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"ping">>, _attrs, _els}. decode_session(__TopXMLNS, __IgnoreEls, {xmlel, <<"session">>, _attrs, _els}) -> {session}. encode_session({session}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"session">>, _attrs, _els}. decode_register(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> {Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email} = decode_register_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, false, undefined, undefined, undefined, undefined, undefined, false, undefined, undefined, undefined, undefined, undefined), {register, Registered, Remove, Instructions, Username, Nick, Password, Name, First, Last, Email, Address, City, State, Zip, Phone, Url, Date, Misc, Text, Key, Xdata}. decode_register_els(__TopXMLNS, __IgnoreEls, [], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> {Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email}; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"x">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"jabber:x:data">> -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, decode_xdata(_xmlns, __IgnoreEls, _el), Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"registered">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, decode_register_registered(__TopXMLNS, __IgnoreEls, _el), Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"remove">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, decode_register_remove(__TopXMLNS, __IgnoreEls, _el), Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"instructions">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, decode_register_instructions(__TopXMLNS, __IgnoreEls, _el), Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"username">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, decode_register_username(__TopXMLNS, __IgnoreEls, _el), Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"nick">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, decode_register_nick(__TopXMLNS, __IgnoreEls, _el), Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"password">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, decode_register_password(__TopXMLNS, __IgnoreEls, _el), Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"name">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, decode_register_name(__TopXMLNS, __IgnoreEls, _el), Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"first">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, decode_register_first(__TopXMLNS, __IgnoreEls, _el), Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"last">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, decode_register_last(__TopXMLNS, __IgnoreEls, _el), First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"email">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, decode_register_email(__TopXMLNS, __IgnoreEls, _el)); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"address">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, decode_register_address(__TopXMLNS, __IgnoreEls, _el), Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"city">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, decode_register_city(__TopXMLNS, __IgnoreEls, _el), Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"state">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, decode_register_state(__TopXMLNS, __IgnoreEls, _el), Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"zip">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, decode_register_zip(__TopXMLNS, __IgnoreEls, _el), Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"phone">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, decode_register_phone(__TopXMLNS, __IgnoreEls, _el), State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"url">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, decode_register_url(__TopXMLNS, __IgnoreEls, _el), Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"date">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, decode_register_date(__TopXMLNS, __IgnoreEls, _el), Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"misc">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, decode_register_misc(__TopXMLNS, __IgnoreEls, _el), Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"text">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, decode_register_text(__TopXMLNS, __IgnoreEls, _el), Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"key">>, _attrs, _} = _el | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, decode_register_key(__TopXMLNS, __IgnoreEls, _el), City, Nick, Url, Email); true -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) end; decode_register_els(__TopXMLNS, __IgnoreEls, [_ | _els], Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email) -> decode_register_els(__TopXMLNS, __IgnoreEls, _els, Zip, Xdata, Misc, Address, Instructions, Text, Last, First, Password, Registered, Date, Phone, State, Name, Username, Remove, Key, City, Nick, Url, Email). encode_register({register, Registered, Remove, Instructions, Username, Nick, Password, Name, First, Last, Email, Address, City, State, Zip, Phone, Url, Date, Misc, Text, Key, Xdata}, _xmlns_attrs) -> _els = lists:reverse('encode_register_$zip'(Zip, 'encode_register_$xdata'(Xdata, 'encode_register_$misc'(Misc, 'encode_register_$address'(Address, 'encode_register_$instructions'(Instructions, 'encode_register_$text'(Text, 'encode_register_$last'(Last, 'encode_register_$first'(First, 'encode_register_$password'(Password, 'encode_register_$registered'(Registered, 'encode_register_$date'(Date, 'encode_register_$phone'(Phone, 'encode_register_$state'(State, 'encode_register_$name'(Name, 'encode_register_$username'(Username, 'encode_register_$remove'(Remove, 'encode_register_$key'(Key, 'encode_register_$city'(City, 'encode_register_$nick'(Nick, 'encode_register_$url'(Url, 'encode_register_$email'(Email, [])))))))))))))))))))))), _attrs = _xmlns_attrs, {xmlel, <<"query">>, _attrs, _els}. 'encode_register_$zip'(undefined, _acc) -> _acc; 'encode_register_$zip'(Zip, _acc) -> [encode_register_zip(Zip, []) | _acc]. 'encode_register_$xdata'(undefined, _acc) -> _acc; 'encode_register_$xdata'(Xdata, _acc) -> [encode_xdata(Xdata, [{<<"xmlns">>, <<"jabber:x:data">>}]) | _acc]. 'encode_register_$misc'(undefined, _acc) -> _acc; 'encode_register_$misc'(Misc, _acc) -> [encode_register_misc(Misc, []) | _acc]. 'encode_register_$address'(undefined, _acc) -> _acc; 'encode_register_$address'(Address, _acc) -> [encode_register_address(Address, []) | _acc]. 'encode_register_$instructions'(undefined, _acc) -> _acc; 'encode_register_$instructions'(Instructions, _acc) -> [encode_register_instructions(Instructions, []) | _acc]. 'encode_register_$text'(undefined, _acc) -> _acc; 'encode_register_$text'(Text, _acc) -> [encode_register_text(Text, []) | _acc]. 'encode_register_$last'(undefined, _acc) -> _acc; 'encode_register_$last'(Last, _acc) -> [encode_register_last(Last, []) | _acc]. 'encode_register_$first'(undefined, _acc) -> _acc; 'encode_register_$first'(First, _acc) -> [encode_register_first(First, []) | _acc]. 'encode_register_$password'(undefined, _acc) -> _acc; 'encode_register_$password'(Password, _acc) -> [encode_register_password(Password, []) | _acc]. 'encode_register_$registered'(false, _acc) -> _acc; 'encode_register_$registered'(Registered, _acc) -> [encode_register_registered(Registered, []) | _acc]. 'encode_register_$date'(undefined, _acc) -> _acc; 'encode_register_$date'(Date, _acc) -> [encode_register_date(Date, []) | _acc]. 'encode_register_$phone'(undefined, _acc) -> _acc; 'encode_register_$phone'(Phone, _acc) -> [encode_register_phone(Phone, []) | _acc]. 'encode_register_$state'(undefined, _acc) -> _acc; 'encode_register_$state'(State, _acc) -> [encode_register_state(State, []) | _acc]. 'encode_register_$name'(undefined, _acc) -> _acc; 'encode_register_$name'(Name, _acc) -> [encode_register_name(Name, []) | _acc]. 'encode_register_$username'(undefined, _acc) -> _acc; 'encode_register_$username'(Username, _acc) -> [encode_register_username(Username, []) | _acc]. 'encode_register_$remove'(false, _acc) -> _acc; 'encode_register_$remove'(Remove, _acc) -> [encode_register_remove(Remove, []) | _acc]. 'encode_register_$key'(undefined, _acc) -> _acc; 'encode_register_$key'(Key, _acc) -> [encode_register_key(Key, []) | _acc]. 'encode_register_$city'(undefined, _acc) -> _acc; 'encode_register_$city'(City, _acc) -> [encode_register_city(City, []) | _acc]. 'encode_register_$nick'(undefined, _acc) -> _acc; 'encode_register_$nick'(Nick, _acc) -> [encode_register_nick(Nick, []) | _acc]. 'encode_register_$url'(undefined, _acc) -> _acc; 'encode_register_$url'(Url, _acc) -> [encode_register_url(Url, []) | _acc]. 'encode_register_$email'(undefined, _acc) -> _acc; 'encode_register_$email'(Email, _acc) -> [encode_register_email(Email, []) | _acc]. decode_register_key(__TopXMLNS, __IgnoreEls, {xmlel, <<"key">>, _attrs, _els}) -> Cdata = decode_register_key_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_key_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_key_cdata(__TopXMLNS, Cdata); decode_register_key_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_key_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_key_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_key_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_key(Cdata, _xmlns_attrs) -> _els = encode_register_key_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"key">>, _attrs, _els}. decode_register_key_cdata(__TopXMLNS, <<>>) -> none; decode_register_key_cdata(__TopXMLNS, _val) -> _val. encode_register_key_cdata(none, _acc) -> _acc; encode_register_key_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_text(__TopXMLNS, __IgnoreEls, {xmlel, <<"text">>, _attrs, _els}) -> Cdata = decode_register_text_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_text_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_text_cdata(__TopXMLNS, Cdata); decode_register_text_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_text_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_text_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_text_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_text(Cdata, _xmlns_attrs) -> _els = encode_register_text_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"text">>, _attrs, _els}. decode_register_text_cdata(__TopXMLNS, <<>>) -> none; decode_register_text_cdata(__TopXMLNS, _val) -> _val. encode_register_text_cdata(none, _acc) -> _acc; encode_register_text_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_misc(__TopXMLNS, __IgnoreEls, {xmlel, <<"misc">>, _attrs, _els}) -> Cdata = decode_register_misc_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_misc_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_misc_cdata(__TopXMLNS, Cdata); decode_register_misc_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_misc_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_misc_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_misc_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_misc(Cdata, _xmlns_attrs) -> _els = encode_register_misc_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"misc">>, _attrs, _els}. decode_register_misc_cdata(__TopXMLNS, <<>>) -> none; decode_register_misc_cdata(__TopXMLNS, _val) -> _val. encode_register_misc_cdata(none, _acc) -> _acc; encode_register_misc_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_date(__TopXMLNS, __IgnoreEls, {xmlel, <<"date">>, _attrs, _els}) -> Cdata = decode_register_date_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_date_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_date_cdata(__TopXMLNS, Cdata); decode_register_date_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_date_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_date_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_date_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_date(Cdata, _xmlns_attrs) -> _els = encode_register_date_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"date">>, _attrs, _els}. decode_register_date_cdata(__TopXMLNS, <<>>) -> none; decode_register_date_cdata(__TopXMLNS, _val) -> _val. encode_register_date_cdata(none, _acc) -> _acc; encode_register_date_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_url(__TopXMLNS, __IgnoreEls, {xmlel, <<"url">>, _attrs, _els}) -> Cdata = decode_register_url_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_url_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_url_cdata(__TopXMLNS, Cdata); decode_register_url_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_url_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_url_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_url_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_url(Cdata, _xmlns_attrs) -> _els = encode_register_url_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"url">>, _attrs, _els}. decode_register_url_cdata(__TopXMLNS, <<>>) -> none; decode_register_url_cdata(__TopXMLNS, _val) -> _val. encode_register_url_cdata(none, _acc) -> _acc; encode_register_url_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_phone(__TopXMLNS, __IgnoreEls, {xmlel, <<"phone">>, _attrs, _els}) -> Cdata = decode_register_phone_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_phone_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_phone_cdata(__TopXMLNS, Cdata); decode_register_phone_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_phone_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_phone_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_phone_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_phone(Cdata, _xmlns_attrs) -> _els = encode_register_phone_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"phone">>, _attrs, _els}. decode_register_phone_cdata(__TopXMLNS, <<>>) -> none; decode_register_phone_cdata(__TopXMLNS, _val) -> _val. encode_register_phone_cdata(none, _acc) -> _acc; encode_register_phone_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_zip(__TopXMLNS, __IgnoreEls, {xmlel, <<"zip">>, _attrs, _els}) -> Cdata = decode_register_zip_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_zip_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_zip_cdata(__TopXMLNS, Cdata); decode_register_zip_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_zip_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_zip_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_zip_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_zip(Cdata, _xmlns_attrs) -> _els = encode_register_zip_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"zip">>, _attrs, _els}. decode_register_zip_cdata(__TopXMLNS, <<>>) -> none; decode_register_zip_cdata(__TopXMLNS, _val) -> _val. encode_register_zip_cdata(none, _acc) -> _acc; encode_register_zip_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_state(__TopXMLNS, __IgnoreEls, {xmlel, <<"state">>, _attrs, _els}) -> Cdata = decode_register_state_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_state_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_state_cdata(__TopXMLNS, Cdata); decode_register_state_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_state_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_state_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_state_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_state(Cdata, _xmlns_attrs) -> _els = encode_register_state_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"state">>, _attrs, _els}. decode_register_state_cdata(__TopXMLNS, <<>>) -> none; decode_register_state_cdata(__TopXMLNS, _val) -> _val. encode_register_state_cdata(none, _acc) -> _acc; encode_register_state_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_city(__TopXMLNS, __IgnoreEls, {xmlel, <<"city">>, _attrs, _els}) -> Cdata = decode_register_city_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_city_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_city_cdata(__TopXMLNS, Cdata); decode_register_city_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_city_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_city_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_city_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_city(Cdata, _xmlns_attrs) -> _els = encode_register_city_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"city">>, _attrs, _els}. decode_register_city_cdata(__TopXMLNS, <<>>) -> none; decode_register_city_cdata(__TopXMLNS, _val) -> _val. encode_register_city_cdata(none, _acc) -> _acc; encode_register_city_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_address(__TopXMLNS, __IgnoreEls, {xmlel, <<"address">>, _attrs, _els}) -> Cdata = decode_register_address_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_address_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_address_cdata(__TopXMLNS, Cdata); decode_register_address_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_address_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_address_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_address_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_address(Cdata, _xmlns_attrs) -> _els = encode_register_address_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"address">>, _attrs, _els}. decode_register_address_cdata(__TopXMLNS, <<>>) -> none; decode_register_address_cdata(__TopXMLNS, _val) -> _val. encode_register_address_cdata(none, _acc) -> _acc; encode_register_address_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_email(__TopXMLNS, __IgnoreEls, {xmlel, <<"email">>, _attrs, _els}) -> Cdata = decode_register_email_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_email_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_email_cdata(__TopXMLNS, Cdata); decode_register_email_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_email_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_email_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_email_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_email(Cdata, _xmlns_attrs) -> _els = encode_register_email_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"email">>, _attrs, _els}. decode_register_email_cdata(__TopXMLNS, <<>>) -> none; decode_register_email_cdata(__TopXMLNS, _val) -> _val. encode_register_email_cdata(none, _acc) -> _acc; encode_register_email_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_last(__TopXMLNS, __IgnoreEls, {xmlel, <<"last">>, _attrs, _els}) -> Cdata = decode_register_last_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_last_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_last_cdata(__TopXMLNS, Cdata); decode_register_last_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_last_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_last_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_last_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_last(Cdata, _xmlns_attrs) -> _els = encode_register_last_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"last">>, _attrs, _els}. decode_register_last_cdata(__TopXMLNS, <<>>) -> none; decode_register_last_cdata(__TopXMLNS, _val) -> _val. encode_register_last_cdata(none, _acc) -> _acc; encode_register_last_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_first(__TopXMLNS, __IgnoreEls, {xmlel, <<"first">>, _attrs, _els}) -> Cdata = decode_register_first_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_first_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_first_cdata(__TopXMLNS, Cdata); decode_register_first_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_first_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_first_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_first_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_first(Cdata, _xmlns_attrs) -> _els = encode_register_first_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"first">>, _attrs, _els}. decode_register_first_cdata(__TopXMLNS, <<>>) -> none; decode_register_first_cdata(__TopXMLNS, _val) -> _val. encode_register_first_cdata(none, _acc) -> _acc; encode_register_first_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_name(__TopXMLNS, __IgnoreEls, {xmlel, <<"name">>, _attrs, _els}) -> Cdata = decode_register_name_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_name_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_name_cdata(__TopXMLNS, Cdata); decode_register_name_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_name_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_name_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_name_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_name(Cdata, _xmlns_attrs) -> _els = encode_register_name_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"name">>, _attrs, _els}. decode_register_name_cdata(__TopXMLNS, <<>>) -> none; decode_register_name_cdata(__TopXMLNS, _val) -> _val. encode_register_name_cdata(none, _acc) -> _acc; encode_register_name_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_password(__TopXMLNS, __IgnoreEls, {xmlel, <<"password">>, _attrs, _els}) -> Cdata = decode_register_password_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_password_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_password_cdata(__TopXMLNS, Cdata); decode_register_password_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_password_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_password_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_password_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_password(Cdata, _xmlns_attrs) -> _els = encode_register_password_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"password">>, _attrs, _els}. decode_register_password_cdata(__TopXMLNS, <<>>) -> none; decode_register_password_cdata(__TopXMLNS, _val) -> _val. encode_register_password_cdata(none, _acc) -> _acc; encode_register_password_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_nick(__TopXMLNS, __IgnoreEls, {xmlel, <<"nick">>, _attrs, _els}) -> Cdata = decode_register_nick_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_nick_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_nick_cdata(__TopXMLNS, Cdata); decode_register_nick_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_nick_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_nick_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_nick_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_nick(Cdata, _xmlns_attrs) -> _els = encode_register_nick_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"nick">>, _attrs, _els}. decode_register_nick_cdata(__TopXMLNS, <<>>) -> none; decode_register_nick_cdata(__TopXMLNS, _val) -> _val. encode_register_nick_cdata(none, _acc) -> _acc; encode_register_nick_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_username(__TopXMLNS, __IgnoreEls, {xmlel, <<"username">>, _attrs, _els}) -> Cdata = decode_register_username_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_username_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_username_cdata(__TopXMLNS, Cdata); decode_register_username_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_username_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_username_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_username_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_username(Cdata, _xmlns_attrs) -> _els = encode_register_username_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"username">>, _attrs, _els}. decode_register_username_cdata(__TopXMLNS, <<>>) -> none; decode_register_username_cdata(__TopXMLNS, _val) -> _val. encode_register_username_cdata(none, _acc) -> _acc; encode_register_username_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_instructions(__TopXMLNS, __IgnoreEls, {xmlel, <<"instructions">>, _attrs, _els}) -> Cdata = decode_register_instructions_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_register_instructions_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_register_instructions_cdata(__TopXMLNS, Cdata); decode_register_instructions_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_register_instructions_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_register_instructions_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_register_instructions_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_register_instructions(Cdata, _xmlns_attrs) -> _els = encode_register_instructions_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"instructions">>, _attrs, _els}. decode_register_instructions_cdata(__TopXMLNS, <<>>) -> undefined; decode_register_instructions_cdata(__TopXMLNS, _val) -> _val. encode_register_instructions_cdata(undefined, _acc) -> _acc; encode_register_instructions_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_register_remove(__TopXMLNS, __IgnoreEls, {xmlel, <<"remove">>, _attrs, _els}) -> true. encode_register_remove(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"remove">>, _attrs, _els}. decode_register_registered(__TopXMLNS, __IgnoreEls, {xmlel, <<"registered">>, _attrs, _els}) -> true. encode_register_registered(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"registered">>, _attrs, _els}. decode_feature_register(__TopXMLNS, __IgnoreEls, {xmlel, <<"register">>, _attrs, _els}) -> {feature_register}. encode_feature_register({feature_register}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"register">>, _attrs, _els}. decode_caps(__TopXMLNS, __IgnoreEls, {xmlel, <<"c">>, _attrs, _els}) -> {Hash, Node, Ver} = decode_caps_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {caps, Hash, Node, Ver}. decode_caps_attrs(__TopXMLNS, [{<<"hash">>, _val} | _attrs], _Hash, Node, Ver) -> decode_caps_attrs(__TopXMLNS, _attrs, _val, Node, Ver); decode_caps_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], Hash, _Node, Ver) -> decode_caps_attrs(__TopXMLNS, _attrs, Hash, _val, Ver); decode_caps_attrs(__TopXMLNS, [{<<"ver">>, _val} | _attrs], Hash, Node, _Ver) -> decode_caps_attrs(__TopXMLNS, _attrs, Hash, Node, _val); decode_caps_attrs(__TopXMLNS, [_ | _attrs], Hash, Node, Ver) -> decode_caps_attrs(__TopXMLNS, _attrs, Hash, Node, Ver); decode_caps_attrs(__TopXMLNS, [], Hash, Node, Ver) -> {decode_caps_attr_hash(__TopXMLNS, Hash), decode_caps_attr_node(__TopXMLNS, Node), decode_caps_attr_ver(__TopXMLNS, Ver)}. encode_caps({caps, Hash, Node, Ver}, _xmlns_attrs) -> _els = [], _attrs = encode_caps_attr_ver(Ver, encode_caps_attr_node(Node, encode_caps_attr_hash(Hash, _xmlns_attrs))), {xmlel, <<"c">>, _attrs, _els}. decode_caps_attr_hash(__TopXMLNS, undefined) -> undefined; decode_caps_attr_hash(__TopXMLNS, _val) -> _val. encode_caps_attr_hash(undefined, _acc) -> _acc; encode_caps_attr_hash(_val, _acc) -> [{<<"hash">>, _val} | _acc]. decode_caps_attr_node(__TopXMLNS, undefined) -> undefined; decode_caps_attr_node(__TopXMLNS, _val) -> _val. encode_caps_attr_node(undefined, _acc) -> _acc; encode_caps_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_caps_attr_ver(__TopXMLNS, undefined) -> undefined; decode_caps_attr_ver(__TopXMLNS, _val) -> case catch base64:decode(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"ver">>, <<"c">>, __TopXMLNS}}); _res -> _res end. encode_caps_attr_ver(undefined, _acc) -> _acc; encode_caps_attr_ver(_val, _acc) -> [{<<"ver">>, base64:encode(_val)} | _acc]. decode_p1_ack(__TopXMLNS, __IgnoreEls, {xmlel, <<"ack">>, _attrs, _els}) -> {p1_ack}. encode_p1_ack({p1_ack}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"ack">>, _attrs, _els}. decode_p1_rebind(__TopXMLNS, __IgnoreEls, {xmlel, <<"rebind">>, _attrs, _els}) -> {p1_rebind}. encode_p1_rebind({p1_rebind}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"rebind">>, _attrs, _els}. decode_p1_push(__TopXMLNS, __IgnoreEls, {xmlel, <<"push">>, _attrs, _els}) -> {p1_push}. encode_p1_push({p1_push}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"push">>, _attrs, _els}. decode_stream_features(__TopXMLNS, __IgnoreEls, {xmlel, <<"stream:features">>, _attrs, _els}) -> __Els = decode_stream_features_els(__TopXMLNS, __IgnoreEls, _els, []), {stream_features, __Els}. decode_stream_features_els(__TopXMLNS, __IgnoreEls, [], __Els) -> lists:reverse(__Els); decode_stream_features_els(__TopXMLNS, __IgnoreEls, [{xmlel, _, _, _} = _el | _els], __Els) -> if __IgnoreEls -> decode_stream_features_els(__TopXMLNS, __IgnoreEls, _els, [_el | __Els]); true -> case is_known_tag(_el) of true -> decode_stream_features_els(__TopXMLNS, __IgnoreEls, _els, [decode(_el) | __Els]); false -> decode_stream_features_els(__TopXMLNS, __IgnoreEls, _els, __Els) end end; decode_stream_features_els(__TopXMLNS, __IgnoreEls, [_ | _els], __Els) -> decode_stream_features_els(__TopXMLNS, __IgnoreEls, _els, __Els). encode_stream_features({stream_features, __Els}, _xmlns_attrs) -> _els = [encode(_el) || _el <- __Els], _attrs = _xmlns_attrs, {xmlel, <<"stream:features">>, _attrs, _els}. decode_compression(__TopXMLNS, __IgnoreEls, {xmlel, <<"compression">>, _attrs, _els}) -> Methods = decode_compression_els(__TopXMLNS, __IgnoreEls, _els, []), {compression, Methods}. decode_compression_els(__TopXMLNS, __IgnoreEls, [], Methods) -> lists:reverse(Methods); decode_compression_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"method">>, _attrs, _} = _el | _els], Methods) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_compression_els(__TopXMLNS, __IgnoreEls, _els, case decode_compression_method(__TopXMLNS, __IgnoreEls, _el) of undefined -> Methods; _new_el -> [_new_el | Methods] end); true -> decode_compression_els(__TopXMLNS, __IgnoreEls, _els, Methods) end; decode_compression_els(__TopXMLNS, __IgnoreEls, [_ | _els], Methods) -> decode_compression_els(__TopXMLNS, __IgnoreEls, _els, Methods). encode_compression({compression, Methods}, _xmlns_attrs) -> _els = lists:reverse('encode_compression_$methods'(Methods, [])), _attrs = _xmlns_attrs, {xmlel, <<"compression">>, _attrs, _els}. 'encode_compression_$methods'([], _acc) -> _acc; 'encode_compression_$methods'([Methods | _els], _acc) -> 'encode_compression_$methods'(_els, [encode_compression_method(Methods, []) | _acc]). decode_compression_method(__TopXMLNS, __IgnoreEls, {xmlel, <<"method">>, _attrs, _els}) -> Cdata = decode_compression_method_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_compression_method_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_compression_method_cdata(__TopXMLNS, Cdata); decode_compression_method_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_compression_method_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_compression_method_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_compression_method_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_compression_method(Cdata, _xmlns_attrs) -> _els = encode_compression_method_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"method">>, _attrs, _els}. decode_compression_method_cdata(__TopXMLNS, <<>>) -> undefined; decode_compression_method_cdata(__TopXMLNS, _val) -> _val. encode_compression_method_cdata(undefined, _acc) -> _acc; encode_compression_method_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_compressed(__TopXMLNS, __IgnoreEls, {xmlel, <<"compressed">>, _attrs, _els}) -> {compressed}. encode_compressed({compressed}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"compressed">>, _attrs, _els}. decode_compress(__TopXMLNS, __IgnoreEls, {xmlel, <<"compress">>, _attrs, _els}) -> Methods = decode_compress_els(__TopXMLNS, __IgnoreEls, _els, []), {compress, Methods}. decode_compress_els(__TopXMLNS, __IgnoreEls, [], Methods) -> lists:reverse(Methods); decode_compress_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"method">>, _attrs, _} = _el | _els], Methods) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_compress_els(__TopXMLNS, __IgnoreEls, _els, case decode_compress_method(__TopXMLNS, __IgnoreEls, _el) of undefined -> Methods; _new_el -> [_new_el | Methods] end); true -> decode_compress_els(__TopXMLNS, __IgnoreEls, _els, Methods) end; decode_compress_els(__TopXMLNS, __IgnoreEls, [_ | _els], Methods) -> decode_compress_els(__TopXMLNS, __IgnoreEls, _els, Methods). encode_compress({compress, Methods}, _xmlns_attrs) -> _els = lists:reverse('encode_compress_$methods'(Methods, [])), _attrs = _xmlns_attrs, {xmlel, <<"compress">>, _attrs, _els}. 'encode_compress_$methods'([], _acc) -> _acc; 'encode_compress_$methods'([Methods | _els], _acc) -> 'encode_compress_$methods'(_els, [encode_compress_method(Methods, []) | _acc]). decode_compress_method(__TopXMLNS, __IgnoreEls, {xmlel, <<"method">>, _attrs, _els}) -> Cdata = decode_compress_method_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_compress_method_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_compress_method_cdata(__TopXMLNS, Cdata); decode_compress_method_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_compress_method_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_compress_method_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_compress_method_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_compress_method(Cdata, _xmlns_attrs) -> _els = encode_compress_method_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"method">>, _attrs, _els}. decode_compress_method_cdata(__TopXMLNS, <<>>) -> undefined; decode_compress_method_cdata(__TopXMLNS, _val) -> _val. encode_compress_method_cdata(undefined, _acc) -> _acc; encode_compress_method_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_compress_failure(__TopXMLNS, __IgnoreEls, {xmlel, <<"failure">>, _attrs, _els}) -> Reason = decode_compress_failure_els(__TopXMLNS, __IgnoreEls, _els, undefined), {compress_failure, Reason}. decode_compress_failure_els(__TopXMLNS, __IgnoreEls, [], Reason) -> Reason; decode_compress_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"setup-failed">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_compress_failure_els(__TopXMLNS, __IgnoreEls, _els, decode_compress_failure_setup_failed(__TopXMLNS, __IgnoreEls, _el)); true -> decode_compress_failure_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_compress_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"processing-failed">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_compress_failure_els(__TopXMLNS, __IgnoreEls, _els, decode_compress_failure_processing_failed(__TopXMLNS, __IgnoreEls, _el)); true -> decode_compress_failure_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_compress_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"unsupported-method">>, _attrs, _} = _el | _els], Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_compress_failure_els(__TopXMLNS, __IgnoreEls, _els, decode_compress_failure_unsupported_method(__TopXMLNS, __IgnoreEls, _el)); true -> decode_compress_failure_els(__TopXMLNS, __IgnoreEls, _els, Reason) end; decode_compress_failure_els(__TopXMLNS, __IgnoreEls, [_ | _els], Reason) -> decode_compress_failure_els(__TopXMLNS, __IgnoreEls, _els, Reason). encode_compress_failure({compress_failure, Reason}, _xmlns_attrs) -> _els = lists:reverse('encode_compress_failure_$reason'(Reason, [])), _attrs = _xmlns_attrs, {xmlel, <<"failure">>, _attrs, _els}. 'encode_compress_failure_$reason'(undefined, _acc) -> _acc; 'encode_compress_failure_$reason'('setup-failed' = Reason, _acc) -> [encode_compress_failure_setup_failed(Reason, []) | _acc]; 'encode_compress_failure_$reason'('processing-failed' = Reason, _acc) -> [encode_compress_failure_processing_failed(Reason, []) | _acc]; 'encode_compress_failure_$reason'('unsupported-method' = Reason, _acc) -> [encode_compress_failure_unsupported_method(Reason, []) | _acc]. decode_compress_failure_unsupported_method(__TopXMLNS, __IgnoreEls, {xmlel, <<"unsupported-method">>, _attrs, _els}) -> 'unsupported-method'. encode_compress_failure_unsupported_method('unsupported-method', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"unsupported-method">>, _attrs, _els}. decode_compress_failure_processing_failed(__TopXMLNS, __IgnoreEls, {xmlel, <<"processing-failed">>, _attrs, _els}) -> 'processing-failed'. encode_compress_failure_processing_failed('processing-failed', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"processing-failed">>, _attrs, _els}. decode_compress_failure_setup_failed(__TopXMLNS, __IgnoreEls, {xmlel, <<"setup-failed">>, _attrs, _els}) -> 'setup-failed'. encode_compress_failure_setup_failed('setup-failed', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"setup-failed">>, _attrs, _els}. decode_starttls_failure(__TopXMLNS, __IgnoreEls, {xmlel, <<"failure">>, _attrs, _els}) -> {starttls_failure}. encode_starttls_failure({starttls_failure}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"failure">>, _attrs, _els}. decode_starttls_proceed(__TopXMLNS, __IgnoreEls, {xmlel, <<"proceed">>, _attrs, _els}) -> {starttls_proceed}. encode_starttls_proceed({starttls_proceed}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"proceed">>, _attrs, _els}. decode_starttls(__TopXMLNS, __IgnoreEls, {xmlel, <<"starttls">>, _attrs, _els}) -> Required = decode_starttls_els(__TopXMLNS, __IgnoreEls, _els, false), {starttls, Required}. decode_starttls_els(__TopXMLNS, __IgnoreEls, [], Required) -> Required; decode_starttls_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"required">>, _attrs, _} = _el | _els], Required) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_starttls_els(__TopXMLNS, __IgnoreEls, _els, decode_starttls_required(__TopXMLNS, __IgnoreEls, _el)); true -> decode_starttls_els(__TopXMLNS, __IgnoreEls, _els, Required) end; decode_starttls_els(__TopXMLNS, __IgnoreEls, [_ | _els], Required) -> decode_starttls_els(__TopXMLNS, __IgnoreEls, _els, Required). encode_starttls({starttls, Required}, _xmlns_attrs) -> _els = lists:reverse('encode_starttls_$required'(Required, [])), _attrs = _xmlns_attrs, {xmlel, <<"starttls">>, _attrs, _els}. 'encode_starttls_$required'(false, _acc) -> _acc; 'encode_starttls_$required'(Required, _acc) -> [encode_starttls_required(Required, []) | _acc]. decode_starttls_required(__TopXMLNS, __IgnoreEls, {xmlel, <<"required">>, _attrs, _els}) -> true. encode_starttls_required(true, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"required">>, _attrs, _els}. decode_sasl_mechanisms(__TopXMLNS, __IgnoreEls, {xmlel, <<"mechanisms">>, _attrs, _els}) -> List = decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls, _els, []), {sasl_mechanisms, List}. decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls, [], List) -> lists:reverse(List); decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"mechanism">>, _attrs, _} = _el | _els], List) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls, _els, case decode_sasl_mechanism(__TopXMLNS, __IgnoreEls, _el) of undefined -> List; _new_el -> [_new_el | List] end); true -> decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls, _els, List) end; decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls, [_ | _els], List) -> decode_sasl_mechanisms_els(__TopXMLNS, __IgnoreEls, _els, List). encode_sasl_mechanisms({sasl_mechanisms, List}, _xmlns_attrs) -> _els = lists:reverse('encode_sasl_mechanisms_$list'(List, [])), _attrs = _xmlns_attrs, {xmlel, <<"mechanisms">>, _attrs, _els}. 'encode_sasl_mechanisms_$list'([], _acc) -> _acc; 'encode_sasl_mechanisms_$list'([List | _els], _acc) -> 'encode_sasl_mechanisms_$list'(_els, [encode_sasl_mechanism(List, []) | _acc]). decode_sasl_mechanism(__TopXMLNS, __IgnoreEls, {xmlel, <<"mechanism">>, _attrs, _els}) -> Cdata = decode_sasl_mechanism_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_sasl_mechanism_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_sasl_mechanism_cdata(__TopXMLNS, Cdata); decode_sasl_mechanism_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_sasl_mechanism_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_sasl_mechanism_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_sasl_mechanism_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_sasl_mechanism(Cdata, _xmlns_attrs) -> _els = encode_sasl_mechanism_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"mechanism">>, _attrs, _els}. decode_sasl_mechanism_cdata(__TopXMLNS, <<>>) -> undefined; decode_sasl_mechanism_cdata(__TopXMLNS, _val) -> _val. encode_sasl_mechanism_cdata(undefined, _acc) -> _acc; encode_sasl_mechanism_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_sasl_failure(__TopXMLNS, __IgnoreEls, {xmlel, <<"failure">>, _attrs, _els}) -> {Text, Reason} = decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, [], undefined), {sasl_failure, Reason, Text}. decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [], Text, Reason) -> {lists:reverse(Text), Reason}; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"text">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, [decode_sasl_failure_text(__TopXMLNS, __IgnoreEls, _el) | Text], Reason); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"aborted">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_aborted(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"account-disabled">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_account_disabled(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"credentials-expired">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_credentials_expired(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"encryption-required">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_encryption_required(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"incorrect-encoding">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_incorrect_encoding(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"invalid-authzid">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_invalid_authzid(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"invalid-mechanism">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_invalid_mechanism(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"malformed-request">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_malformed_request(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"mechanism-too-weak">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_mechanism_too_weak(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-authorized">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_not_authorized(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"temporary-auth-failure">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_sasl_failure_temporary_auth_failure(__TopXMLNS, __IgnoreEls, _el)); true -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, [_ | _els], Text, Reason) -> decode_sasl_failure_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason). encode_sasl_failure({sasl_failure, Reason, Text}, _xmlns_attrs) -> _els = lists:reverse('encode_sasl_failure_$text'(Text, 'encode_sasl_failure_$reason'(Reason, []))), _attrs = _xmlns_attrs, {xmlel, <<"failure">>, _attrs, _els}. 'encode_sasl_failure_$text'([], _acc) -> _acc; 'encode_sasl_failure_$text'([Text | _els], _acc) -> 'encode_sasl_failure_$text'(_els, [encode_sasl_failure_text(Text, []) | _acc]). 'encode_sasl_failure_$reason'(undefined, _acc) -> _acc; 'encode_sasl_failure_$reason'(aborted = Reason, _acc) -> [encode_sasl_failure_aborted(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('account-disabled' = Reason, _acc) -> [encode_sasl_failure_account_disabled(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('credentials-expired' = Reason, _acc) -> [encode_sasl_failure_credentials_expired(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('encryption-required' = Reason, _acc) -> [encode_sasl_failure_encryption_required(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('incorrect-encoding' = Reason, _acc) -> [encode_sasl_failure_incorrect_encoding(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('invalid-authzid' = Reason, _acc) -> [encode_sasl_failure_invalid_authzid(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('invalid-mechanism' = Reason, _acc) -> [encode_sasl_failure_invalid_mechanism(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('malformed-request' = Reason, _acc) -> [encode_sasl_failure_malformed_request(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('mechanism-too-weak' = Reason, _acc) -> [encode_sasl_failure_mechanism_too_weak(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('not-authorized' = Reason, _acc) -> [encode_sasl_failure_not_authorized(Reason, []) | _acc]; 'encode_sasl_failure_$reason'('temporary-auth-failure' = Reason, _acc) -> [encode_sasl_failure_temporary_auth_failure(Reason, []) | _acc]. decode_sasl_failure_temporary_auth_failure(__TopXMLNS, __IgnoreEls, {xmlel, <<"temporary-auth-failure">>, _attrs, _els}) -> 'temporary-auth-failure'. encode_sasl_failure_temporary_auth_failure('temporary-auth-failure', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"temporary-auth-failure">>, _attrs, _els}. decode_sasl_failure_not_authorized(__TopXMLNS, __IgnoreEls, {xmlel, <<"not-authorized">>, _attrs, _els}) -> 'not-authorized'. encode_sasl_failure_not_authorized('not-authorized', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"not-authorized">>, _attrs, _els}. decode_sasl_failure_mechanism_too_weak(__TopXMLNS, __IgnoreEls, {xmlel, <<"mechanism-too-weak">>, _attrs, _els}) -> 'mechanism-too-weak'. encode_sasl_failure_mechanism_too_weak('mechanism-too-weak', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"mechanism-too-weak">>, _attrs, _els}. decode_sasl_failure_malformed_request(__TopXMLNS, __IgnoreEls, {xmlel, <<"malformed-request">>, _attrs, _els}) -> 'malformed-request'. encode_sasl_failure_malformed_request('malformed-request', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"malformed-request">>, _attrs, _els}. decode_sasl_failure_invalid_mechanism(__TopXMLNS, __IgnoreEls, {xmlel, <<"invalid-mechanism">>, _attrs, _els}) -> 'invalid-mechanism'. encode_sasl_failure_invalid_mechanism('invalid-mechanism', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"invalid-mechanism">>, _attrs, _els}. decode_sasl_failure_invalid_authzid(__TopXMLNS, __IgnoreEls, {xmlel, <<"invalid-authzid">>, _attrs, _els}) -> 'invalid-authzid'. encode_sasl_failure_invalid_authzid('invalid-authzid', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"invalid-authzid">>, _attrs, _els}. decode_sasl_failure_incorrect_encoding(__TopXMLNS, __IgnoreEls, {xmlel, <<"incorrect-encoding">>, _attrs, _els}) -> 'incorrect-encoding'. encode_sasl_failure_incorrect_encoding('incorrect-encoding', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"incorrect-encoding">>, _attrs, _els}. decode_sasl_failure_encryption_required(__TopXMLNS, __IgnoreEls, {xmlel, <<"encryption-required">>, _attrs, _els}) -> 'encryption-required'. encode_sasl_failure_encryption_required('encryption-required', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"encryption-required">>, _attrs, _els}. decode_sasl_failure_credentials_expired(__TopXMLNS, __IgnoreEls, {xmlel, <<"credentials-expired">>, _attrs, _els}) -> 'credentials-expired'. encode_sasl_failure_credentials_expired('credentials-expired', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"credentials-expired">>, _attrs, _els}. decode_sasl_failure_account_disabled(__TopXMLNS, __IgnoreEls, {xmlel, <<"account-disabled">>, _attrs, _els}) -> 'account-disabled'. encode_sasl_failure_account_disabled('account-disabled', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"account-disabled">>, _attrs, _els}. decode_sasl_failure_aborted(__TopXMLNS, __IgnoreEls, {xmlel, <<"aborted">>, _attrs, _els}) -> aborted. encode_sasl_failure_aborted(aborted, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"aborted">>, _attrs, _els}. decode_sasl_failure_text(__TopXMLNS, __IgnoreEls, {xmlel, <<"text">>, _attrs, _els}) -> Data = decode_sasl_failure_text_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Lang = decode_sasl_failure_text_attrs(__TopXMLNS, _attrs, undefined), {text, Lang, Data}. decode_sasl_failure_text_els(__TopXMLNS, __IgnoreEls, [], Data) -> decode_sasl_failure_text_cdata(__TopXMLNS, Data); decode_sasl_failure_text_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Data) -> decode_sasl_failure_text_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_sasl_failure_text_els(__TopXMLNS, __IgnoreEls, [_ | _els], Data) -> decode_sasl_failure_text_els(__TopXMLNS, __IgnoreEls, _els, Data). decode_sasl_failure_text_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], _Lang) -> decode_sasl_failure_text_attrs(__TopXMLNS, _attrs, _val); decode_sasl_failure_text_attrs(__TopXMLNS, [_ | _attrs], Lang) -> decode_sasl_failure_text_attrs(__TopXMLNS, _attrs, Lang); decode_sasl_failure_text_attrs(__TopXMLNS, [], Lang) -> 'decode_sasl_failure_text_attr_xml:lang'(__TopXMLNS, Lang). encode_sasl_failure_text({text, Lang, Data}, _xmlns_attrs) -> _els = encode_sasl_failure_text_cdata(Data, []), _attrs = 'encode_sasl_failure_text_attr_xml:lang'(Lang, _xmlns_attrs), {xmlel, <<"text">>, _attrs, _els}. 'decode_sasl_failure_text_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_sasl_failure_text_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_sasl_failure_text_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_sasl_failure_text_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_sasl_failure_text_cdata(__TopXMLNS, <<>>) -> undefined; decode_sasl_failure_text_cdata(__TopXMLNS, _val) -> _val. encode_sasl_failure_text_cdata(undefined, _acc) -> _acc; encode_sasl_failure_text_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_sasl_success(__TopXMLNS, __IgnoreEls, {xmlel, <<"success">>, _attrs, _els}) -> Text = decode_sasl_success_els(__TopXMLNS, __IgnoreEls, _els, <<>>), {sasl_success, Text}. decode_sasl_success_els(__TopXMLNS, __IgnoreEls, [], Text) -> decode_sasl_success_cdata(__TopXMLNS, Text); decode_sasl_success_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Text) -> decode_sasl_success_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_sasl_success_els(__TopXMLNS, __IgnoreEls, [_ | _els], Text) -> decode_sasl_success_els(__TopXMLNS, __IgnoreEls, _els, Text). encode_sasl_success({sasl_success, Text}, _xmlns_attrs) -> _els = encode_sasl_success_cdata(Text, []), _attrs = _xmlns_attrs, {xmlel, <<"success">>, _attrs, _els}. decode_sasl_success_cdata(__TopXMLNS, <<>>) -> undefined; decode_sasl_success_cdata(__TopXMLNS, _val) -> case catch base64:decode(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"success">>, __TopXMLNS}}); _res -> _res end. encode_sasl_success_cdata(undefined, _acc) -> _acc; encode_sasl_success_cdata(_val, _acc) -> [{xmlcdata, base64:encode(_val)} | _acc]. decode_sasl_response(__TopXMLNS, __IgnoreEls, {xmlel, <<"response">>, _attrs, _els}) -> Text = decode_sasl_response_els(__TopXMLNS, __IgnoreEls, _els, <<>>), {sasl_response, Text}. decode_sasl_response_els(__TopXMLNS, __IgnoreEls, [], Text) -> decode_sasl_response_cdata(__TopXMLNS, Text); decode_sasl_response_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Text) -> decode_sasl_response_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_sasl_response_els(__TopXMLNS, __IgnoreEls, [_ | _els], Text) -> decode_sasl_response_els(__TopXMLNS, __IgnoreEls, _els, Text). encode_sasl_response({sasl_response, Text}, _xmlns_attrs) -> _els = encode_sasl_response_cdata(Text, []), _attrs = _xmlns_attrs, {xmlel, <<"response">>, _attrs, _els}. decode_sasl_response_cdata(__TopXMLNS, <<>>) -> undefined; decode_sasl_response_cdata(__TopXMLNS, _val) -> case catch base64:decode(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"response">>, __TopXMLNS}}); _res -> _res end. encode_sasl_response_cdata(undefined, _acc) -> _acc; encode_sasl_response_cdata(_val, _acc) -> [{xmlcdata, base64:encode(_val)} | _acc]. decode_sasl_challenge(__TopXMLNS, __IgnoreEls, {xmlel, <<"challenge">>, _attrs, _els}) -> Text = decode_sasl_challenge_els(__TopXMLNS, __IgnoreEls, _els, <<>>), {sasl_challenge, Text}. decode_sasl_challenge_els(__TopXMLNS, __IgnoreEls, [], Text) -> decode_sasl_challenge_cdata(__TopXMLNS, Text); decode_sasl_challenge_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Text) -> decode_sasl_challenge_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_sasl_challenge_els(__TopXMLNS, __IgnoreEls, [_ | _els], Text) -> decode_sasl_challenge_els(__TopXMLNS, __IgnoreEls, _els, Text). encode_sasl_challenge({sasl_challenge, Text}, _xmlns_attrs) -> _els = encode_sasl_challenge_cdata(Text, []), _attrs = _xmlns_attrs, {xmlel, <<"challenge">>, _attrs, _els}. decode_sasl_challenge_cdata(__TopXMLNS, <<>>) -> undefined; decode_sasl_challenge_cdata(__TopXMLNS, _val) -> case catch base64:decode(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"challenge">>, __TopXMLNS}}); _res -> _res end. encode_sasl_challenge_cdata(undefined, _acc) -> _acc; encode_sasl_challenge_cdata(_val, _acc) -> [{xmlcdata, base64:encode(_val)} | _acc]. decode_sasl_abort(__TopXMLNS, __IgnoreEls, {xmlel, <<"abort">>, _attrs, _els}) -> {sasl_abort}. encode_sasl_abort({sasl_abort}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"abort">>, _attrs, _els}. decode_sasl_auth(__TopXMLNS, __IgnoreEls, {xmlel, <<"auth">>, _attrs, _els}) -> Text = decode_sasl_auth_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Mechanism = decode_sasl_auth_attrs(__TopXMLNS, _attrs, undefined), {sasl_auth, Mechanism, Text}. decode_sasl_auth_els(__TopXMLNS, __IgnoreEls, [], Text) -> decode_sasl_auth_cdata(__TopXMLNS, Text); decode_sasl_auth_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Text) -> decode_sasl_auth_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_sasl_auth_els(__TopXMLNS, __IgnoreEls, [_ | _els], Text) -> decode_sasl_auth_els(__TopXMLNS, __IgnoreEls, _els, Text). decode_sasl_auth_attrs(__TopXMLNS, [{<<"mechanism">>, _val} | _attrs], _Mechanism) -> decode_sasl_auth_attrs(__TopXMLNS, _attrs, _val); decode_sasl_auth_attrs(__TopXMLNS, [_ | _attrs], Mechanism) -> decode_sasl_auth_attrs(__TopXMLNS, _attrs, Mechanism); decode_sasl_auth_attrs(__TopXMLNS, [], Mechanism) -> decode_sasl_auth_attr_mechanism(__TopXMLNS, Mechanism). encode_sasl_auth({sasl_auth, Mechanism, Text}, _xmlns_attrs) -> _els = encode_sasl_auth_cdata(Text, []), _attrs = encode_sasl_auth_attr_mechanism(Mechanism, _xmlns_attrs), {xmlel, <<"auth">>, _attrs, _els}. decode_sasl_auth_attr_mechanism(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"mechanism">>, <<"auth">>, __TopXMLNS}}); decode_sasl_auth_attr_mechanism(__TopXMLNS, _val) -> _val. encode_sasl_auth_attr_mechanism(_val, _acc) -> [{<<"mechanism">>, _val} | _acc]. decode_sasl_auth_cdata(__TopXMLNS, <<>>) -> undefined; decode_sasl_auth_cdata(__TopXMLNS, _val) -> case catch base64:decode(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"auth">>, __TopXMLNS}}); _res -> _res end. encode_sasl_auth_cdata(undefined, _acc) -> _acc; encode_sasl_auth_cdata(_val, _acc) -> [{xmlcdata, base64:encode(_val)} | _acc]. decode_bind(__TopXMLNS, __IgnoreEls, {xmlel, <<"bind">>, _attrs, _els}) -> {Jid, Resource} = decode_bind_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), {bind, Jid, Resource}. decode_bind_els(__TopXMLNS, __IgnoreEls, [], Jid, Resource) -> {Jid, Resource}; decode_bind_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"jid">>, _attrs, _} = _el | _els], Jid, Resource) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bind_els(__TopXMLNS, __IgnoreEls, _els, decode_bind_jid(__TopXMLNS, __IgnoreEls, _el), Resource); true -> decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid, Resource) end; decode_bind_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"resource">>, _attrs, _} = _el | _els], Jid, Resource) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid, decode_bind_resource(__TopXMLNS, __IgnoreEls, _el)); true -> decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid, Resource) end; decode_bind_els(__TopXMLNS, __IgnoreEls, [_ | _els], Jid, Resource) -> decode_bind_els(__TopXMLNS, __IgnoreEls, _els, Jid, Resource). encode_bind({bind, Jid, Resource}, _xmlns_attrs) -> _els = lists:reverse('encode_bind_$jid'(Jid, 'encode_bind_$resource'(Resource, []))), _attrs = _xmlns_attrs, {xmlel, <<"bind">>, _attrs, _els}. 'encode_bind_$jid'(undefined, _acc) -> _acc; 'encode_bind_$jid'(Jid, _acc) -> [encode_bind_jid(Jid, []) | _acc]. 'encode_bind_$resource'(undefined, _acc) -> _acc; 'encode_bind_$resource'(Resource, _acc) -> [encode_bind_resource(Resource, []) | _acc]. decode_bind_resource(__TopXMLNS, __IgnoreEls, {xmlel, <<"resource">>, _attrs, _els}) -> Cdata = decode_bind_resource_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_bind_resource_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_bind_resource_cdata(__TopXMLNS, Cdata); decode_bind_resource_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_bind_resource_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_bind_resource_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_bind_resource_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_bind_resource(Cdata, _xmlns_attrs) -> _els = encode_bind_resource_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"resource">>, _attrs, _els}. decode_bind_resource_cdata(__TopXMLNS, <<>>) -> undefined; decode_bind_resource_cdata(__TopXMLNS, _val) -> case catch resourceprep(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"resource">>, __TopXMLNS}}); _res -> _res end. encode_bind_resource_cdata(undefined, _acc) -> _acc; encode_bind_resource_cdata(_val, _acc) -> [{xmlcdata, resourceprep(_val)} | _acc]. decode_bind_jid(__TopXMLNS, __IgnoreEls, {xmlel, <<"jid">>, _attrs, _els}) -> Cdata = decode_bind_jid_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_bind_jid_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_bind_jid_cdata(__TopXMLNS, Cdata); decode_bind_jid_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_bind_jid_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_bind_jid_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_bind_jid_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_bind_jid(Cdata, _xmlns_attrs) -> _els = encode_bind_jid_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"jid">>, _attrs, _els}. decode_bind_jid_cdata(__TopXMLNS, <<>>) -> undefined; decode_bind_jid_cdata(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"jid">>, __TopXMLNS}}); _res -> _res end. encode_bind_jid_cdata(undefined, _acc) -> _acc; encode_bind_jid_cdata(_val, _acc) -> [{xmlcdata, enc_jid(_val)} | _acc]. decode_error(__TopXMLNS, __IgnoreEls, {xmlel, <<"error">>, _attrs, _els}) -> {Text, Reason} = decode_error_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), {Type, By} = decode_error_attrs(__TopXMLNS, _attrs, undefined, undefined), {error, Type, By, Reason, Text}. decode_error_els(__TopXMLNS, __IgnoreEls, [], Text, Reason) -> {Text, Reason}; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"text">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, decode_error_text(_xmlns, __IgnoreEls, _el), Reason); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"bad-request">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_bad_request(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"conflict">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_conflict(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"feature-not-implemented">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_feature_not_implemented(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"forbidden">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_forbidden(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"gone">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_gone(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"internal-server-error">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_internal_server_error(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item-not-found">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_item_not_found(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"jid-malformed">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_jid_malformed(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-acceptable">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_not_acceptable(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-allowed">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_not_allowed(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"not-authorized">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_not_authorized(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"policy-violation">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_policy_violation(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"recipient-unavailable">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_recipient_unavailable(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"redirect">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_redirect(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"registration-required">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_registration_required(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"remote-server-not-found">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_remote_server_not_found(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"remote-server-timeout">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_remote_server_timeout(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"resource-constraint">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_resource_constraint(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"service-unavailable">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_service_unavailable(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"subscription-required">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_subscription_required(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"undefined-condition">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_undefined_condition(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"unexpected-request">>, _attrs, _} = _el | _els], Text, Reason) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"urn:ietf:params:xml:ns:xmpp-stanzas">> -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, decode_error_unexpected_request(_xmlns, __IgnoreEls, _el)); true -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason) end; decode_error_els(__TopXMLNS, __IgnoreEls, [_ | _els], Text, Reason) -> decode_error_els(__TopXMLNS, __IgnoreEls, _els, Text, Reason). decode_error_attrs(__TopXMLNS, [{<<"type">>, _val} | _attrs], _Type, By) -> decode_error_attrs(__TopXMLNS, _attrs, _val, By); decode_error_attrs(__TopXMLNS, [{<<"by">>, _val} | _attrs], Type, _By) -> decode_error_attrs(__TopXMLNS, _attrs, Type, _val); decode_error_attrs(__TopXMLNS, [_ | _attrs], Type, By) -> decode_error_attrs(__TopXMLNS, _attrs, Type, By); decode_error_attrs(__TopXMLNS, [], Type, By) -> {decode_error_attr_type(__TopXMLNS, Type), decode_error_attr_by(__TopXMLNS, By)}. encode_error({error, Type, By, Reason, Text}, _xmlns_attrs) -> _els = lists:reverse('encode_error_$text'(Text, 'encode_error_$reason'(Reason, []))), _attrs = encode_error_attr_by(By, encode_error_attr_type(Type, _xmlns_attrs)), {xmlel, <<"error">>, _attrs, _els}. 'encode_error_$text'(undefined, _acc) -> _acc; 'encode_error_$text'(Text, _acc) -> [encode_error_text(Text, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]. 'encode_error_$reason'(undefined, _acc) -> _acc; 'encode_error_$reason'('bad-request' = Reason, _acc) -> [encode_error_bad_request(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'(conflict = Reason, _acc) -> [encode_error_conflict(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('feature-not-implemented' = Reason, _acc) -> [encode_error_feature_not_implemented(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'(forbidden = Reason, _acc) -> [encode_error_forbidden(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'({gone, _} = Reason, _acc) -> [encode_error_gone(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('internal-server-error' = Reason, _acc) -> [encode_error_internal_server_error(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('item-not-found' = Reason, _acc) -> [encode_error_item_not_found(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('jid-malformed' = Reason, _acc) -> [encode_error_jid_malformed(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('not-acceptable' = Reason, _acc) -> [encode_error_not_acceptable(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('not-allowed' = Reason, _acc) -> [encode_error_not_allowed(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('not-authorized' = Reason, _acc) -> [encode_error_not_authorized(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('policy-violation' = Reason, _acc) -> [encode_error_policy_violation(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('recipient-unavailable' = Reason, _acc) -> [encode_error_recipient_unavailable(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'({redirect, _} = Reason, _acc) -> [encode_error_redirect(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('registration-required' = Reason, _acc) -> [encode_error_registration_required(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('remote-server-not-found' = Reason, _acc) -> [encode_error_remote_server_not_found(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('remote-server-timeout' = Reason, _acc) -> [encode_error_remote_server_timeout(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('resource-constraint' = Reason, _acc) -> [encode_error_resource_constraint(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('service-unavailable' = Reason, _acc) -> [encode_error_service_unavailable(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('subscription-required' = Reason, _acc) -> [encode_error_subscription_required(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('undefined-condition' = Reason, _acc) -> [encode_error_undefined_condition(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]; 'encode_error_$reason'('unexpected-request' = Reason, _acc) -> [encode_error_unexpected_request(Reason, [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}]) | _acc]. decode_error_attr_type(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"type">>, <<"error">>, __TopXMLNS}}); decode_error_attr_type(__TopXMLNS, _val) -> case catch dec_enum(_val, [auth, cancel, continue, modify, wait]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"type">>, <<"error">>, __TopXMLNS}}); _res -> _res end. encode_error_attr_type(_val, _acc) -> [{<<"type">>, enc_enum(_val)} | _acc]. decode_error_attr_by(__TopXMLNS, undefined) -> undefined; decode_error_attr_by(__TopXMLNS, _val) -> _val. encode_error_attr_by(undefined, _acc) -> _acc; encode_error_attr_by(_val, _acc) -> [{<<"by">>, _val} | _acc]. decode_error_text(__TopXMLNS, __IgnoreEls, {xmlel, <<"text">>, _attrs, _els}) -> Data = decode_error_text_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Lang = decode_error_text_attrs(__TopXMLNS, _attrs, undefined), {text, Lang, Data}. decode_error_text_els(__TopXMLNS, __IgnoreEls, [], Data) -> decode_error_text_cdata(__TopXMLNS, Data); decode_error_text_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Data) -> decode_error_text_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_error_text_els(__TopXMLNS, __IgnoreEls, [_ | _els], Data) -> decode_error_text_els(__TopXMLNS, __IgnoreEls, _els, Data). decode_error_text_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], _Lang) -> decode_error_text_attrs(__TopXMLNS, _attrs, _val); decode_error_text_attrs(__TopXMLNS, [_ | _attrs], Lang) -> decode_error_text_attrs(__TopXMLNS, _attrs, Lang); decode_error_text_attrs(__TopXMLNS, [], Lang) -> 'decode_error_text_attr_xml:lang'(__TopXMLNS, Lang). encode_error_text({text, Lang, Data}, _xmlns_attrs) -> _els = encode_error_text_cdata(Data, []), _attrs = 'encode_error_text_attr_xml:lang'(Lang, _xmlns_attrs), {xmlel, <<"text">>, _attrs, _els}. 'decode_error_text_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_error_text_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_error_text_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_error_text_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_error_text_cdata(__TopXMLNS, <<>>) -> undefined; decode_error_text_cdata(__TopXMLNS, _val) -> _val. encode_error_text_cdata(undefined, _acc) -> _acc; encode_error_text_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_error_unexpected_request(__TopXMLNS, __IgnoreEls, {xmlel, <<"unexpected-request">>, _attrs, _els}) -> 'unexpected-request'. encode_error_unexpected_request('unexpected-request', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"unexpected-request">>, _attrs, _els}. decode_error_undefined_condition(__TopXMLNS, __IgnoreEls, {xmlel, <<"undefined-condition">>, _attrs, _els}) -> 'undefined-condition'. encode_error_undefined_condition('undefined-condition', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"undefined-condition">>, _attrs, _els}. decode_error_subscription_required(__TopXMLNS, __IgnoreEls, {xmlel, <<"subscription-required">>, _attrs, _els}) -> 'subscription-required'. encode_error_subscription_required('subscription-required', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"subscription-required">>, _attrs, _els}. decode_error_service_unavailable(__TopXMLNS, __IgnoreEls, {xmlel, <<"service-unavailable">>, _attrs, _els}) -> 'service-unavailable'. encode_error_service_unavailable('service-unavailable', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"service-unavailable">>, _attrs, _els}. decode_error_resource_constraint(__TopXMLNS, __IgnoreEls, {xmlel, <<"resource-constraint">>, _attrs, _els}) -> 'resource-constraint'. encode_error_resource_constraint('resource-constraint', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"resource-constraint">>, _attrs, _els}. decode_error_remote_server_timeout(__TopXMLNS, __IgnoreEls, {xmlel, <<"remote-server-timeout">>, _attrs, _els}) -> 'remote-server-timeout'. encode_error_remote_server_timeout('remote-server-timeout', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"remote-server-timeout">>, _attrs, _els}. decode_error_remote_server_not_found(__TopXMLNS, __IgnoreEls, {xmlel, <<"remote-server-not-found">>, _attrs, _els}) -> 'remote-server-not-found'. encode_error_remote_server_not_found('remote-server-not-found', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"remote-server-not-found">>, _attrs, _els}. decode_error_registration_required(__TopXMLNS, __IgnoreEls, {xmlel, <<"registration-required">>, _attrs, _els}) -> 'registration-required'. encode_error_registration_required('registration-required', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"registration-required">>, _attrs, _els}. decode_error_redirect(__TopXMLNS, __IgnoreEls, {xmlel, <<"redirect">>, _attrs, _els}) -> Uri = decode_error_redirect_els(__TopXMLNS, __IgnoreEls, _els, <<>>), {redirect, Uri}. decode_error_redirect_els(__TopXMLNS, __IgnoreEls, [], Uri) -> decode_error_redirect_cdata(__TopXMLNS, Uri); decode_error_redirect_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Uri) -> decode_error_redirect_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_error_redirect_els(__TopXMLNS, __IgnoreEls, [_ | _els], Uri) -> decode_error_redirect_els(__TopXMLNS, __IgnoreEls, _els, Uri). encode_error_redirect({redirect, Uri}, _xmlns_attrs) -> _els = encode_error_redirect_cdata(Uri, []), _attrs = _xmlns_attrs, {xmlel, <<"redirect">>, _attrs, _els}. decode_error_redirect_cdata(__TopXMLNS, <<>>) -> undefined; decode_error_redirect_cdata(__TopXMLNS, _val) -> _val. encode_error_redirect_cdata(undefined, _acc) -> _acc; encode_error_redirect_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_error_recipient_unavailable(__TopXMLNS, __IgnoreEls, {xmlel, <<"recipient-unavailable">>, _attrs, _els}) -> 'recipient-unavailable'. encode_error_recipient_unavailable('recipient-unavailable', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"recipient-unavailable">>, _attrs, _els}. decode_error_policy_violation(__TopXMLNS, __IgnoreEls, {xmlel, <<"policy-violation">>, _attrs, _els}) -> 'policy-violation'. encode_error_policy_violation('policy-violation', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"policy-violation">>, _attrs, _els}. decode_error_not_authorized(__TopXMLNS, __IgnoreEls, {xmlel, <<"not-authorized">>, _attrs, _els}) -> 'not-authorized'. encode_error_not_authorized('not-authorized', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"not-authorized">>, _attrs, _els}. decode_error_not_allowed(__TopXMLNS, __IgnoreEls, {xmlel, <<"not-allowed">>, _attrs, _els}) -> 'not-allowed'. encode_error_not_allowed('not-allowed', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"not-allowed">>, _attrs, _els}. decode_error_not_acceptable(__TopXMLNS, __IgnoreEls, {xmlel, <<"not-acceptable">>, _attrs, _els}) -> 'not-acceptable'. encode_error_not_acceptable('not-acceptable', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"not-acceptable">>, _attrs, _els}. decode_error_jid_malformed(__TopXMLNS, __IgnoreEls, {xmlel, <<"jid-malformed">>, _attrs, _els}) -> 'jid-malformed'. encode_error_jid_malformed('jid-malformed', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"jid-malformed">>, _attrs, _els}. decode_error_item_not_found(__TopXMLNS, __IgnoreEls, {xmlel, <<"item-not-found">>, _attrs, _els}) -> 'item-not-found'. encode_error_item_not_found('item-not-found', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"item-not-found">>, _attrs, _els}. decode_error_internal_server_error(__TopXMLNS, __IgnoreEls, {xmlel, <<"internal-server-error">>, _attrs, _els}) -> 'internal-server-error'. encode_error_internal_server_error('internal-server-error', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"internal-server-error">>, _attrs, _els}. decode_error_gone(__TopXMLNS, __IgnoreEls, {xmlel, <<"gone">>, _attrs, _els}) -> Uri = decode_error_gone_els(__TopXMLNS, __IgnoreEls, _els, <<>>), {gone, Uri}. decode_error_gone_els(__TopXMLNS, __IgnoreEls, [], Uri) -> decode_error_gone_cdata(__TopXMLNS, Uri); decode_error_gone_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Uri) -> decode_error_gone_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_error_gone_els(__TopXMLNS, __IgnoreEls, [_ | _els], Uri) -> decode_error_gone_els(__TopXMLNS, __IgnoreEls, _els, Uri). encode_error_gone({gone, Uri}, _xmlns_attrs) -> _els = encode_error_gone_cdata(Uri, []), _attrs = _xmlns_attrs, {xmlel, <<"gone">>, _attrs, _els}. decode_error_gone_cdata(__TopXMLNS, <<>>) -> undefined; decode_error_gone_cdata(__TopXMLNS, _val) -> _val. encode_error_gone_cdata(undefined, _acc) -> _acc; encode_error_gone_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_error_forbidden(__TopXMLNS, __IgnoreEls, {xmlel, <<"forbidden">>, _attrs, _els}) -> forbidden. encode_error_forbidden(forbidden, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"forbidden">>, _attrs, _els}. decode_error_feature_not_implemented(__TopXMLNS, __IgnoreEls, {xmlel, <<"feature-not-implemented">>, _attrs, _els}) -> 'feature-not-implemented'. encode_error_feature_not_implemented('feature-not-implemented', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"feature-not-implemented">>, _attrs, _els}. decode_error_conflict(__TopXMLNS, __IgnoreEls, {xmlel, <<"conflict">>, _attrs, _els}) -> conflict. encode_error_conflict(conflict, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"conflict">>, _attrs, _els}. decode_error_bad_request(__TopXMLNS, __IgnoreEls, {xmlel, <<"bad-request">>, _attrs, _els}) -> 'bad-request'. encode_error_bad_request('bad-request', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"bad-request">>, _attrs, _els}. decode_presence(__TopXMLNS, __IgnoreEls, {xmlel, <<"presence">>, _attrs, _els}) -> {Error, Status, Show, Priority, __Els} = decode_presence_els(__TopXMLNS, __IgnoreEls, _els, undefined, [], undefined, undefined, []), {Id, Type, From, To, Lang} = decode_presence_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined, undefined), {presence, Id, Type, Lang, From, To, Show, Status, Priority, Error, __Els}. decode_presence_els(__TopXMLNS, __IgnoreEls, [], Error, Status, Show, Priority, __Els) -> {Error, lists:reverse(Status), Show, Priority, lists:reverse(__Els)}; decode_presence_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"error">>, _attrs, _} = _el | _els], Error, Status, Show, Priority, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, decode_error(__TopXMLNS, __IgnoreEls, _el), Status, Show, Priority, __Els); true -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, Priority, __Els) end; decode_presence_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"show">>, _attrs, _} = _el | _els], Error, Status, Show, Priority, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, decode_presence_show(__TopXMLNS, __IgnoreEls, _el), Priority, __Els); true -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, Priority, __Els) end; decode_presence_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"status">>, _attrs, _} = _el | _els], Error, Status, Show, Priority, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, [decode_presence_status(__TopXMLNS, __IgnoreEls, _el) | Status], Show, Priority, __Els); true -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, Priority, __Els) end; decode_presence_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"priority">>, _attrs, _} = _el | _els], Error, Status, Show, Priority, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, decode_presence_priority(__TopXMLNS, __IgnoreEls, _el), __Els); true -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, Priority, __Els) end; decode_presence_els(__TopXMLNS, __IgnoreEls, [{xmlel, _, _, _} = _el | _els], Error, Status, Show, Priority, __Els) -> if __IgnoreEls -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, Priority, [_el | __Els]); true -> case is_known_tag(_el) of true -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, Priority, [decode(_el) | __Els]); false -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, Priority, __Els) end end; decode_presence_els(__TopXMLNS, __IgnoreEls, [_ | _els], Error, Status, Show, Priority, __Els) -> decode_presence_els(__TopXMLNS, __IgnoreEls, _els, Error, Status, Show, Priority, __Els). decode_presence_attrs(__TopXMLNS, [{<<"id">>, _val} | _attrs], _Id, Type, From, To, Lang) -> decode_presence_attrs(__TopXMLNS, _attrs, _val, Type, From, To, Lang); decode_presence_attrs(__TopXMLNS, [{<<"type">>, _val} | _attrs], Id, _Type, From, To, Lang) -> decode_presence_attrs(__TopXMLNS, _attrs, Id, _val, From, To, Lang); decode_presence_attrs(__TopXMLNS, [{<<"from">>, _val} | _attrs], Id, Type, _From, To, Lang) -> decode_presence_attrs(__TopXMLNS, _attrs, Id, Type, _val, To, Lang); decode_presence_attrs(__TopXMLNS, [{<<"to">>, _val} | _attrs], Id, Type, From, _To, Lang) -> decode_presence_attrs(__TopXMLNS, _attrs, Id, Type, From, _val, Lang); decode_presence_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], Id, Type, From, To, _Lang) -> decode_presence_attrs(__TopXMLNS, _attrs, Id, Type, From, To, _val); decode_presence_attrs(__TopXMLNS, [_ | _attrs], Id, Type, From, To, Lang) -> decode_presence_attrs(__TopXMLNS, _attrs, Id, Type, From, To, Lang); decode_presence_attrs(__TopXMLNS, [], Id, Type, From, To, Lang) -> {decode_presence_attr_id(__TopXMLNS, Id), decode_presence_attr_type(__TopXMLNS, Type), decode_presence_attr_from(__TopXMLNS, From), decode_presence_attr_to(__TopXMLNS, To), 'decode_presence_attr_xml:lang'(__TopXMLNS, Lang)}. encode_presence({presence, Id, Type, Lang, From, To, Show, Status, Priority, Error, __Els}, _xmlns_attrs) -> _els = [encode(_el) || _el <- __Els] ++ lists:reverse('encode_presence_$error'(Error, 'encode_presence_$status'(Status, 'encode_presence_$show'(Show, 'encode_presence_$priority'(Priority, []))))), _attrs = 'encode_presence_attr_xml:lang'(Lang, encode_presence_attr_to(To, encode_presence_attr_from(From, encode_presence_attr_type(Type, encode_presence_attr_id(Id, _xmlns_attrs))))), {xmlel, <<"presence">>, _attrs, _els}. 'encode_presence_$error'(undefined, _acc) -> _acc; 'encode_presence_$error'(Error, _acc) -> [encode_error(Error, []) | _acc]. 'encode_presence_$status'([], _acc) -> _acc; 'encode_presence_$status'([Status | _els], _acc) -> 'encode_presence_$status'(_els, [encode_presence_status(Status, []) | _acc]). 'encode_presence_$show'(undefined, _acc) -> _acc; 'encode_presence_$show'(Show, _acc) -> [encode_presence_show(Show, []) | _acc]. 'encode_presence_$priority'(undefined, _acc) -> _acc; 'encode_presence_$priority'(Priority, _acc) -> [encode_presence_priority(Priority, []) | _acc]. decode_presence_attr_id(__TopXMLNS, undefined) -> undefined; decode_presence_attr_id(__TopXMLNS, _val) -> _val. encode_presence_attr_id(undefined, _acc) -> _acc; encode_presence_attr_id(_val, _acc) -> [{<<"id">>, _val} | _acc]. decode_presence_attr_type(__TopXMLNS, undefined) -> undefined; decode_presence_attr_type(__TopXMLNS, _val) -> case catch dec_enum(_val, [unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"type">>, <<"presence">>, __TopXMLNS}}); _res -> _res end. encode_presence_attr_type(undefined, _acc) -> _acc; encode_presence_attr_type(_val, _acc) -> [{<<"type">>, enc_enum(_val)} | _acc]. decode_presence_attr_from(__TopXMLNS, undefined) -> undefined; decode_presence_attr_from(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"from">>, <<"presence">>, __TopXMLNS}}); _res -> _res end. encode_presence_attr_from(undefined, _acc) -> _acc; encode_presence_attr_from(_val, _acc) -> [{<<"from">>, enc_jid(_val)} | _acc]. decode_presence_attr_to(__TopXMLNS, undefined) -> undefined; decode_presence_attr_to(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"to">>, <<"presence">>, __TopXMLNS}}); _res -> _res end. encode_presence_attr_to(undefined, _acc) -> _acc; encode_presence_attr_to(_val, _acc) -> [{<<"to">>, enc_jid(_val)} | _acc]. 'decode_presence_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_presence_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_presence_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_presence_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_presence_priority(__TopXMLNS, __IgnoreEls, {xmlel, <<"priority">>, _attrs, _els}) -> Cdata = decode_presence_priority_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_presence_priority_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_presence_priority_cdata(__TopXMLNS, Cdata); decode_presence_priority_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_presence_priority_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_presence_priority_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_presence_priority_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_presence_priority(Cdata, _xmlns_attrs) -> _els = encode_presence_priority_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"priority">>, _attrs, _els}. decode_presence_priority_cdata(__TopXMLNS, <<>>) -> undefined; decode_presence_priority_cdata(__TopXMLNS, _val) -> case catch dec_int(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"priority">>, __TopXMLNS}}); _res -> _res end. encode_presence_priority_cdata(undefined, _acc) -> _acc; encode_presence_priority_cdata(_val, _acc) -> [{xmlcdata, enc_int(_val)} | _acc]. decode_presence_status(__TopXMLNS, __IgnoreEls, {xmlel, <<"status">>, _attrs, _els}) -> Data = decode_presence_status_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Lang = decode_presence_status_attrs(__TopXMLNS, _attrs, undefined), {text, Lang, Data}. decode_presence_status_els(__TopXMLNS, __IgnoreEls, [], Data) -> decode_presence_status_cdata(__TopXMLNS, Data); decode_presence_status_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Data) -> decode_presence_status_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_presence_status_els(__TopXMLNS, __IgnoreEls, [_ | _els], Data) -> decode_presence_status_els(__TopXMLNS, __IgnoreEls, _els, Data). decode_presence_status_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], _Lang) -> decode_presence_status_attrs(__TopXMLNS, _attrs, _val); decode_presence_status_attrs(__TopXMLNS, [_ | _attrs], Lang) -> decode_presence_status_attrs(__TopXMLNS, _attrs, Lang); decode_presence_status_attrs(__TopXMLNS, [], Lang) -> 'decode_presence_status_attr_xml:lang'(__TopXMLNS, Lang). encode_presence_status({text, Lang, Data}, _xmlns_attrs) -> _els = encode_presence_status_cdata(Data, []), _attrs = 'encode_presence_status_attr_xml:lang'(Lang, _xmlns_attrs), {xmlel, <<"status">>, _attrs, _els}. 'decode_presence_status_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_presence_status_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_presence_status_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_presence_status_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_presence_status_cdata(__TopXMLNS, <<>>) -> undefined; decode_presence_status_cdata(__TopXMLNS, _val) -> _val. encode_presence_status_cdata(undefined, _acc) -> _acc; encode_presence_status_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_presence_show(__TopXMLNS, __IgnoreEls, {xmlel, <<"show">>, _attrs, _els}) -> Cdata = decode_presence_show_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_presence_show_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_presence_show_cdata(__TopXMLNS, Cdata); decode_presence_show_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_presence_show_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_presence_show_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_presence_show_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_presence_show(Cdata, _xmlns_attrs) -> _els = encode_presence_show_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"show">>, _attrs, _els}. decode_presence_show_cdata(__TopXMLNS, <<>>) -> undefined; decode_presence_show_cdata(__TopXMLNS, _val) -> case catch dec_enum(_val, [away, chat, dnd, xa]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_cdata_value, <<>>, <<"show">>, __TopXMLNS}}); _res -> _res end. encode_presence_show_cdata(undefined, _acc) -> _acc; encode_presence_show_cdata(_val, _acc) -> [{xmlcdata, enc_enum(_val)} | _acc]. decode_message(__TopXMLNS, __IgnoreEls, {xmlel, <<"message">>, _attrs, _els}) -> {Error, Thread, Subject, Body, __Els} = decode_message_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, [], [], []), {Id, Type, From, To, Lang} = decode_message_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined, undefined), {message, Id, Type, Lang, From, To, Subject, Body, Thread, Error, __Els}. decode_message_els(__TopXMLNS, __IgnoreEls, [], Error, Thread, Subject, Body, __Els) -> {Error, Thread, lists:reverse(Subject), lists:reverse(Body), lists:reverse(__Els)}; decode_message_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"error">>, _attrs, _} = _el | _els], Error, Thread, Subject, Body, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, decode_error(__TopXMLNS, __IgnoreEls, _el), Thread, Subject, Body, __Els); true -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, Body, __Els) end; decode_message_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"subject">>, _attrs, _} = _el | _els], Error, Thread, Subject, Body, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, [decode_message_subject(__TopXMLNS, __IgnoreEls, _el) | Subject], Body, __Els); true -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, Body, __Els) end; decode_message_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"thread">>, _attrs, _} = _el | _els], Error, Thread, Subject, Body, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, decode_message_thread(__TopXMLNS, __IgnoreEls, _el), Subject, Body, __Els); true -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, Body, __Els) end; decode_message_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"body">>, _attrs, _} = _el | _els], Error, Thread, Subject, Body, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, [decode_message_body(__TopXMLNS, __IgnoreEls, _el) | Body], __Els); true -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, Body, __Els) end; decode_message_els(__TopXMLNS, __IgnoreEls, [{xmlel, _, _, _} = _el | _els], Error, Thread, Subject, Body, __Els) -> if __IgnoreEls -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, Body, [_el | __Els]); true -> case is_known_tag(_el) of true -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, Body, [decode(_el) | __Els]); false -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, Body, __Els) end end; decode_message_els(__TopXMLNS, __IgnoreEls, [_ | _els], Error, Thread, Subject, Body, __Els) -> decode_message_els(__TopXMLNS, __IgnoreEls, _els, Error, Thread, Subject, Body, __Els). decode_message_attrs(__TopXMLNS, [{<<"id">>, _val} | _attrs], _Id, Type, From, To, Lang) -> decode_message_attrs(__TopXMLNS, _attrs, _val, Type, From, To, Lang); decode_message_attrs(__TopXMLNS, [{<<"type">>, _val} | _attrs], Id, _Type, From, To, Lang) -> decode_message_attrs(__TopXMLNS, _attrs, Id, _val, From, To, Lang); decode_message_attrs(__TopXMLNS, [{<<"from">>, _val} | _attrs], Id, Type, _From, To, Lang) -> decode_message_attrs(__TopXMLNS, _attrs, Id, Type, _val, To, Lang); decode_message_attrs(__TopXMLNS, [{<<"to">>, _val} | _attrs], Id, Type, From, _To, Lang) -> decode_message_attrs(__TopXMLNS, _attrs, Id, Type, From, _val, Lang); decode_message_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], Id, Type, From, To, _Lang) -> decode_message_attrs(__TopXMLNS, _attrs, Id, Type, From, To, _val); decode_message_attrs(__TopXMLNS, [_ | _attrs], Id, Type, From, To, Lang) -> decode_message_attrs(__TopXMLNS, _attrs, Id, Type, From, To, Lang); decode_message_attrs(__TopXMLNS, [], Id, Type, From, To, Lang) -> {decode_message_attr_id(__TopXMLNS, Id), decode_message_attr_type(__TopXMLNS, Type), decode_message_attr_from(__TopXMLNS, From), decode_message_attr_to(__TopXMLNS, To), 'decode_message_attr_xml:lang'(__TopXMLNS, Lang)}. encode_message({message, Id, Type, Lang, From, To, Subject, Body, Thread, Error, __Els}, _xmlns_attrs) -> _els = [encode(_el) || _el <- __Els] ++ lists:reverse('encode_message_$error'(Error, 'encode_message_$thread'(Thread, 'encode_message_$subject'(Subject, 'encode_message_$body'(Body, []))))), _attrs = 'encode_message_attr_xml:lang'(Lang, encode_message_attr_to(To, encode_message_attr_from(From, encode_message_attr_type(Type, encode_message_attr_id(Id, _xmlns_attrs))))), {xmlel, <<"message">>, _attrs, _els}. 'encode_message_$error'(undefined, _acc) -> _acc; 'encode_message_$error'(Error, _acc) -> [encode_error(Error, []) | _acc]. 'encode_message_$thread'(undefined, _acc) -> _acc; 'encode_message_$thread'(Thread, _acc) -> [encode_message_thread(Thread, []) | _acc]. 'encode_message_$subject'([], _acc) -> _acc; 'encode_message_$subject'([Subject | _els], _acc) -> 'encode_message_$subject'(_els, [encode_message_subject(Subject, []) | _acc]). 'encode_message_$body'([], _acc) -> _acc; 'encode_message_$body'([Body | _els], _acc) -> 'encode_message_$body'(_els, [encode_message_body(Body, []) | _acc]). decode_message_attr_id(__TopXMLNS, undefined) -> undefined; decode_message_attr_id(__TopXMLNS, _val) -> _val. encode_message_attr_id(undefined, _acc) -> _acc; encode_message_attr_id(_val, _acc) -> [{<<"id">>, _val} | _acc]. decode_message_attr_type(__TopXMLNS, undefined) -> normal; decode_message_attr_type(__TopXMLNS, _val) -> case catch dec_enum(_val, [chat, normal, groupchat, headline, error]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"type">>, <<"message">>, __TopXMLNS}}); _res -> _res end. encode_message_attr_type(normal, _acc) -> _acc; encode_message_attr_type(_val, _acc) -> [{<<"type">>, enc_enum(_val)} | _acc]. decode_message_attr_from(__TopXMLNS, undefined) -> undefined; decode_message_attr_from(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"from">>, <<"message">>, __TopXMLNS}}); _res -> _res end. encode_message_attr_from(undefined, _acc) -> _acc; encode_message_attr_from(_val, _acc) -> [{<<"from">>, enc_jid(_val)} | _acc]. decode_message_attr_to(__TopXMLNS, undefined) -> undefined; decode_message_attr_to(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"to">>, <<"message">>, __TopXMLNS}}); _res -> _res end. encode_message_attr_to(undefined, _acc) -> _acc; encode_message_attr_to(_val, _acc) -> [{<<"to">>, enc_jid(_val)} | _acc]. 'decode_message_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_message_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_message_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_message_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_message_thread(__TopXMLNS, __IgnoreEls, {xmlel, <<"thread">>, _attrs, _els}) -> Cdata = decode_message_thread_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_message_thread_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_message_thread_cdata(__TopXMLNS, Cdata); decode_message_thread_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_message_thread_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_message_thread_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_message_thread_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_message_thread(Cdata, _xmlns_attrs) -> _els = encode_message_thread_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"thread">>, _attrs, _els}. decode_message_thread_cdata(__TopXMLNS, <<>>) -> undefined; decode_message_thread_cdata(__TopXMLNS, _val) -> _val. encode_message_thread_cdata(undefined, _acc) -> _acc; encode_message_thread_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_message_body(__TopXMLNS, __IgnoreEls, {xmlel, <<"body">>, _attrs, _els}) -> Data = decode_message_body_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Lang = decode_message_body_attrs(__TopXMLNS, _attrs, undefined), {text, Lang, Data}. decode_message_body_els(__TopXMLNS, __IgnoreEls, [], Data) -> decode_message_body_cdata(__TopXMLNS, Data); decode_message_body_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Data) -> decode_message_body_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_message_body_els(__TopXMLNS, __IgnoreEls, [_ | _els], Data) -> decode_message_body_els(__TopXMLNS, __IgnoreEls, _els, Data). decode_message_body_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], _Lang) -> decode_message_body_attrs(__TopXMLNS, _attrs, _val); decode_message_body_attrs(__TopXMLNS, [_ | _attrs], Lang) -> decode_message_body_attrs(__TopXMLNS, _attrs, Lang); decode_message_body_attrs(__TopXMLNS, [], Lang) -> 'decode_message_body_attr_xml:lang'(__TopXMLNS, Lang). encode_message_body({text, Lang, Data}, _xmlns_attrs) -> _els = encode_message_body_cdata(Data, []), _attrs = 'encode_message_body_attr_xml:lang'(Lang, _xmlns_attrs), {xmlel, <<"body">>, _attrs, _els}. 'decode_message_body_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_message_body_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_message_body_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_message_body_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_message_body_cdata(__TopXMLNS, <<>>) -> undefined; decode_message_body_cdata(__TopXMLNS, _val) -> _val. encode_message_body_cdata(undefined, _acc) -> _acc; encode_message_body_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_message_subject(__TopXMLNS, __IgnoreEls, {xmlel, <<"subject">>, _attrs, _els}) -> Data = decode_message_subject_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Lang = decode_message_subject_attrs(__TopXMLNS, _attrs, undefined), {text, Lang, Data}. decode_message_subject_els(__TopXMLNS, __IgnoreEls, [], Data) -> decode_message_subject_cdata(__TopXMLNS, Data); decode_message_subject_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Data) -> decode_message_subject_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_message_subject_els(__TopXMLNS, __IgnoreEls, [_ | _els], Data) -> decode_message_subject_els(__TopXMLNS, __IgnoreEls, _els, Data). decode_message_subject_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], _Lang) -> decode_message_subject_attrs(__TopXMLNS, _attrs, _val); decode_message_subject_attrs(__TopXMLNS, [_ | _attrs], Lang) -> decode_message_subject_attrs(__TopXMLNS, _attrs, Lang); decode_message_subject_attrs(__TopXMLNS, [], Lang) -> 'decode_message_subject_attr_xml:lang'(__TopXMLNS, Lang). encode_message_subject({text, Lang, Data}, _xmlns_attrs) -> _els = encode_message_subject_cdata(Data, []), _attrs = 'encode_message_subject_attr_xml:lang'(Lang, _xmlns_attrs), {xmlel, <<"subject">>, _attrs, _els}. 'decode_message_subject_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_message_subject_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_message_subject_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_message_subject_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_message_subject_cdata(__TopXMLNS, <<>>) -> undefined; decode_message_subject_cdata(__TopXMLNS, _val) -> _val. encode_message_subject_cdata(undefined, _acc) -> _acc; encode_message_subject_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_iq(__TopXMLNS, __IgnoreEls, {xmlel, <<"iq">>, _attrs, _els}) -> {Error, __Els} = decode_iq_els(__TopXMLNS, __IgnoreEls, _els, undefined, []), {Id, Type, From, To, Lang} = decode_iq_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined, undefined), {iq, Id, Type, Lang, From, To, Error, __Els}. decode_iq_els(__TopXMLNS, __IgnoreEls, [], Error, __Els) -> {Error, lists:reverse(__Els)}; decode_iq_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"error">>, _attrs, _} = _el | _els], Error, __Els) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_iq_els(__TopXMLNS, __IgnoreEls, _els, decode_error(__TopXMLNS, __IgnoreEls, _el), __Els); true -> decode_iq_els(__TopXMLNS, __IgnoreEls, _els, Error, __Els) end; decode_iq_els(__TopXMLNS, __IgnoreEls, [{xmlel, _, _, _} = _el | _els], Error, __Els) -> if __IgnoreEls -> decode_iq_els(__TopXMLNS, __IgnoreEls, _els, Error, [_el | __Els]); true -> case is_known_tag(_el) of true -> decode_iq_els(__TopXMLNS, __IgnoreEls, _els, Error, [decode(_el) | __Els]); false -> decode_iq_els(__TopXMLNS, __IgnoreEls, _els, Error, __Els) end end; decode_iq_els(__TopXMLNS, __IgnoreEls, [_ | _els], Error, __Els) -> decode_iq_els(__TopXMLNS, __IgnoreEls, _els, Error, __Els). decode_iq_attrs(__TopXMLNS, [{<<"id">>, _val} | _attrs], _Id, Type, From, To, Lang) -> decode_iq_attrs(__TopXMLNS, _attrs, _val, Type, From, To, Lang); decode_iq_attrs(__TopXMLNS, [{<<"type">>, _val} | _attrs], Id, _Type, From, To, Lang) -> decode_iq_attrs(__TopXMLNS, _attrs, Id, _val, From, To, Lang); decode_iq_attrs(__TopXMLNS, [{<<"from">>, _val} | _attrs], Id, Type, _From, To, Lang) -> decode_iq_attrs(__TopXMLNS, _attrs, Id, Type, _val, To, Lang); decode_iq_attrs(__TopXMLNS, [{<<"to">>, _val} | _attrs], Id, Type, From, _To, Lang) -> decode_iq_attrs(__TopXMLNS, _attrs, Id, Type, From, _val, Lang); decode_iq_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], Id, Type, From, To, _Lang) -> decode_iq_attrs(__TopXMLNS, _attrs, Id, Type, From, To, _val); decode_iq_attrs(__TopXMLNS, [_ | _attrs], Id, Type, From, To, Lang) -> decode_iq_attrs(__TopXMLNS, _attrs, Id, Type, From, To, Lang); decode_iq_attrs(__TopXMLNS, [], Id, Type, From, To, Lang) -> {decode_iq_attr_id(__TopXMLNS, Id), decode_iq_attr_type(__TopXMLNS, Type), decode_iq_attr_from(__TopXMLNS, From), decode_iq_attr_to(__TopXMLNS, To), 'decode_iq_attr_xml:lang'(__TopXMLNS, Lang)}. encode_iq({iq, Id, Type, Lang, From, To, Error, __Els}, _xmlns_attrs) -> _els = [encode(_el) || _el <- __Els] ++ lists:reverse('encode_iq_$error'(Error, [])), _attrs = 'encode_iq_attr_xml:lang'(Lang, encode_iq_attr_to(To, encode_iq_attr_from(From, encode_iq_attr_type(Type, encode_iq_attr_id(Id, _xmlns_attrs))))), {xmlel, <<"iq">>, _attrs, _els}. 'encode_iq_$error'(undefined, _acc) -> _acc; 'encode_iq_$error'(Error, _acc) -> [encode_error(Error, []) | _acc]. decode_iq_attr_id(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"id">>, <<"iq">>, __TopXMLNS}}); decode_iq_attr_id(__TopXMLNS, _val) -> _val. encode_iq_attr_id(_val, _acc) -> [{<<"id">>, _val} | _acc]. decode_iq_attr_type(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"type">>, <<"iq">>, __TopXMLNS}}); decode_iq_attr_type(__TopXMLNS, _val) -> case catch dec_enum(_val, [get, set, result, error]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"type">>, <<"iq">>, __TopXMLNS}}); _res -> _res end. encode_iq_attr_type(_val, _acc) -> [{<<"type">>, enc_enum(_val)} | _acc]. decode_iq_attr_from(__TopXMLNS, undefined) -> undefined; decode_iq_attr_from(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"from">>, <<"iq">>, __TopXMLNS}}); _res -> _res end. encode_iq_attr_from(undefined, _acc) -> _acc; encode_iq_attr_from(_val, _acc) -> [{<<"from">>, enc_jid(_val)} | _acc]. decode_iq_attr_to(__TopXMLNS, undefined) -> undefined; decode_iq_attr_to(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"to">>, <<"iq">>, __TopXMLNS}}); _res -> _res end. encode_iq_attr_to(undefined, _acc) -> _acc; encode_iq_attr_to(_val, _acc) -> [{<<"to">>, enc_jid(_val)} | _acc]. 'decode_iq_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_iq_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_iq_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_iq_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_stats(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> Stat = decode_stats_els(__TopXMLNS, __IgnoreEls, _els, []), {stats, Stat}. decode_stats_els(__TopXMLNS, __IgnoreEls, [], Stat) -> lists:reverse(Stat); decode_stats_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"stat">>, _attrs, _} = _el | _els], Stat) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_stats_els(__TopXMLNS, __IgnoreEls, _els, [decode_stat(__TopXMLNS, __IgnoreEls, _el) | Stat]); true -> decode_stats_els(__TopXMLNS, __IgnoreEls, _els, Stat) end; decode_stats_els(__TopXMLNS, __IgnoreEls, [_ | _els], Stat) -> decode_stats_els(__TopXMLNS, __IgnoreEls, _els, Stat). encode_stats({stats, Stat}, _xmlns_attrs) -> _els = lists:reverse('encode_stats_$stat'(Stat, [])), _attrs = _xmlns_attrs, {xmlel, <<"query">>, _attrs, _els}. 'encode_stats_$stat'([], _acc) -> _acc; 'encode_stats_$stat'([Stat | _els], _acc) -> 'encode_stats_$stat'(_els, [encode_stat(Stat, []) | _acc]). decode_stat(__TopXMLNS, __IgnoreEls, {xmlel, <<"stat">>, _attrs, _els}) -> Error = decode_stat_els(__TopXMLNS, __IgnoreEls, _els, []), {Name, Units, Value} = decode_stat_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {stat, Name, Units, Value, Error}. decode_stat_els(__TopXMLNS, __IgnoreEls, [], Error) -> lists:reverse(Error); decode_stat_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"error">>, _attrs, _} = _el | _els], Error) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_stat_els(__TopXMLNS, __IgnoreEls, _els, [decode_stat_error(__TopXMLNS, __IgnoreEls, _el) | Error]); true -> decode_stat_els(__TopXMLNS, __IgnoreEls, _els, Error) end; decode_stat_els(__TopXMLNS, __IgnoreEls, [_ | _els], Error) -> decode_stat_els(__TopXMLNS, __IgnoreEls, _els, Error). decode_stat_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], _Name, Units, Value) -> decode_stat_attrs(__TopXMLNS, _attrs, _val, Units, Value); decode_stat_attrs(__TopXMLNS, [{<<"units">>, _val} | _attrs], Name, _Units, Value) -> decode_stat_attrs(__TopXMLNS, _attrs, Name, _val, Value); decode_stat_attrs(__TopXMLNS, [{<<"value">>, _val} | _attrs], Name, Units, _Value) -> decode_stat_attrs(__TopXMLNS, _attrs, Name, Units, _val); decode_stat_attrs(__TopXMLNS, [_ | _attrs], Name, Units, Value) -> decode_stat_attrs(__TopXMLNS, _attrs, Name, Units, Value); decode_stat_attrs(__TopXMLNS, [], Name, Units, Value) -> {decode_stat_attr_name(__TopXMLNS, Name), decode_stat_attr_units(__TopXMLNS, Units), decode_stat_attr_value(__TopXMLNS, Value)}. encode_stat({stat, Name, Units, Value, Error}, _xmlns_attrs) -> _els = lists:reverse('encode_stat_$error'(Error, [])), _attrs = encode_stat_attr_value(Value, encode_stat_attr_units(Units, encode_stat_attr_name(Name, _xmlns_attrs))), {xmlel, <<"stat">>, _attrs, _els}. 'encode_stat_$error'([], _acc) -> _acc; 'encode_stat_$error'([Error | _els], _acc) -> 'encode_stat_$error'(_els, [encode_stat_error(Error, []) | _acc]). decode_stat_attr_name(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"name">>, <<"stat">>, __TopXMLNS}}); decode_stat_attr_name(__TopXMLNS, _val) -> _val. encode_stat_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_stat_attr_units(__TopXMLNS, undefined) -> undefined; decode_stat_attr_units(__TopXMLNS, _val) -> _val. encode_stat_attr_units(undefined, _acc) -> _acc; encode_stat_attr_units(_val, _acc) -> [{<<"units">>, _val} | _acc]. decode_stat_attr_value(__TopXMLNS, undefined) -> undefined; decode_stat_attr_value(__TopXMLNS, _val) -> _val. encode_stat_attr_value(undefined, _acc) -> _acc; encode_stat_attr_value(_val, _acc) -> [{<<"value">>, _val} | _acc]. decode_stat_error(__TopXMLNS, __IgnoreEls, {xmlel, <<"error">>, _attrs, _els}) -> Cdata = decode_stat_error_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Code = decode_stat_error_attrs(__TopXMLNS, _attrs, undefined), {Code, Cdata}. decode_stat_error_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_stat_error_cdata(__TopXMLNS, Cdata); decode_stat_error_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_stat_error_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_stat_error_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_stat_error_els(__TopXMLNS, __IgnoreEls, _els, Cdata). decode_stat_error_attrs(__TopXMLNS, [{<<"code">>, _val} | _attrs], _Code) -> decode_stat_error_attrs(__TopXMLNS, _attrs, _val); decode_stat_error_attrs(__TopXMLNS, [_ | _attrs], Code) -> decode_stat_error_attrs(__TopXMLNS, _attrs, Code); decode_stat_error_attrs(__TopXMLNS, [], Code) -> decode_stat_error_attr_code(__TopXMLNS, Code). encode_stat_error({Code, Cdata}, _xmlns_attrs) -> _els = encode_stat_error_cdata(Cdata, []), _attrs = encode_stat_error_attr_code(Code, _xmlns_attrs), {xmlel, <<"error">>, _attrs, _els}. decode_stat_error_attr_code(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"code">>, <<"error">>, __TopXMLNS}}); decode_stat_error_attr_code(__TopXMLNS, _val) -> case catch dec_int(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"code">>, <<"error">>, __TopXMLNS}}); _res -> _res end. encode_stat_error_attr_code(_val, _acc) -> [{<<"code">>, enc_int(_val)} | _acc]. decode_stat_error_cdata(__TopXMLNS, <<>>) -> undefined; decode_stat_error_cdata(__TopXMLNS, _val) -> _val. encode_stat_error_cdata(undefined, _acc) -> _acc; encode_stat_error_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_bookmarks_storage(__TopXMLNS, __IgnoreEls, {xmlel, <<"storage">>, _attrs, _els}) -> {Conference, Url} = decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, _els, [], []), {bookmark_storage, Conference, Url}. decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, [], Conference, Url) -> {lists:reverse(Conference), lists:reverse(Url)}; decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"conference">>, _attrs, _} = _el | _els], Conference, Url) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, _els, [decode_bookmark_conference(__TopXMLNS, __IgnoreEls, _el) | Conference], Url); true -> decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, _els, Conference, Url) end; decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"url">>, _attrs, _} = _el | _els], Conference, Url) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, _els, Conference, [decode_bookmark_url(__TopXMLNS, __IgnoreEls, _el) | Url]); true -> decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, _els, Conference, Url) end; decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, [_ | _els], Conference, Url) -> decode_bookmarks_storage_els(__TopXMLNS, __IgnoreEls, _els, Conference, Url). encode_bookmarks_storage({bookmark_storage, Conference, Url}, _xmlns_attrs) -> _els = lists:reverse('encode_bookmarks_storage_$conference'(Conference, 'encode_bookmarks_storage_$url'(Url, []))), _attrs = _xmlns_attrs, {xmlel, <<"storage">>, _attrs, _els}. 'encode_bookmarks_storage_$conference'([], _acc) -> _acc; 'encode_bookmarks_storage_$conference'([Conference | _els], _acc) -> 'encode_bookmarks_storage_$conference'(_els, [encode_bookmark_conference(Conference, []) | _acc]). 'encode_bookmarks_storage_$url'([], _acc) -> _acc; 'encode_bookmarks_storage_$url'([Url | _els], _acc) -> 'encode_bookmarks_storage_$url'(_els, [encode_bookmark_url(Url, []) | _acc]). decode_bookmark_url(__TopXMLNS, __IgnoreEls, {xmlel, <<"url">>, _attrs, _els}) -> {Name, Url} = decode_bookmark_url_attrs(__TopXMLNS, _attrs, undefined, undefined), {bookmark_url, Name, Url}. decode_bookmark_url_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], _Name, Url) -> decode_bookmark_url_attrs(__TopXMLNS, _attrs, _val, Url); decode_bookmark_url_attrs(__TopXMLNS, [{<<"url">>, _val} | _attrs], Name, _Url) -> decode_bookmark_url_attrs(__TopXMLNS, _attrs, Name, _val); decode_bookmark_url_attrs(__TopXMLNS, [_ | _attrs], Name, Url) -> decode_bookmark_url_attrs(__TopXMLNS, _attrs, Name, Url); decode_bookmark_url_attrs(__TopXMLNS, [], Name, Url) -> {decode_bookmark_url_attr_name(__TopXMLNS, Name), decode_bookmark_url_attr_url(__TopXMLNS, Url)}. encode_bookmark_url({bookmark_url, Name, Url}, _xmlns_attrs) -> _els = [], _attrs = encode_bookmark_url_attr_url(Url, encode_bookmark_url_attr_name(Name, _xmlns_attrs)), {xmlel, <<"url">>, _attrs, _els}. decode_bookmark_url_attr_name(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"name">>, <<"url">>, __TopXMLNS}}); decode_bookmark_url_attr_name(__TopXMLNS, _val) -> _val. encode_bookmark_url_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_bookmark_url_attr_url(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"url">>, <<"url">>, __TopXMLNS}}); decode_bookmark_url_attr_url(__TopXMLNS, _val) -> _val. encode_bookmark_url_attr_url(_val, _acc) -> [{<<"url">>, _val} | _acc]. decode_bookmark_conference(__TopXMLNS, __IgnoreEls, {xmlel, <<"conference">>, _attrs, _els}) -> {Password, Nick} = decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined), {Name, Jid, Autojoin} = decode_bookmark_conference_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {bookmark_conference, Name, Jid, Autojoin, Nick, Password}. decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, [], Password, Nick) -> {Password, Nick}; decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"nick">>, _attrs, _} = _el | _els], Password, Nick) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, _els, Password, decode_conference_nick(__TopXMLNS, __IgnoreEls, _el)); true -> decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, _els, Password, Nick) end; decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"password">>, _attrs, _} = _el | _els], Password, Nick) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, _els, decode_conference_password(__TopXMLNS, __IgnoreEls, _el), Nick); true -> decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, _els, Password, Nick) end; decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, [_ | _els], Password, Nick) -> decode_bookmark_conference_els(__TopXMLNS, __IgnoreEls, _els, Password, Nick). decode_bookmark_conference_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], _Name, Jid, Autojoin) -> decode_bookmark_conference_attrs(__TopXMLNS, _attrs, _val, Jid, Autojoin); decode_bookmark_conference_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], Name, _Jid, Autojoin) -> decode_bookmark_conference_attrs(__TopXMLNS, _attrs, Name, _val, Autojoin); decode_bookmark_conference_attrs(__TopXMLNS, [{<<"autojoin">>, _val} | _attrs], Name, Jid, _Autojoin) -> decode_bookmark_conference_attrs(__TopXMLNS, _attrs, Name, Jid, _val); decode_bookmark_conference_attrs(__TopXMLNS, [_ | _attrs], Name, Jid, Autojoin) -> decode_bookmark_conference_attrs(__TopXMLNS, _attrs, Name, Jid, Autojoin); decode_bookmark_conference_attrs(__TopXMLNS, [], Name, Jid, Autojoin) -> {decode_bookmark_conference_attr_name(__TopXMLNS, Name), decode_bookmark_conference_attr_jid(__TopXMLNS, Jid), decode_bookmark_conference_attr_autojoin(__TopXMLNS, Autojoin)}. encode_bookmark_conference({bookmark_conference, Name, Jid, Autojoin, Nick, Password}, _xmlns_attrs) -> _els = lists:reverse('encode_bookmark_conference_$password'(Password, 'encode_bookmark_conference_$nick'(Nick, []))), _attrs = encode_bookmark_conference_attr_autojoin(Autojoin, encode_bookmark_conference_attr_jid(Jid, encode_bookmark_conference_attr_name(Name, _xmlns_attrs))), {xmlel, <<"conference">>, _attrs, _els}. 'encode_bookmark_conference_$password'(undefined, _acc) -> _acc; 'encode_bookmark_conference_$password'(Password, _acc) -> [encode_conference_password(Password, []) | _acc]. 'encode_bookmark_conference_$nick'(undefined, _acc) -> _acc; 'encode_bookmark_conference_$nick'(Nick, _acc) -> [encode_conference_nick(Nick, []) | _acc]. decode_bookmark_conference_attr_name(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"name">>, <<"conference">>, __TopXMLNS}}); decode_bookmark_conference_attr_name(__TopXMLNS, _val) -> _val. encode_bookmark_conference_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_bookmark_conference_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"conference">>, __TopXMLNS}}); decode_bookmark_conference_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"conference">>, __TopXMLNS}}); _res -> _res end. encode_bookmark_conference_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_bookmark_conference_attr_autojoin(__TopXMLNS, undefined) -> false; decode_bookmark_conference_attr_autojoin(__TopXMLNS, _val) -> case catch dec_bool(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"autojoin">>, <<"conference">>, __TopXMLNS}}); _res -> _res end. encode_bookmark_conference_attr_autojoin(false, _acc) -> _acc; encode_bookmark_conference_attr_autojoin(_val, _acc) -> [{<<"autojoin">>, enc_bool(_val)} | _acc]. decode_conference_password(__TopXMLNS, __IgnoreEls, {xmlel, <<"password">>, _attrs, _els}) -> Cdata = decode_conference_password_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_conference_password_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_conference_password_cdata(__TopXMLNS, Cdata); decode_conference_password_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_conference_password_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_conference_password_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_conference_password_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_conference_password(Cdata, _xmlns_attrs) -> _els = encode_conference_password_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"password">>, _attrs, _els}. decode_conference_password_cdata(__TopXMLNS, <<>>) -> undefined; decode_conference_password_cdata(__TopXMLNS, _val) -> _val. encode_conference_password_cdata(undefined, _acc) -> _acc; encode_conference_password_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_conference_nick(__TopXMLNS, __IgnoreEls, {xmlel, <<"nick">>, _attrs, _els}) -> Cdata = decode_conference_nick_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_conference_nick_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_conference_nick_cdata(__TopXMLNS, Cdata); decode_conference_nick_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_conference_nick_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_conference_nick_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_conference_nick_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_conference_nick(Cdata, _xmlns_attrs) -> _els = encode_conference_nick_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"nick">>, _attrs, _els}. decode_conference_nick_cdata(__TopXMLNS, <<>>) -> undefined; decode_conference_nick_cdata(__TopXMLNS, _val) -> _val. encode_conference_nick_cdata(undefined, _acc) -> _acc; encode_conference_nick_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_private(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> __Xmls = decode_private_els(__TopXMLNS, __IgnoreEls, _els, []), {private, __Xmls}. decode_private_els(__TopXMLNS, __IgnoreEls, [], __Xmls) -> lists:reverse(__Xmls); decode_private_els(__TopXMLNS, __IgnoreEls, [{xmlel, _, _, _} = _el | _els], __Xmls) -> decode_private_els(__TopXMLNS, __IgnoreEls, _els, [_el | __Xmls]); decode_private_els(__TopXMLNS, __IgnoreEls, [_ | _els], __Xmls) -> decode_private_els(__TopXMLNS, __IgnoreEls, _els, __Xmls). encode_private({private, __Xmls}, _xmlns_attrs) -> _els = __Xmls, _attrs = _xmlns_attrs, {xmlel, <<"query">>, _attrs, _els}. decode_disco_items(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> Items = decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els, []), Node = decode_disco_items_attrs(__TopXMLNS, _attrs, undefined), {disco_items, Node, Items}. decode_disco_items_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_disco_items_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els, [decode_disco_item(__TopXMLNS, __IgnoreEls, _el) | Items]); true -> decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_disco_items_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_disco_items_els(__TopXMLNS, __IgnoreEls, _els, Items). decode_disco_items_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node) -> decode_disco_items_attrs(__TopXMLNS, _attrs, _val); decode_disco_items_attrs(__TopXMLNS, [_ | _attrs], Node) -> decode_disco_items_attrs(__TopXMLNS, _attrs, Node); decode_disco_items_attrs(__TopXMLNS, [], Node) -> decode_disco_items_attr_node(__TopXMLNS, Node). encode_disco_items({disco_items, Node, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_disco_items_$items'(Items, [])), _attrs = encode_disco_items_attr_node(Node, _xmlns_attrs), {xmlel, <<"query">>, _attrs, _els}. 'encode_disco_items_$items'([], _acc) -> _acc; 'encode_disco_items_$items'([Items | _els], _acc) -> 'encode_disco_items_$items'(_els, [encode_disco_item(Items, []) | _acc]). decode_disco_items_attr_node(__TopXMLNS, undefined) -> undefined; decode_disco_items_attr_node(__TopXMLNS, _val) -> _val. encode_disco_items_attr_node(undefined, _acc) -> _acc; encode_disco_items_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_disco_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> {Jid, Name, Node} = decode_disco_item_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), {disco_item, Jid, Name, Node}. decode_disco_item_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid, Name, Node) -> decode_disco_item_attrs(__TopXMLNS, _attrs, _val, Name, Node); decode_disco_item_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], Jid, _Name, Node) -> decode_disco_item_attrs(__TopXMLNS, _attrs, Jid, _val, Node); decode_disco_item_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], Jid, Name, _Node) -> decode_disco_item_attrs(__TopXMLNS, _attrs, Jid, Name, _val); decode_disco_item_attrs(__TopXMLNS, [_ | _attrs], Jid, Name, Node) -> decode_disco_item_attrs(__TopXMLNS, _attrs, Jid, Name, Node); decode_disco_item_attrs(__TopXMLNS, [], Jid, Name, Node) -> {decode_disco_item_attr_jid(__TopXMLNS, Jid), decode_disco_item_attr_name(__TopXMLNS, Name), decode_disco_item_attr_node(__TopXMLNS, Node)}. encode_disco_item({disco_item, Jid, Name, Node}, _xmlns_attrs) -> _els = [], _attrs = encode_disco_item_attr_node(Node, encode_disco_item_attr_name(Name, encode_disco_item_attr_jid(Jid, _xmlns_attrs))), {xmlel, <<"item">>, _attrs, _els}. decode_disco_item_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"item">>, __TopXMLNS}}); decode_disco_item_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_disco_item_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_disco_item_attr_name(__TopXMLNS, undefined) -> undefined; decode_disco_item_attr_name(__TopXMLNS, _val) -> _val. encode_disco_item_attr_name(undefined, _acc) -> _acc; encode_disco_item_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_disco_item_attr_node(__TopXMLNS, undefined) -> undefined; decode_disco_item_attr_node(__TopXMLNS, _val) -> _val. encode_disco_item_attr_node(undefined, _acc) -> _acc; encode_disco_item_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_disco_info(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> {Xdata, Features, Identities} = decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els, [], [], []), Node = decode_disco_info_attrs(__TopXMLNS, _attrs, undefined), {disco_info, Node, Identities, Features, Xdata}. decode_disco_info_els(__TopXMLNS, __IgnoreEls, [], Xdata, Features, Identities) -> {lists:reverse(Xdata), lists:reverse(Features), lists:reverse(Identities)}; decode_disco_info_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"identity">>, _attrs, _} = _el | _els], Xdata, Features, Identities) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els, Xdata, Features, [decode_disco_identity(__TopXMLNS, __IgnoreEls, _el) | Identities]); true -> decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els, Xdata, Features, Identities) end; decode_disco_info_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"feature">>, _attrs, _} = _el | _els], Xdata, Features, Identities) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els, Xdata, [decode_disco_feature(__TopXMLNS, __IgnoreEls, _el) | Features], Identities); true -> decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els, Xdata, Features, Identities) end; decode_disco_info_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata, Features, Identities) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<"jabber:x:data">> -> decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els, [decode_xdata(_xmlns, __IgnoreEls, _el) | Xdata], Features, Identities); true -> decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els, Xdata, Features, Identities) end; decode_disco_info_els(__TopXMLNS, __IgnoreEls, [_ | _els], Xdata, Features, Identities) -> decode_disco_info_els(__TopXMLNS, __IgnoreEls, _els, Xdata, Features, Identities). decode_disco_info_attrs(__TopXMLNS, [{<<"node">>, _val} | _attrs], _Node) -> decode_disco_info_attrs(__TopXMLNS, _attrs, _val); decode_disco_info_attrs(__TopXMLNS, [_ | _attrs], Node) -> decode_disco_info_attrs(__TopXMLNS, _attrs, Node); decode_disco_info_attrs(__TopXMLNS, [], Node) -> decode_disco_info_attr_node(__TopXMLNS, Node). encode_disco_info({disco_info, Node, Identities, Features, Xdata}, _xmlns_attrs) -> _els = lists:reverse('encode_disco_info_$xdata'(Xdata, 'encode_disco_info_$features'(Features, 'encode_disco_info_$identities'(Identities, [])))), _attrs = encode_disco_info_attr_node(Node, _xmlns_attrs), {xmlel, <<"query">>, _attrs, _els}. 'encode_disco_info_$xdata'([], _acc) -> _acc; 'encode_disco_info_$xdata'([Xdata | _els], _acc) -> 'encode_disco_info_$xdata'(_els, [encode_xdata(Xdata, [{<<"xmlns">>, <<"jabber:x:data">>}]) | _acc]). 'encode_disco_info_$features'([], _acc) -> _acc; 'encode_disco_info_$features'([Features | _els], _acc) -> 'encode_disco_info_$features'(_els, [encode_disco_feature(Features, []) | _acc]). 'encode_disco_info_$identities'([], _acc) -> _acc; 'encode_disco_info_$identities'([Identities | _els], _acc) -> 'encode_disco_info_$identities'(_els, [encode_disco_identity(Identities, []) | _acc]). decode_disco_info_attr_node(__TopXMLNS, undefined) -> undefined; decode_disco_info_attr_node(__TopXMLNS, _val) -> _val. encode_disco_info_attr_node(undefined, _acc) -> _acc; encode_disco_info_attr_node(_val, _acc) -> [{<<"node">>, _val} | _acc]. decode_disco_feature(__TopXMLNS, __IgnoreEls, {xmlel, <<"feature">>, _attrs, _els}) -> Var = decode_disco_feature_attrs(__TopXMLNS, _attrs, undefined), Var. decode_disco_feature_attrs(__TopXMLNS, [{<<"var">>, _val} | _attrs], _Var) -> decode_disco_feature_attrs(__TopXMLNS, _attrs, _val); decode_disco_feature_attrs(__TopXMLNS, [_ | _attrs], Var) -> decode_disco_feature_attrs(__TopXMLNS, _attrs, Var); decode_disco_feature_attrs(__TopXMLNS, [], Var) -> decode_disco_feature_attr_var(__TopXMLNS, Var). encode_disco_feature(Var, _xmlns_attrs) -> _els = [], _attrs = encode_disco_feature_attr_var(Var, _xmlns_attrs), {xmlel, <<"feature">>, _attrs, _els}. decode_disco_feature_attr_var(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"var">>, <<"feature">>, __TopXMLNS}}); decode_disco_feature_attr_var(__TopXMLNS, _val) -> _val. encode_disco_feature_attr_var(_val, _acc) -> [{<<"var">>, _val} | _acc]. decode_disco_identity(__TopXMLNS, __IgnoreEls, {xmlel, <<"identity">>, _attrs, _els}) -> {Category, Type, Lang, Name} = decode_disco_identity_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined), {identity, Category, Type, Lang, Name}. decode_disco_identity_attrs(__TopXMLNS, [{<<"category">>, _val} | _attrs], _Category, Type, Lang, Name) -> decode_disco_identity_attrs(__TopXMLNS, _attrs, _val, Type, Lang, Name); decode_disco_identity_attrs(__TopXMLNS, [{<<"type">>, _val} | _attrs], Category, _Type, Lang, Name) -> decode_disco_identity_attrs(__TopXMLNS, _attrs, Category, _val, Lang, Name); decode_disco_identity_attrs(__TopXMLNS, [{<<"xml:lang">>, _val} | _attrs], Category, Type, _Lang, Name) -> decode_disco_identity_attrs(__TopXMLNS, _attrs, Category, Type, _val, Name); decode_disco_identity_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], Category, Type, Lang, _Name) -> decode_disco_identity_attrs(__TopXMLNS, _attrs, Category, Type, Lang, _val); decode_disco_identity_attrs(__TopXMLNS, [_ | _attrs], Category, Type, Lang, Name) -> decode_disco_identity_attrs(__TopXMLNS, _attrs, Category, Type, Lang, Name); decode_disco_identity_attrs(__TopXMLNS, [], Category, Type, Lang, Name) -> {decode_disco_identity_attr_category(__TopXMLNS, Category), decode_disco_identity_attr_type(__TopXMLNS, Type), 'decode_disco_identity_attr_xml:lang'(__TopXMLNS, Lang), decode_disco_identity_attr_name(__TopXMLNS, Name)}. encode_disco_identity({identity, Category, Type, Lang, Name}, _xmlns_attrs) -> _els = [], _attrs = encode_disco_identity_attr_name(Name, 'encode_disco_identity_attr_xml:lang'(Lang, encode_disco_identity_attr_type(Type, encode_disco_identity_attr_category(Category, _xmlns_attrs)))), {xmlel, <<"identity">>, _attrs, _els}. decode_disco_identity_attr_category(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"category">>, <<"identity">>, __TopXMLNS}}); decode_disco_identity_attr_category(__TopXMLNS, _val) -> _val. encode_disco_identity_attr_category(_val, _acc) -> [{<<"category">>, _val} | _acc]. decode_disco_identity_attr_type(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"type">>, <<"identity">>, __TopXMLNS}}); decode_disco_identity_attr_type(__TopXMLNS, _val) -> _val. encode_disco_identity_attr_type(_val, _acc) -> [{<<"type">>, _val} | _acc]. 'decode_disco_identity_attr_xml:lang'(__TopXMLNS, undefined) -> undefined; 'decode_disco_identity_attr_xml:lang'(__TopXMLNS, _val) -> _val. 'encode_disco_identity_attr_xml:lang'(undefined, _acc) -> _acc; 'encode_disco_identity_attr_xml:lang'(_val, _acc) -> [{<<"xml:lang">>, _val} | _acc]. decode_disco_identity_attr_name(__TopXMLNS, undefined) -> undefined; decode_disco_identity_attr_name(__TopXMLNS, _val) -> _val. encode_disco_identity_attr_name(undefined, _acc) -> _acc; encode_disco_identity_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_block_list(__TopXMLNS, __IgnoreEls, {xmlel, <<"blocklist">>, _attrs, _els}) -> {block_list}. encode_block_list({block_list}, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"blocklist">>, _attrs, _els}. decode_unblock(__TopXMLNS, __IgnoreEls, {xmlel, <<"unblock">>, _attrs, _els}) -> Items = decode_unblock_els(__TopXMLNS, __IgnoreEls, _els, []), {unblock, Items}. decode_unblock_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_unblock_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_unblock_els(__TopXMLNS, __IgnoreEls, _els, case decode_block_item(__TopXMLNS, __IgnoreEls, _el) of undefined -> Items; _new_el -> [_new_el | Items] end); true -> decode_unblock_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_unblock_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_unblock_els(__TopXMLNS, __IgnoreEls, _els, Items). encode_unblock({unblock, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_unblock_$items'(Items, [])), _attrs = _xmlns_attrs, {xmlel, <<"unblock">>, _attrs, _els}. 'encode_unblock_$items'([], _acc) -> _acc; 'encode_unblock_$items'([Items | _els], _acc) -> 'encode_unblock_$items'(_els, [encode_block_item(Items, []) | _acc]). decode_block(__TopXMLNS, __IgnoreEls, {xmlel, <<"block">>, _attrs, _els}) -> Items = decode_block_els(__TopXMLNS, __IgnoreEls, _els, []), {block, Items}. decode_block_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_block_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_block_els(__TopXMLNS, __IgnoreEls, _els, case decode_block_item(__TopXMLNS, __IgnoreEls, _el) of undefined -> Items; _new_el -> [_new_el | Items] end); true -> decode_block_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_block_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_block_els(__TopXMLNS, __IgnoreEls, _els, Items). encode_block({block, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_block_$items'(Items, [])), _attrs = _xmlns_attrs, {xmlel, <<"block">>, _attrs, _els}. 'encode_block_$items'([], _acc) -> _acc; 'encode_block_$items'([Items | _els], _acc) -> 'encode_block_$items'(_els, [encode_block_item(Items, []) | _acc]). decode_block_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> Jid = decode_block_item_attrs(__TopXMLNS, _attrs, undefined), Jid. decode_block_item_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid) -> decode_block_item_attrs(__TopXMLNS, _attrs, _val); decode_block_item_attrs(__TopXMLNS, [_ | _attrs], Jid) -> decode_block_item_attrs(__TopXMLNS, _attrs, Jid); decode_block_item_attrs(__TopXMLNS, [], Jid) -> decode_block_item_attr_jid(__TopXMLNS, Jid). encode_block_item(Jid, _xmlns_attrs) -> _els = [], _attrs = encode_block_item_attr_jid(Jid, _xmlns_attrs), {xmlel, <<"item">>, _attrs, _els}. decode_block_item_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"item">>, __TopXMLNS}}); decode_block_item_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_block_item_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_privacy(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> {Lists, Default, Active} = decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, [], undefined, undefined), {privacy, Lists, Default, Active}. decode_privacy_els(__TopXMLNS, __IgnoreEls, [], Lists, Default, Active) -> {lists:reverse(Lists), Default, Active}; decode_privacy_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"list">>, _attrs, _} = _el | _els], Lists, Default, Active) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, [decode_privacy_list(__TopXMLNS, __IgnoreEls, _el) | Lists], Default, Active); true -> decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists, Default, Active) end; decode_privacy_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"default">>, _attrs, _} = _el | _els], Lists, Default, Active) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists, decode_privacy_default_list(__TopXMLNS, __IgnoreEls, _el), Active); true -> decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists, Default, Active) end; decode_privacy_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"active">>, _attrs, _} = _el | _els], Lists, Default, Active) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists, Default, decode_privacy_active_list(__TopXMLNS, __IgnoreEls, _el)); true -> decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists, Default, Active) end; decode_privacy_els(__TopXMLNS, __IgnoreEls, [_ | _els], Lists, Default, Active) -> decode_privacy_els(__TopXMLNS, __IgnoreEls, _els, Lists, Default, Active). encode_privacy({privacy, Lists, Default, Active}, _xmlns_attrs) -> _els = lists:reverse('encode_privacy_$lists'(Lists, 'encode_privacy_$default'(Default, 'encode_privacy_$active'(Active, [])))), _attrs = _xmlns_attrs, {xmlel, <<"query">>, _attrs, _els}. 'encode_privacy_$lists'([], _acc) -> _acc; 'encode_privacy_$lists'([Lists | _els], _acc) -> 'encode_privacy_$lists'(_els, [encode_privacy_list(Lists, []) | _acc]). 'encode_privacy_$default'(undefined, _acc) -> _acc; 'encode_privacy_$default'(Default, _acc) -> [encode_privacy_default_list(Default, []) | _acc]. 'encode_privacy_$active'(undefined, _acc) -> _acc; 'encode_privacy_$active'(Active, _acc) -> [encode_privacy_active_list(Active, []) | _acc]. decode_privacy_active_list(__TopXMLNS, __IgnoreEls, {xmlel, <<"active">>, _attrs, _els}) -> Name = decode_privacy_active_list_attrs(__TopXMLNS, _attrs, undefined), Name. decode_privacy_active_list_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], _Name) -> decode_privacy_active_list_attrs(__TopXMLNS, _attrs, _val); decode_privacy_active_list_attrs(__TopXMLNS, [_ | _attrs], Name) -> decode_privacy_active_list_attrs(__TopXMLNS, _attrs, Name); decode_privacy_active_list_attrs(__TopXMLNS, [], Name) -> decode_privacy_active_list_attr_name(__TopXMLNS, Name). encode_privacy_active_list(Name, _xmlns_attrs) -> _els = [], _attrs = encode_privacy_active_list_attr_name(Name, _xmlns_attrs), {xmlel, <<"active">>, _attrs, _els}. decode_privacy_active_list_attr_name(__TopXMLNS, undefined) -> none; decode_privacy_active_list_attr_name(__TopXMLNS, _val) -> _val. encode_privacy_active_list_attr_name(none, _acc) -> _acc; encode_privacy_active_list_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_privacy_default_list(__TopXMLNS, __IgnoreEls, {xmlel, <<"default">>, _attrs, _els}) -> Name = decode_privacy_default_list_attrs(__TopXMLNS, _attrs, undefined), Name. decode_privacy_default_list_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], _Name) -> decode_privacy_default_list_attrs(__TopXMLNS, _attrs, _val); decode_privacy_default_list_attrs(__TopXMLNS, [_ | _attrs], Name) -> decode_privacy_default_list_attrs(__TopXMLNS, _attrs, Name); decode_privacy_default_list_attrs(__TopXMLNS, [], Name) -> decode_privacy_default_list_attr_name(__TopXMLNS, Name). encode_privacy_default_list(Name, _xmlns_attrs) -> _els = [], _attrs = encode_privacy_default_list_attr_name(Name, _xmlns_attrs), {xmlel, <<"default">>, _attrs, _els}. decode_privacy_default_list_attr_name(__TopXMLNS, undefined) -> none; decode_privacy_default_list_attr_name(__TopXMLNS, _val) -> _val. encode_privacy_default_list_attr_name(none, _acc) -> _acc; encode_privacy_default_list_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_privacy_list(__TopXMLNS, __IgnoreEls, {xmlel, <<"list">>, _attrs, _els}) -> Items = decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els, []), Name = decode_privacy_list_attrs(__TopXMLNS, _attrs, undefined), {privacy_list, Name, Items}. decode_privacy_list_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_privacy_list_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els, [decode_privacy_item(__TopXMLNS, __IgnoreEls, _el) | Items]); true -> decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_privacy_list_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_privacy_list_els(__TopXMLNS, __IgnoreEls, _els, Items). decode_privacy_list_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], _Name) -> decode_privacy_list_attrs(__TopXMLNS, _attrs, _val); decode_privacy_list_attrs(__TopXMLNS, [_ | _attrs], Name) -> decode_privacy_list_attrs(__TopXMLNS, _attrs, Name); decode_privacy_list_attrs(__TopXMLNS, [], Name) -> decode_privacy_list_attr_name(__TopXMLNS, Name). encode_privacy_list({privacy_list, Name, Items}, _xmlns_attrs) -> _els = lists:reverse('encode_privacy_list_$items'(Items, [])), _attrs = encode_privacy_list_attr_name(Name, _xmlns_attrs), {xmlel, <<"list">>, _attrs, _els}. 'encode_privacy_list_$items'([], _acc) -> _acc; 'encode_privacy_list_$items'([Items | _els], _acc) -> 'encode_privacy_list_$items'(_els, [encode_privacy_item(Items, []) | _acc]). decode_privacy_list_attr_name(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"name">>, <<"list">>, __TopXMLNS}}); decode_privacy_list_attr_name(__TopXMLNS, _val) -> _val. encode_privacy_list_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_privacy_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> Kinds = decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, []), {Action, Order, Type, Value} = decode_privacy_item_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined), {privacy_item, Order, Action, Type, Value, Kinds}. decode_privacy_item_els(__TopXMLNS, __IgnoreEls, [], Kinds) -> lists:reverse(Kinds); decode_privacy_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"message">>, _attrs, _} = _el | _els], Kinds) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds); true -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds) end; decode_privacy_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"iq">>, _attrs, _} = _el | _els], Kinds) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds); true -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds) end; decode_privacy_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"presence-in">>, _attrs, _} = _el | _els], Kinds) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds); true -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds) end; decode_privacy_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"presence-out">>, _attrs, _} = _el | _els], Kinds) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds); true -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds) end; decode_privacy_item_els(__TopXMLNS, __IgnoreEls, [_ | _els], Kinds) -> decode_privacy_item_els(__TopXMLNS, __IgnoreEls, _els, Kinds). decode_privacy_item_attrs(__TopXMLNS, [{<<"action">>, _val} | _attrs], _Action, Order, Type, Value) -> decode_privacy_item_attrs(__TopXMLNS, _attrs, _val, Order, Type, Value); decode_privacy_item_attrs(__TopXMLNS, [{<<"order">>, _val} | _attrs], Action, _Order, Type, Value) -> decode_privacy_item_attrs(__TopXMLNS, _attrs, Action, _val, Type, Value); decode_privacy_item_attrs(__TopXMLNS, [{<<"type">>, _val} | _attrs], Action, Order, _Type, Value) -> decode_privacy_item_attrs(__TopXMLNS, _attrs, Action, Order, _val, Value); decode_privacy_item_attrs(__TopXMLNS, [{<<"value">>, _val} | _attrs], Action, Order, Type, _Value) -> decode_privacy_item_attrs(__TopXMLNS, _attrs, Action, Order, Type, _val); decode_privacy_item_attrs(__TopXMLNS, [_ | _attrs], Action, Order, Type, Value) -> decode_privacy_item_attrs(__TopXMLNS, _attrs, Action, Order, Type, Value); decode_privacy_item_attrs(__TopXMLNS, [], Action, Order, Type, Value) -> {decode_privacy_item_attr_action(__TopXMLNS, Action), decode_privacy_item_attr_order(__TopXMLNS, Order), decode_privacy_item_attr_type(__TopXMLNS, Type), decode_privacy_item_attr_value(__TopXMLNS, Value)}. encode_privacy_item({privacy_item, Order, Action, Type, Value, Kinds}, _xmlns_attrs) -> _els = lists:reverse('encode_privacy_item_$kinds'(Kinds, [])), _attrs = encode_privacy_item_attr_value(Value, encode_privacy_item_attr_type(Type, encode_privacy_item_attr_order(Order, encode_privacy_item_attr_action(Action, _xmlns_attrs)))), {xmlel, <<"item">>, _attrs, _els}. 'encode_privacy_item_$kinds'([], _acc) -> _acc; 'encode_privacy_item_$kinds'([message = Kinds | _els], _acc) -> 'encode_privacy_item_$kinds'(_els, [encode_privacy_message(Kinds, []) | _acc]); 'encode_privacy_item_$kinds'([iq = Kinds | _els], _acc) -> 'encode_privacy_item_$kinds'(_els, [encode_privacy_iq(Kinds, []) | _acc]); 'encode_privacy_item_$kinds'(['presence-in' = Kinds | _els], _acc) -> 'encode_privacy_item_$kinds'(_els, [encode_privacy_presence_in(Kinds, []) | _acc]); 'encode_privacy_item_$kinds'(['presence-out' = Kinds | _els], _acc) -> 'encode_privacy_item_$kinds'(_els, [encode_privacy_presence_out(Kinds, []) | _acc]). decode_privacy_item_attr_action(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"action">>, <<"item">>, __TopXMLNS}}); decode_privacy_item_attr_action(__TopXMLNS, _val) -> case catch dec_enum(_val, [allow, deny]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"action">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_privacy_item_attr_action(_val, _acc) -> [{<<"action">>, enc_enum(_val)} | _acc]. decode_privacy_item_attr_order(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"order">>, <<"item">>, __TopXMLNS}}); decode_privacy_item_attr_order(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"order">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_privacy_item_attr_order(_val, _acc) -> [{<<"order">>, enc_int(_val)} | _acc]. decode_privacy_item_attr_type(__TopXMLNS, undefined) -> undefined; decode_privacy_item_attr_type(__TopXMLNS, _val) -> case catch dec_enum(_val, [group, jid, subscription]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"type">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_privacy_item_attr_type(undefined, _acc) -> _acc; encode_privacy_item_attr_type(_val, _acc) -> [{<<"type">>, enc_enum(_val)} | _acc]. decode_privacy_item_attr_value(__TopXMLNS, undefined) -> undefined; decode_privacy_item_attr_value(__TopXMLNS, _val) -> _val. encode_privacy_item_attr_value(undefined, _acc) -> _acc; encode_privacy_item_attr_value(_val, _acc) -> [{<<"value">>, _val} | _acc]. decode_privacy_presence_out(__TopXMLNS, __IgnoreEls, {xmlel, <<"presence-out">>, _attrs, _els}) -> 'presence-out'. encode_privacy_presence_out('presence-out', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"presence-out">>, _attrs, _els}. decode_privacy_presence_in(__TopXMLNS, __IgnoreEls, {xmlel, <<"presence-in">>, _attrs, _els}) -> 'presence-in'. encode_privacy_presence_in('presence-in', _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"presence-in">>, _attrs, _els}. decode_privacy_iq(__TopXMLNS, __IgnoreEls, {xmlel, <<"iq">>, _attrs, _els}) -> iq. encode_privacy_iq(iq, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"iq">>, _attrs, _els}. decode_privacy_message(__TopXMLNS, __IgnoreEls, {xmlel, <<"message">>, _attrs, _els}) -> message. encode_privacy_message(message, _xmlns_attrs) -> _els = [], _attrs = _xmlns_attrs, {xmlel, <<"message">>, _attrs, _els}. decode_roster(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> Items = decode_roster_els(__TopXMLNS, __IgnoreEls, _els, []), Ver = decode_roster_attrs(__TopXMLNS, _attrs, undefined), {roster, Items, Ver}. decode_roster_els(__TopXMLNS, __IgnoreEls, [], Items) -> lists:reverse(Items); decode_roster_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_roster_els(__TopXMLNS, __IgnoreEls, _els, [decode_roster_item(__TopXMLNS, __IgnoreEls, _el) | Items]); true -> decode_roster_els(__TopXMLNS, __IgnoreEls, _els, Items) end; decode_roster_els(__TopXMLNS, __IgnoreEls, [_ | _els], Items) -> decode_roster_els(__TopXMLNS, __IgnoreEls, _els, Items). decode_roster_attrs(__TopXMLNS, [{<<"ver">>, _val} | _attrs], _Ver) -> decode_roster_attrs(__TopXMLNS, _attrs, _val); decode_roster_attrs(__TopXMLNS, [_ | _attrs], Ver) -> decode_roster_attrs(__TopXMLNS, _attrs, Ver); decode_roster_attrs(__TopXMLNS, [], Ver) -> decode_roster_attr_ver(__TopXMLNS, Ver). encode_roster({roster, Items, Ver}, _xmlns_attrs) -> _els = lists:reverse('encode_roster_$items'(Items, [])), _attrs = encode_roster_attr_ver(Ver, _xmlns_attrs), {xmlel, <<"query">>, _attrs, _els}. 'encode_roster_$items'([], _acc) -> _acc; 'encode_roster_$items'([Items | _els], _acc) -> 'encode_roster_$items'(_els, [encode_roster_item(Items, []) | _acc]). decode_roster_attr_ver(__TopXMLNS, undefined) -> undefined; decode_roster_attr_ver(__TopXMLNS, _val) -> _val. encode_roster_attr_ver(undefined, _acc) -> _acc; encode_roster_attr_ver(_val, _acc) -> [{<<"ver">>, _val} | _acc]. decode_roster_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> Groups = decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els, []), {Jid, Name, Subscription, Ask} = decode_roster_item_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined, undefined), {roster_item, Jid, Name, Groups, Subscription, Ask}. decode_roster_item_els(__TopXMLNS, __IgnoreEls, [], Groups) -> lists:reverse(Groups); decode_roster_item_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"group">>, _attrs, _} = _el | _els], Groups) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els, [decode_roster_group(__TopXMLNS, __IgnoreEls, _el) | Groups]); true -> decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els, Groups) end; decode_roster_item_els(__TopXMLNS, __IgnoreEls, [_ | _els], Groups) -> decode_roster_item_els(__TopXMLNS, __IgnoreEls, _els, Groups). decode_roster_item_attrs(__TopXMLNS, [{<<"jid">>, _val} | _attrs], _Jid, Name, Subscription, Ask) -> decode_roster_item_attrs(__TopXMLNS, _attrs, _val, Name, Subscription, Ask); decode_roster_item_attrs(__TopXMLNS, [{<<"name">>, _val} | _attrs], Jid, _Name, Subscription, Ask) -> decode_roster_item_attrs(__TopXMLNS, _attrs, Jid, _val, Subscription, Ask); decode_roster_item_attrs(__TopXMLNS, [{<<"subscription">>, _val} | _attrs], Jid, Name, _Subscription, Ask) -> decode_roster_item_attrs(__TopXMLNS, _attrs, Jid, Name, _val, Ask); decode_roster_item_attrs(__TopXMLNS, [{<<"ask">>, _val} | _attrs], Jid, Name, Subscription, _Ask) -> decode_roster_item_attrs(__TopXMLNS, _attrs, Jid, Name, Subscription, _val); decode_roster_item_attrs(__TopXMLNS, [_ | _attrs], Jid, Name, Subscription, Ask) -> decode_roster_item_attrs(__TopXMLNS, _attrs, Jid, Name, Subscription, Ask); decode_roster_item_attrs(__TopXMLNS, [], Jid, Name, Subscription, Ask) -> {decode_roster_item_attr_jid(__TopXMLNS, Jid), decode_roster_item_attr_name(__TopXMLNS, Name), decode_roster_item_attr_subscription(__TopXMLNS, Subscription), decode_roster_item_attr_ask(__TopXMLNS, Ask)}. encode_roster_item({roster_item, Jid, Name, Groups, Subscription, Ask}, _xmlns_attrs) -> _els = lists:reverse('encode_roster_item_$groups'(Groups, [])), _attrs = encode_roster_item_attr_ask(Ask, encode_roster_item_attr_subscription(Subscription, encode_roster_item_attr_name(Name, encode_roster_item_attr_jid(Jid, _xmlns_attrs)))), {xmlel, <<"item">>, _attrs, _els}. 'encode_roster_item_$groups'([], _acc) -> _acc; 'encode_roster_item_$groups'([Groups | _els], _acc) -> 'encode_roster_item_$groups'(_els, [encode_roster_group(Groups, []) | _acc]). decode_roster_item_attr_jid(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"jid">>, <<"item">>, __TopXMLNS}}); decode_roster_item_attr_jid(__TopXMLNS, _val) -> case catch dec_jid(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"jid">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_roster_item_attr_jid(_val, _acc) -> [{<<"jid">>, enc_jid(_val)} | _acc]. decode_roster_item_attr_name(__TopXMLNS, undefined) -> undefined; decode_roster_item_attr_name(__TopXMLNS, _val) -> _val. encode_roster_item_attr_name(undefined, _acc) -> _acc; encode_roster_item_attr_name(_val, _acc) -> [{<<"name">>, _val} | _acc]. decode_roster_item_attr_subscription(__TopXMLNS, undefined) -> none; decode_roster_item_attr_subscription(__TopXMLNS, _val) -> case catch dec_enum(_val, [none, to, from, both, remove]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"subscription">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_roster_item_attr_subscription(none, _acc) -> _acc; encode_roster_item_attr_subscription(_val, _acc) -> [{<<"subscription">>, enc_enum(_val)} | _acc]. decode_roster_item_attr_ask(__TopXMLNS, undefined) -> undefined; decode_roster_item_attr_ask(__TopXMLNS, _val) -> case catch dec_enum(_val, [subscribe]) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"ask">>, <<"item">>, __TopXMLNS}}); _res -> _res end. encode_roster_item_attr_ask(undefined, _acc) -> _acc; encode_roster_item_attr_ask(_val, _acc) -> [{<<"ask">>, enc_enum(_val)} | _acc]. decode_roster_group(__TopXMLNS, __IgnoreEls, {xmlel, <<"group">>, _attrs, _els}) -> Cdata = decode_roster_group_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_roster_group_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_roster_group_cdata(__TopXMLNS, Cdata); decode_roster_group_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_roster_group_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_roster_group_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_roster_group_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_roster_group(Cdata, _xmlns_attrs) -> _els = encode_roster_group_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"group">>, _attrs, _els}. decode_roster_group_cdata(__TopXMLNS, <<>>) -> erlang:error({xmpp_codec, {missing_cdata, <<>>, <<"group">>, __TopXMLNS}}); decode_roster_group_cdata(__TopXMLNS, _val) -> _val. encode_roster_group_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_version(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> {Ver, Os, Name} = decode_version_els(__TopXMLNS, __IgnoreEls, _els, undefined, undefined, undefined), {version, Name, Ver, Os}. decode_version_els(__TopXMLNS, __IgnoreEls, [], Ver, Os, Name) -> {Ver, Os, Name}; decode_version_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"name">>, _attrs, _} = _el | _els], Ver, Os, Name) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver, Os, decode_version_name(__TopXMLNS, __IgnoreEls, _el)); true -> decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver, Os, Name) end; decode_version_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"version">>, _attrs, _} = _el | _els], Ver, Os, Name) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_version_els(__TopXMLNS, __IgnoreEls, _els, decode_version_ver(__TopXMLNS, __IgnoreEls, _el), Os, Name); true -> decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver, Os, Name) end; decode_version_els(__TopXMLNS, __IgnoreEls, [{xmlel, <<"os">>, _attrs, _} = _el | _els], Ver, Os, Name) -> _xmlns = get_attr(<<"xmlns">>, _attrs), if _xmlns == <<>>; _xmlns == __TopXMLNS -> decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver, decode_version_os(__TopXMLNS, __IgnoreEls, _el), Name); true -> decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver, Os, Name) end; decode_version_els(__TopXMLNS, __IgnoreEls, [_ | _els], Ver, Os, Name) -> decode_version_els(__TopXMLNS, __IgnoreEls, _els, Ver, Os, Name). encode_version({version, Name, Ver, Os}, _xmlns_attrs) -> _els = lists:reverse('encode_version_$ver'(Ver, 'encode_version_$os'(Os, 'encode_version_$name'(Name, [])))), _attrs = _xmlns_attrs, {xmlel, <<"query">>, _attrs, _els}. 'encode_version_$ver'(undefined, _acc) -> _acc; 'encode_version_$ver'(Ver, _acc) -> [encode_version_ver(Ver, []) | _acc]. 'encode_version_$os'(undefined, _acc) -> _acc; 'encode_version_$os'(Os, _acc) -> [encode_version_os(Os, []) | _acc]. 'encode_version_$name'(undefined, _acc) -> _acc; 'encode_version_$name'(Name, _acc) -> [encode_version_name(Name, []) | _acc]. decode_version_os(__TopXMLNS, __IgnoreEls, {xmlel, <<"os">>, _attrs, _els}) -> Cdata = decode_version_os_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_version_os_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_version_os_cdata(__TopXMLNS, Cdata); decode_version_os_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_version_os_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_version_os_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_version_os_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_version_os(Cdata, _xmlns_attrs) -> _els = encode_version_os_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"os">>, _attrs, _els}. decode_version_os_cdata(__TopXMLNS, <<>>) -> erlang:error({xmpp_codec, {missing_cdata, <<>>, <<"os">>, __TopXMLNS}}); decode_version_os_cdata(__TopXMLNS, _val) -> _val. encode_version_os_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_version_ver(__TopXMLNS, __IgnoreEls, {xmlel, <<"version">>, _attrs, _els}) -> Cdata = decode_version_ver_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_version_ver_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_version_ver_cdata(__TopXMLNS, Cdata); decode_version_ver_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_version_ver_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_version_ver_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_version_ver_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_version_ver(Cdata, _xmlns_attrs) -> _els = encode_version_ver_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"version">>, _attrs, _els}. decode_version_ver_cdata(__TopXMLNS, <<>>) -> erlang:error({xmpp_codec, {missing_cdata, <<>>, <<"version">>, __TopXMLNS}}); decode_version_ver_cdata(__TopXMLNS, _val) -> _val. encode_version_ver_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_version_name(__TopXMLNS, __IgnoreEls, {xmlel, <<"name">>, _attrs, _els}) -> Cdata = decode_version_name_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Cdata. decode_version_name_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> decode_version_name_cdata(__TopXMLNS, Cdata); decode_version_name_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Cdata) -> decode_version_name_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_version_name_els(__TopXMLNS, __IgnoreEls, [_ | _els], Cdata) -> decode_version_name_els(__TopXMLNS, __IgnoreEls, _els, Cdata). encode_version_name(Cdata, _xmlns_attrs) -> _els = encode_version_name_cdata(Cdata, []), _attrs = _xmlns_attrs, {xmlel, <<"name">>, _attrs, _els}. decode_version_name_cdata(__TopXMLNS, <<>>) -> erlang:error({xmpp_codec, {missing_cdata, <<>>, <<"name">>, __TopXMLNS}}); decode_version_name_cdata(__TopXMLNS, _val) -> _val. encode_version_name_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. decode_last(__TopXMLNS, __IgnoreEls, {xmlel, <<"query">>, _attrs, _els}) -> Text = decode_last_els(__TopXMLNS, __IgnoreEls, _els, <<>>), Seconds = decode_last_attrs(__TopXMLNS, _attrs, undefined), {last, Seconds, Text}. decode_last_els(__TopXMLNS, __IgnoreEls, [], Text) -> decode_last_cdata(__TopXMLNS, Text); decode_last_els(__TopXMLNS, __IgnoreEls, [{xmlcdata, _data} | _els], Text) -> decode_last_els(__TopXMLNS, __IgnoreEls, _els, <>); decode_last_els(__TopXMLNS, __IgnoreEls, [_ | _els], Text) -> decode_last_els(__TopXMLNS, __IgnoreEls, _els, Text). decode_last_attrs(__TopXMLNS, [{<<"seconds">>, _val} | _attrs], _Seconds) -> decode_last_attrs(__TopXMLNS, _attrs, _val); decode_last_attrs(__TopXMLNS, [_ | _attrs], Seconds) -> decode_last_attrs(__TopXMLNS, _attrs, Seconds); decode_last_attrs(__TopXMLNS, [], Seconds) -> decode_last_attr_seconds(__TopXMLNS, Seconds). encode_last({last, Seconds, Text}, _xmlns_attrs) -> _els = encode_last_cdata(Text, []), _attrs = encode_last_attr_seconds(Seconds, _xmlns_attrs), {xmlel, <<"query">>, _attrs, _els}. decode_last_attr_seconds(__TopXMLNS, undefined) -> undefined; decode_last_attr_seconds(__TopXMLNS, _val) -> case catch dec_int(_val, 0, infinity) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"seconds">>, <<"query">>, __TopXMLNS}}); _res -> _res end. encode_last_attr_seconds(undefined, _acc) -> _acc; encode_last_attr_seconds(_val, _acc) -> [{<<"seconds">>, enc_int(_val)} | _acc]. decode_last_cdata(__TopXMLNS, <<>>) -> undefined; decode_last_cdata(__TopXMLNS, _val) -> _val. encode_last_cdata(undefined, _acc) -> _acc; encode_last_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. ejabberd-16.01/plugins/0000755000232200023220000000000012645157216015317 5ustar debalancedebalanceejabberd-16.01/plugins/deps_erl_opts.erl0000644000232200023220000000104412645157216020664 0ustar debalancedebalance-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), []}. ejabberd-16.01/test/0000755000232200023220000000000012645157216014615 5ustar debalancedebalanceejabberd-16.01/test/ejabberd_SUITE.erl0000644000232200023220000022570712645157216020045 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov %%% @copyright (C) 2002-2015, ProcessOne %%% @doc %%% %%% @end %%% Created : 2 Jun 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- -module(ejabberd_SUITE). -compile(export_all). -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, 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, make_iq_result/1, start_event_relay/0, stop_event_relay/1, put_event/2, get_event/1, bind/1, auth/1, open_session/1, zlib/1, starttls/1, close_socket/1]). -include("suite.hrl"). suite() -> [{timetrap, {seconds,120}}]. init_per_suite(Config) -> NewConfig = init_config(Config), DataDir = proplists:get_value(data_dir, NewConfig), {ok, CWD} = file:get_cwd(), ExtAuthScript = filename:join([DataDir, "extauth.py"]), LDIFFile = filename:join([DataDir, "ejabberd.ldif"]), {ok, _} = file:copy(ExtAuthScript, filename:join([CWD, "extauth.py"])), {ok, _} = ldap_srv:start(LDIFFile), ok = application:start(ejabberd), NewConfig. end_per_suite(_Config) -> ok. init_per_group(no_db, Config) -> re_register(Config), Config; init_per_group(mnesia, Config) -> mod_muc:shutdown_rooms(?MNESIA_VHOST), set_opt(server, ?MNESIA_VHOST, Config); init_per_group(mysql, Config) -> case catch ejabberd_odbc:sql_query(?MYSQL_VHOST, [<<"select 1;">>]) of {selected, _, _} -> mod_muc:shutdown_rooms(?MYSQL_VHOST), create_sql_tables(mysql, ?config(base_dir, Config)), set_opt(server, ?MYSQL_VHOST, Config); Err -> {skip, {mysql_not_available, Err}} end; init_per_group(pgsql, Config) -> case catch ejabberd_odbc:sql_query(?PGSQL_VHOST, [<<"select 1;">>]) of {selected, _, _} -> mod_muc:shutdown_rooms(?PGSQL_VHOST), create_sql_tables(pgsql, ?config(base_dir, Config)), set_opt(server, ?PGSQL_VHOST, Config); Err -> {skip, {pgsql_not_available, Err}} end; init_per_group(sqlite, Config) -> case catch ejabberd_odbc:sql_query(?SQLITE_VHOST, [<<"select 1;">>]) of {selected, _, _} -> mod_muc:shutdown_rooms(?SQLITE_VHOST), set_opt(server, ?SQLITE_VHOST, Config); Err -> {skip, {sqlite_not_available, Err}} end; init_per_group(ldap, Config) -> set_opt(server, ?LDAP_VHOST, Config); init_per_group(extauth, Config) -> set_opt(server, ?EXTAUTH_VHOST, Config); init_per_group(riak, Config) -> case ejabberd_riak:is_connected() of true -> mod_muc:shutdown_rooms(?RIAK_VHOST), NewConfig = set_opt(server, ?RIAK_VHOST, Config), clear_riak_tables(NewConfig); Err -> {skip, {riak_not_available, Err}} end; init_per_group(_GroupName, Config) -> Pid = start_event_relay(), set_opt(event_relay, Pid, Config). end_per_group(mnesia, _Config) -> ok; end_per_group(mysql, _Config) -> ok; end_per_group(pgsql, _Config) -> ok; end_per_group(sqlite, _Config) -> ok; end_per_group(no_db, _Config) -> ok; end_per_group(ldap, _Config) -> ok; end_per_group(extauth, _Config) -> ok; end_per_group(riak, _Config) -> ok; end_per_group(_GroupName, Config) -> stop_event_relay(Config), ok. init_per_testcase(stop_ejabberd, Config) -> open_session(bind(auth(connect(Config)))); init_per_testcase(TestCase, OrigConfig) -> subscribe_to_events(OrigConfig), Server = ?config(server, OrigConfig), Resource = ?config(resource, OrigConfig), MasterResource = ?config(master_resource, OrigConfig), SlaveResource = ?config(slave_resource, OrigConfig), Test = atom_to_list(TestCase), IsMaster = lists:suffix("_master", Test), IsSlave = lists:suffix("_slave", Test), IsCarbons = lists:prefix("carbons_", Test), User = if IsMaster or IsCarbons -> <<"test_master">>; IsSlave -> <<"test_slave">>; true -> <<"test_single">> end, MyResource = if IsMaster and IsCarbons -> MasterResource; IsSlave and IsCarbons -> SlaveResource; true -> Resource end, Slave = if IsCarbons -> jlib:make_jid(<<"test_master">>, Server, SlaveResource); true -> jlib:make_jid(<<"test_slave">>, Server, Resource) end, Master = if IsCarbons -> jlib:make_jid(<<"test_master">>, Server, MasterResource); true -> jlib:make_jid(<<"test_master">>, Server, Resource) end, Config = set_opt(user, User, set_opt(slave, Slave, set_opt(master, Master, set_opt(resource, MyResource, OrigConfig)))), case TestCase of test_connect -> Config; test_auth -> connect(Config); test_starttls -> connect(Config); test_zlib -> connect(Config); test_register -> connect(Config); auth_md5 -> connect(Config); auth_plain -> connect(Config); test_bind -> auth(connect(Config)); sm_resume -> auth(connect(Config)); test_open_session -> bind(auth(connect(Config))); _ when IsMaster or IsSlave -> Password = ?config(password, Config), ejabberd_auth:try_register(User, Server, Password), open_session(bind(auth(connect(Config)))); _ -> open_session(bind(auth(connect(Config)))) end. end_per_testcase(_TestCase, _Config) -> ok. no_db_tests() -> [{generic, [sequence], [test_connect, test_starttls, test_zlib, test_auth, test_bind, test_open_session, presence, ping, version, time, stats, sm, sm_resume, disco]}, {test_proxy65, [parallel], [proxy65_master, proxy65_slave]}]. db_tests(riak) -> %% No support for mod_pubsub [{single_user, [sequence], [test_register, auth_plain, auth_md5, presence_broadcast, last, roster_get, private, privacy, blocking, vcard, test_unregister]}, {test_muc_register, [sequence], [muc_register_master, muc_register_slave]}, {test_roster_subscribe, [parallel], [roster_subscribe_master, roster_subscribe_slave]}, {test_offline, [sequence], [offline_master, offline_slave]}, {test_muc, [parallel], [muc_master, muc_slave]}, {test_announce, [sequence], [announce_master, announce_slave]}, {test_vcard_xupdate, [parallel], [vcard_xupdate_master, vcard_xupdate_slave]}, {test_roster_remove, [parallel], [roster_remove_master, roster_remove_slave]}]; db_tests(mnesia) -> [{single_user, [sequence], [test_register, auth_plain, auth_md5, presence_broadcast, last, roster_get, roster_ver, private, privacy, blocking, vcard, pubsub, test_unregister]}, {test_muc_register, [sequence], [muc_register_master, muc_register_slave]}, {test_roster_subscribe, [parallel], [roster_subscribe_master, 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], [client_state_master, client_state_slave]}, {test_muc, [parallel], [muc_master, muc_slave]}, {test_announce, [sequence], [announce_master, announce_slave]}, {test_vcard_xupdate, [parallel], [vcard_xupdate_master, vcard_xupdate_slave]}, {test_roster_remove, [parallel], [roster_remove_master, roster_remove_slave]}]; db_tests(_) -> %% No support for carboncopy [{single_user, [sequence], [test_register, auth_plain, auth_md5, presence_broadcast, last, roster_get, roster_ver, private, privacy, blocking, vcard, pubsub, test_unregister]}, {test_muc_register, [sequence], [muc_register_master, muc_register_slave]}, {test_roster_subscribe, [parallel], [roster_subscribe_master, 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], [announce_master, announce_slave]}, {test_vcard_xupdate, [parallel], [vcard_xupdate_master, vcard_xupdate_slave]}, {test_roster_remove, [parallel], [roster_remove_master, roster_remove_slave]}]. ldap_tests() -> [{ldap_tests, [sequence], [test_auth, vcard_get]}]. extauth_tests() -> [{extauth_tests, [sequence], [test_auth, test_unregister]}]. groups() -> [{ldap, [sequence], ldap_tests()}, {extauth, [sequence], extauth_tests()}, {no_db, [sequence], no_db_tests()}, {mnesia, [sequence], db_tests(mnesia)}, {mysql, [sequence], db_tests(mysql)}, {pgsql, [sequence], db_tests(pgsql)}, {sqlite, [sequence], db_tests(sqlite)}, {riak, [sequence], db_tests(riak)}]. all() -> [{group, ldap}, {group, no_db}, {group, mnesia}, {group, mysql}, {group, pgsql}, {group, sqlite}, {group, extauth}, {group, riak}, stop_ejabberd]. stop_ejabberd(Config) -> ok = application:stop(ejabberd), ?recv1(#stream_error{reason = 'system-shutdown'}), ?recv1({xmlstreamend, <<"stream:stream">>}), Config. test_connect(Config) -> disconnect(connect(Config)). test_starttls(Config) -> case ?config(starttls, Config) of true -> disconnect(starttls(Config)); _ -> {skipped, 'starttls_not_available'} end. test_zlib(Config) -> case ?config(compression, Config) of [_|_] = Ms -> case lists:member(<<"zlib">>, Ms) of true -> disconnect(zlib(Config)); false -> {skipped, 'zlib_not_available'} end; _ -> {skipped, 'compression_not_available'} end. test_register(Config) -> case ?config(register, Config) of true -> disconnect(register(Config)); _ -> {skipped, 'registration_not_available'} end. register(Config) -> #iq{type = result, sub_els = [#register{username = none, password = none}]} = send_recv(Config, #iq{type = get, to = server_jid(Config), sub_els = [#register{}]}), #iq{type = result, sub_els = []} = send_recv( Config, #iq{type = set, sub_els = [#register{username = ?config(user, Config), password = ?config(password, Config)}]}), Config. test_unregister(Config) -> case ?config(register, Config) of true -> try_unregister(Config); _ -> {skipped, 'registration_not_available'} end. try_unregister(Config) -> true = is_feature_advertised(Config, ?NS_REGISTER), #iq{type = result, sub_els = []} = send_recv( Config, #iq{type = set, sub_els = [#register{remove = true}]}), ?recv1(#stream_error{reason = conflict}), Config. auth_md5(Config) -> Mechs = ?config(mechs, Config), case lists:member(<<"DIGEST-MD5">>, Mechs) of true -> disconnect(auth_SASL(<<"DIGEST-MD5">>, Config)); false -> disconnect(Config), {skipped, 'DIGEST-MD5_not_available'} end. auth_plain(Config) -> Mechs = ?config(mechs, Config), case lists:member(<<"PLAIN">>, Mechs) of true -> disconnect(auth_SASL(<<"PLAIN">>, Config)); false -> disconnect(Config), {skipped, 'PLAIN_not_available'} end. test_auth(Config) -> disconnect(auth(Config)). test_bind(Config) -> disconnect(bind(Config)). test_open_session(Config) -> disconnect(open_session(Config)). roster_get(Config) -> #iq{type = result, sub_els = [#roster{items = []}]} = send_recv(Config, #iq{type = get, sub_els = [#roster{}]}), disconnect(Config). roster_ver(Config) -> %% Get initial "ver" #iq{type = result, sub_els = [#roster{ver = Ver1, items = []}]} = send_recv(Config, #iq{type = get, sub_els = [#roster{ver = <<"">>}]}), %% Should receive empty IQ-result #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = get, sub_els = [#roster{ver = Ver1}]}), %% 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" ?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, sub_els = [#roster{ver = Ver1}]}), %% Now requesting roster with the newest "ver". Should receive empty IQ. #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = get, sub_els = [#roster{ver = Ver2}]}), disconnect(Config). presence(Config) -> send(Config, #presence{}), JID = my_jid(Config), ?recv1(#presence{from = JID, to = JID}), disconnect(Config). presence_broadcast(Config) -> Feature = <<"p1:tmp:", (randoms:get_string())/binary>>, 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), ServerJID = server_jid(Config), Info = #disco_info{identities = [#identity{category = <<"client">>, type = <<"bot">>, lang = <<"en">>, name = <<"ejabberd_ct">>}], node = Node, features = [Feature]}, Caps = #caps{hash = <<"sha-1">>, node = ?EJABBERD_CT_URI, ver = Ver}, send(Config, #presence{sub_els = [Caps]}), JID = my_jid(Config), %% We receive: %% 1) disco#info iq request for CAPS %% 2) welcome message %% 3) presence broadcast {IQ, _, _} = ?recv3(#iq{type = get, from = ServerJID, sub_els = [#disco_info{node = Node}]}, #message{type = normal}, #presence{from = JID, to = JID}), send(Config, #iq{type = result, id = IQ#iq.id, to = ServerJID, sub_els = [Info]}), %% We're trying to read our feature from ejabberd database %% with exponential back-off as our IQ response may be delayed. [Feature] = lists:foldl( fun(Time, []) -> timer:sleep(Time), mod_caps:get_features( Server, mod_caps:read_caps( [xmpp_codec:encode(Caps)])); (_, Acc) -> Acc end, [], [0, 100, 200, 2000, 5000, 10000]), disconnect(Config). ping(Config) -> true = is_feature_advertised(Config, ?NS_PING), #iq{type = result, sub_els = []} = send_recv( Config, #iq{type = get, sub_els = [#ping{}], to = server_jid(Config)}), disconnect(Config). version(Config) -> true = is_feature_advertised(Config, ?NS_VERSION), #iq{type = result, sub_els = [#version{}]} = send_recv( Config, #iq{type = get, sub_els = [#version{}], to = server_jid(Config)}), disconnect(Config). time(Config) -> true = is_feature_advertised(Config, ?NS_TIME), #iq{type = result, sub_els = [#time{}]} = send_recv(Config, #iq{type = get, sub_els = [#time{}], to = server_jid(Config)}), disconnect(Config). disco(Config) -> true = is_feature_advertised(Config, ?NS_DISCO_INFO), true = is_feature_advertised(Config, ?NS_DISCO_ITEMS), #iq{type = result, sub_els = [#disco_items{items = Items}]} = send_recv( Config, #iq{type = get, sub_els = [#disco_items{}], to = server_jid(Config)}), lists:foreach( fun(#disco_item{jid = JID, node = Node}) -> #iq{type = result} = send_recv(Config, #iq{type = get, to = JID, sub_els = [#disco_info{node = Node}]}) end, Items), disconnect(Config). sm(Config) -> Server = ?config(server, Config), ServerJID = jlib:make_jid(<<"">>, Server, <<"">>), Msg = #message{to = ServerJID, body = [#text{data = <<"body">>}]}, true = ?config(sm, Config), %% Enable the session management with resumption enabled send(Config, #sm_enable{resume = true, xmlns = ?NS_STREAM_MGMT_3}), ?recv1(#sm_enabled{id = ID, resume = true}), %% Initial request; 'h' should be 0. send(Config, #sm_r{xmlns = ?NS_STREAM_MGMT_3}), ?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}), ?recv1(#sm_a{h = 3}), close_socket(Config), {save_config, set_opt(sm_previd, ID, Config)}. sm_resume(Config) -> {sm, SMConfig} = ?config(saved_config, Config), ID = ?config(sm_previd, SMConfig), Server = ?config(server, Config), ServerJID = jlib:make_jid(<<"">>, Server, <<"">>), MyJID = my_jid(Config), Txt = #text{data = <<"body">>}, Msg = #message{from = ServerJID, to = MyJID, body = [Txt]}, %% 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}), ?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). private(Config) -> Conference = #bookmark_conference{name = <<"Some name">>, autojoin = true, jid = jlib:make_jid( <<"some">>, <<"some.conference.org">>, <<>>)}, Storage = #bookmark_storage{conference = [Conference]}, StorageXMLOut = xmpp_codec:encode(Storage), #iq{type = error} = send_recv(Config, #iq{type = get, sub_els = [#private{}], to = server_jid(Config)}), #iq{type = result, sub_els = []} = send_recv( Config, #iq{type = set, sub_els = [#private{xml_els = [StorageXMLOut]}]}), #iq{type = result, sub_els = [#private{xml_els = [StorageXMLIn]}]} = send_recv( Config, #iq{type = get, sub_els = [#private{xml_els = [xmpp_codec:encode( #bookmark_storage{})]}]}), Storage = xmpp_codec:decode(StorageXMLIn), disconnect(Config). last(Config) -> true = is_feature_advertised(Config, ?NS_LAST), #iq{type = result, sub_els = [#last{}]} = send_recv(Config, #iq{type = get, sub_els = [#last{}], to = server_jid(Config)}), disconnect(Config). privacy(Config) -> true = is_feature_advertised(Config, ?NS_PRIVACY), #iq{type = result, sub_els = [#privacy{}]} = send_recv(Config, #iq{type = get, sub_els = [#privacy{}]}), JID = <<"tybalt@example.com">>, I1 = send(Config, #iq{type = set, sub_els = [#privacy{ lists = [#privacy_list{ name = <<"public">>, items = [#privacy_item{ type = jid, order = 3, action = deny, kinds = ['presence-in'], value = JID}]}]}]}), {Push1, _} = ?recv2( #iq{type = set, sub_els = [#privacy{ lists = [#privacy_list{ name = <<"public">>}]}]}, #iq{type = result, id = I1, sub_els = []}), send(Config, make_iq_result(Push1)), #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#privacy{active = <<"public">>}]}), #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#privacy{default = <<"public">>}]}), #iq{type = result, sub_els = [#privacy{default = <<"public">>, active = <<"public">>, lists = [#privacy_list{name = <<"public">>}]}]} = send_recv(Config, #iq{type = get, sub_els = [#privacy{}]}), #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#privacy{default = none}]}), #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#privacy{active = none}]}), I2 = send(Config, #iq{type = set, sub_els = [#privacy{ lists = [#privacy_list{ name = <<"public">>}]}]}), {Push2, _} = ?recv2( #iq{type = set, sub_els = [#privacy{ lists = [#privacy_list{ name = <<"public">>}]}]}, #iq{type = result, id = I2, sub_els = []}), send(Config, make_iq_result(Push2)), disconnect(Config). blocking(Config) -> true = is_feature_advertised(Config, ?NS_BLOCKING), JID = jlib:make_jid(<<"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, sub_els = [#block{items = [JID]}]}), {Push1, Push2, _} = ?recv3( #iq{type = set, sub_els = [#privacy{lists = [#privacy_list{}]}]}, #iq{type = set, sub_els = [#block{items = [JID]}]}, #iq{type = result, id = I1, sub_els = []}), send(Config, make_iq_result(Push1)), send(Config, make_iq_result(Push2)), I2 = send(Config, #iq{type = set, sub_els = [#unblock{items = [JID]}]}), {Push3, Push4, _} = ?recv3( #iq{type = set, sub_els = [#privacy{lists = [#privacy_list{}]}]}, #iq{type = set, sub_els = [#unblock{items = [JID]}]}, #iq{type = result, id = I2, sub_els = []}), send(Config, make_iq_result(Push3)), send(Config, make_iq_result(Push4)), disconnect(Config). vcard(Config) -> true = is_feature_advertised(Config, ?NS_VCARD), VCard = #vcard{fn = <<"Peter Saint-Andre">>, n = #vcard_name{family = <<"Saint-Andre">>, given = <<"Peter">>}, nickname = <<"stpeter">>, bday = <<"1966-08-06">>, adr = [#vcard_adr{work = true, extadd = <<"Suite 600">>, street = <<"1899 Wynkoop Street">>, locality = <<"Denver">>, region = <<"CO">>, pcode = <<"80202">>, ctry = <<"USA">>}, #vcard_adr{home = true, locality = <<"Denver">>, region = <<"CO">>, pcode = <<"80209">>, ctry = <<"USA">>}], tel = [#vcard_tel{work = true,voice = true, number = <<"303-308-3282">>}, #vcard_tel{home = true,voice = true, number = <<"303-555-1212">>}], email = [#vcard_email{internet = true,pref = true, userid = <<"stpeter@jabber.org">>}], jabberid = <<"stpeter@jabber.org">>, title = <<"Executive Director">>,role = <<"Patron Saint">>, org = #vcard_org{name = <<"XMPP Standards Foundation">>}, url = <<"http://www.xmpp.org/xsf/people/stpeter.shtml">>, desc = <<"More information about me is located on my " "personal website: http://www.saint-andre.com/">>}, #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [VCard]}), %% TODO: check if VCard == VCard1. #iq{type = result, sub_els = [_VCard1]} = send_recv(Config, #iq{type = get, sub_els = [#vcard{}]}), disconnect(Config). vcard_get(Config) -> true = is_feature_advertised(Config, ?NS_VCARD), %% TODO: check if VCard corresponds to LDIF data from ejabberd.ldif #iq{type = result, sub_els = [_VCard]} = send_recv(Config, #iq{type = get, sub_els = [#vcard{}]}), disconnect(Config). vcard_xupdate_master(Config) -> Img = <<137, "PNG\r\n", 26, $\n>>, ImgHash = p1_sha:sha(Img), MyJID = my_jid(Config), Peer = ?config(slave, Config), wait_for_slave(Config), send(Config, #presence{}), ?recv2(#presence{from = MyJID, type = undefined}, #presence{from = Peer, type = undefined}), VCard = #vcard{photo = #vcard_photo{type = <<"image/png">>, binval = Img}}, I1 = send(Config, #iq{type = set, sub_els = [VCard]}), ?recv2(#iq{type = result, sub_els = [], id = I1}, #presence{from = MyJID, type = undefined, sub_els = [#vcard_xupdate{photo = ImgHash}]}), I2 = send(Config, #iq{type = set, sub_els = [#vcard{}]}), ?recv3(#iq{type = result, sub_els = [], id = I2}, #presence{from = MyJID, type = undefined, sub_els = [#vcard_xupdate{photo = undefined}]}, #presence{from = Peer, type = unavailable}), disconnect(Config). vcard_xupdate_slave(Config) -> Img = <<137, "PNG\r\n", 26, $\n>>, ImgHash = p1_sha:sha(Img), MyJID = my_jid(Config), Peer = ?config(master, Config), send(Config, #presence{}), ?recv1(#presence{from = MyJID, type = undefined}), wait_for_master(Config), ?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) -> #iq{type = result, sub_els = [#stats{stat = Stats}]} = send_recv(Config, #iq{type = get, sub_els = [#stats{}], to = server_jid(Config)}), lists:foreach( fun(#stat{} = Stat) -> #iq{type = result, sub_els = [_|_]} = send_recv(Config, #iq{type = get, sub_els = [#stats{stat = [Stat]}], to = server_jid(Config)}) end, Stats), disconnect(Config). pubsub(Config) -> Features = get_features(Config, pubsub_jid(Config)), true = lists:member(?NS_PUBSUB, Features), %% Publish element within node "presence" ItemID = randoms:get_string(), Node = <<"presence">>, Item = #pubsub_item{id = ItemID, xml_els = [xmpp_codec:encode(#presence{})]}, #iq{type = result, sub_els = [#pubsub{publish = #pubsub_publish{ node = Node, items = [#pubsub_item{id = ItemID}]}}]} = send_recv(Config, #iq{type = set, to = pubsub_jid(Config), sub_els = [#pubsub{publish = #pubsub_publish{ node = Node, items = [Item]}}]}), %% Subscribe to node "presence" I1 = send(Config, #iq{type = set, to = pubsub_jid(Config), sub_els = [#pubsub{subscribe = #pubsub_subscribe{ node = Node, jid = my_jid(Config)}}]}), ?recv2( #message{sub_els = [#pubsub_event{}, #delay{}]}, #iq{type = result, id = I1}), %% Get subscriptions true = lists:member(?PUBSUB("retrieve-subscriptions"), Features), #iq{type = result, sub_els = [#pubsub{subscriptions = {none, [#pubsub_subscription{node = Node}]}}]} = send_recv(Config, #iq{type = get, to = pubsub_jid(Config), sub_els = [#pubsub{subscriptions = {none, []}}]}), %% Get affiliations true = lists:member(?PUBSUB("retrieve-affiliations"), Features), #iq{type = result, sub_els = [#pubsub{ affiliations = [#pubsub_affiliation{node = Node, type = owner}]}]} = send_recv(Config, #iq{type = get, to = pubsub_jid(Config), sub_els = [#pubsub{affiliations = []}]}), %% Fetching published items from node "presence" #iq{type = result, sub_els = [#pubsub{items = #pubsub_items{ node = Node, items = [Item]}}]} = send_recv(Config, #iq{type = get, to = pubsub_jid(Config), sub_els = [#pubsub{items = #pubsub_items{node = Node}}]}), %% Deleting the item from the node true = lists:member(?PUBSUB("delete-items"), Features), I2 = send(Config, #iq{type = set, to = pubsub_jid(Config), sub_els = [#pubsub{retract = #pubsub_retract{ node = Node, items = [#pubsub_item{id = ItemID}]}}]}), ?recv2( #iq{type = result, id = I2, sub_els = []}, #message{sub_els = [#pubsub_event{ items = [#pubsub_event_items{ node = Node, retract = [ItemID]}]}]}), %% Unsubscribe from node "presence" #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, to = pubsub_jid(Config), sub_els = [#pubsub{unsubscribe = #pubsub_unsubscribe{ node = Node, jid = my_jid(Config)}}]}), disconnect(Config). roster_subscribe_master(Config) -> send(Config, #presence{}), ?recv1(#presence{}), wait_for_slave(Config), Peer = ?config(slave, Config), LPeer = jlib:jid_remove_resource(Peer), send(Config, #presence{type = subscribe, to = LPeer}), Push1 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ ask = subscribe, subscription = none, jid = LPeer}]}]}), send(Config, make_iq_result(Push1)), {Push2, _} = ?recv2( #iq{type = set, sub_els = [#roster{items = [#roster_item{ subscription = to, jid = LPeer}]}]}, #presence{type = subscribed, from = LPeer}), send(Config, make_iq_result(Push2)), ?recv1(#presence{type = undefined, from = Peer}), %% BUG: ejabberd sends previous push again. Is it ok? Push3 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ subscription = to, jid = LPeer}]}]}), send(Config, make_iq_result(Push3)), ?recv1(#presence{type = subscribe, from = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}), Push4 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ subscription = both, jid = LPeer}]}]}), send(Config, make_iq_result(Push4)), %% Move into a group Groups = [<<"A">>, <<"B">>], Item = #roster_item{jid = LPeer, groups = Groups}, I1 = send(Config, #iq{type = set, sub_els = [#roster{items = [Item]}]}), {Push5, _} = ?recv2( #iq{type = set, sub_els = [#roster{items = [#roster_item{ jid = LPeer, subscription = both}]}]}, #iq{type = result, id = I1, sub_els = []}), send(Config, make_iq_result(Push5)), #iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push5, Groups = lists:sort(G1), wait_for_slave(Config), ?recv1(#presence{type = unavailable, from = Peer}), disconnect(Config). roster_subscribe_slave(Config) -> send(Config, #presence{}), ?recv1(#presence{}), wait_for_master(Config), Peer = ?config(master, Config), LPeer = jlib:jid_remove_resource(Peer), ?recv1(#presence{type = subscribe, from = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}), Push1 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ subscription = from, jid = LPeer}]}]}), send(Config, make_iq_result(Push1)), send(Config, #presence{type = subscribe, to = LPeer}), Push2 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ ask = subscribe, subscription = from, jid = LPeer}]}]}), send(Config, make_iq_result(Push2)), {Push3, _} = ?recv2( #iq{type = set, sub_els = [#roster{items = [#roster_item{ subscription = both, jid = LPeer}]}]}, #presence{type = subscribed, from = LPeer}), send(Config, make_iq_result(Push3)), ?recv1(#presence{type = undefined, from = Peer}), wait_for_master(Config), disconnect(Config). roster_remove_master(Config) -> MyJID = my_jid(Config), Peer = ?config(slave, Config), LPeer = jlib:jid_remove_resource(Peer), Groups = [<<"A">>, <<"B">>], wait_for_slave(Config), send(Config, #presence{}), ?recv2(#presence{from = MyJID, type = undefined}, #presence{from = Peer, type = undefined}), %% The peer removed us from its roster. {Push1, Push2, _, _, _} = ?recv5( %% TODO: I guess this can be optimized, we don't need %% to send transient roster push with subscription = 'to'. #iq{type = set, sub_els = [#roster{items = [#roster_item{ jid = LPeer, subscription = to}]}]}, #iq{type = set, sub_els = [#roster{items = [#roster_item{ jid = LPeer, subscription = none}]}]}, #presence{type = unsubscribe, from = LPeer}, #presence{type = unsubscribed, from = LPeer}, #presence{type = unavailable, from = Peer}), send(Config, make_iq_result(Push1)), send(Config, make_iq_result(Push2)), #iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push1, #iq{sub_els = [#roster{items = [#roster_item{groups = G2}]}]} = Push2, Groups = lists:sort(G1), Groups = lists:sort(G2), disconnect(Config). roster_remove_slave(Config) -> MyJID = my_jid(Config), Peer = ?config(master, Config), LPeer = jlib:jid_remove_resource(Peer), send(Config, #presence{}), ?recv1(#presence{from = MyJID, type = undefined}), wait_for_master(Config), ?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]}]}), {Push, _, _} = ?recv3( #iq{type = set, sub_els = [#roster{items = [#roster_item{ jid = LPeer, subscription = remove}]}]}, #iq{type = result, id = I, sub_els = []}, #presence{type = unavailable, from = Peer}), send(Config, make_iq_result(Push)), disconnect(Config). proxy65_master(Config) -> Proxy = proxy_jid(Config), MyJID = my_jid(Config), Peer = ?config(slave, Config), wait_for_slave(Config), send(Config, #presence{}), ?recv1(#presence{from = MyJID, type = undefined}), true = is_feature_advertised(Config, ?NS_BYTESTREAMS, Proxy), #iq{type = result, sub_els = [#bytestreams{hosts = [StreamHost]}]} = send_recv( Config, #iq{type = get, sub_els = [#bytestreams{}], to = Proxy}), SID = randoms:get_string(), Data = crypto:rand_bytes(1024), put_event(Config, {StreamHost, SID, Data}), Socks5 = socks5_connect(StreamHost, {SID, MyJID, Peer}), wait_for_slave(Config), #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, to = Proxy, sub_els = [#bytestreams{activate = Peer, sid = SID}]}), socks5_send(Socks5, Data), %%?recv1(#presence{type = unavailable, from = Peer}), disconnect(Config). proxy65_slave(Config) -> MyJID = my_jid(Config), Peer = ?config(master, Config), send(Config, #presence{}), ?recv1(#presence{from = MyJID, type = undefined}), wait_for_master(Config), {StreamHost, SID, Data} = get_event(Config), Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}), wait_for_master(Config), socks5_recv(Socks5, Data), disconnect(Config). muc_master(Config) -> MyJID = my_jid(Config), PeerJID = ?config(slave, Config), PeerBareJID = jlib:jid_remove_resource(PeerJID), PeerJIDStr = jlib: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), PeerNick = ?config(slave_nick, Config), PeerNickJID = jlib:jid_replace_resource(Room, PeerNick), Subject = ?config(room_subject, Config), Localhost = jlib:make_jid(<<"">>, <<"localhost">>, <<"">>), true = is_feature_advertised(Config, ?NS_MUC, MUC), %% Joining send(Config, #presence{to = MyNickJID, sub_els = [#muc{}]}), %% As per XEP-0045 we MUST receive stanzas in the following order: %% 1. In-room presence from other occupants %% 2. In-room presence from the joining entity itself (so-called "self-presence") %% 3. Room history (if any) %% 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. ?recv1(#presence{ from = MyNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ status_codes = Codes, items = [#muc_item{role = moderator, jid = MyJID, 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), %% Request the configuration #iq{type = result, sub_els = [#muc_owner{config = #xdata{} = RoomCfg}]} = send_recv(Config, #iq{type = get, sub_els = [#muc_owner{}], to = Room}), NewFields = lists:flatmap( fun(#xdata_field{var = Var, values = OrigVals}) -> Vals = case Var of <<"FORM_TYPE">> -> OrigVals; <<"muc#roomconfig_roomname">> -> [<<"Test room">>]; <<"muc#roomconfig_roomdesc">> -> [<<"Trying to break the server">>]; <<"muc#roomconfig_persistentroom">> -> [<<"1">>]; <<"members_by_default">> -> [<<"0">>]; <<"muc#roomconfig_allowvoicerequests">> -> [<<"1">>]; <<"public_list">> -> [<<"1">>]; <<"muc#roomconfig_publicroom">> -> [<<"1">>]; _ -> [] end, if Vals /= [] -> [#xdata_field{values = Vals, var = Var}]; true -> [] end end, RoomCfg#xdata.fields), NewRoomCfg = #xdata{type = submit, fields = NewFields}, 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}]}), ?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}), ?recv1(#message{from = MyNickJID, id = I, type = groupchat, body = [Text]}) end, lists:seq(1, 5)), %% Inviting the peer send(Config, #message{to = Room, type = normal, sub_els = [#muc_user{ invites = [#muc_invite{to = PeerJID}]}]}), %% Peer is joining ?recv1(#presence{from = PeerNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{role = visitor, jid = PeerJID, affiliation = none}]}]}), %% Receiving a voice request ?recv1(#message{from = Room, sub_els = [#xdata{type = form, instructions = [_], fields = VoiceReqFs}]}), %% Approving the voice request ReplyVoiceReqFs = lists:map( fun(#xdata_field{var = Var, values = OrigVals}) -> Vals = case {Var, OrigVals} of {<<"FORM_TYPE">>, [<<"http://jabber.org/protocol/muc#request">>]} -> OrigVals; {<<"muc#role">>, [<<"participant">>]} -> [<<"participant">>]; {<<"muc#jid">>, [PeerJIDStr]} -> [PeerJIDStr]; {<<"muc#roomnick">>, [PeerNick]} -> [PeerNick]; {<<"muc#request_allow">>, [<<"0">>]} -> [<<"1">>] end, #xdata_field{values = Vals, var = Var} end, VoiceReqFs), send(Config, #message{to = Room, sub_els = [#xdata{type = submit, fields = ReplyVoiceReqFs}]}), %% Peer is becoming a participant ?recv1(#presence{from = PeerNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{role = participant, jid = PeerJID, affiliation = none}]}]}), %% Receive private message from the peer ?recv1(#message{from = PeerNickJID, body = [#text{data = Subject}]}), %% Granting membership to the peer and localhost server I1 = send(Config, #iq{type = set, to = Room, sub_els = [#muc_admin{ items = [#muc_item{jid = Localhost, affiliation = member}, #muc_item{nick = PeerNick, jid = PeerBareJID, affiliation = member}]}]}), %% Peer became a member ?recv1(#presence{from = PeerNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{affiliation = member, jid = PeerJID, role = participant}]}]}), %% BUG: We should not receive any sub_els! ?recv1(#iq{type = result, id = I1, sub_els = [_|_]}), %% Receive groupchat message from the peer ?recv1(#message{type = groupchat, from = PeerNickJID, body = [#text{data = Subject}]}), %% Kick the peer I2 = send(Config, #iq{type = set, to = Room, sub_els = [#muc_admin{ items = [#muc_item{nick = PeerNick, role = none}]}]}), %% Got notification the peer is kicked %% 307 -> Inform user that he or she has been kicked from the room ?recv1(#presence{from = PeerNickJID, type = unavailable, sub_els = [#muc_user{ status_codes = [307], items = [#muc_item{affiliation = member, jid = PeerJID, role = none}]}]}), %% BUG: We should not receive any sub_els! ?recv1(#iq{type = result, id = I2, sub_els = [_|_]}), %% Destroying the room I3 = send(Config, #iq{type = set, to = Room, sub_els = [#muc_owner{ destroy = #muc_owner_destroy{ reason = Subject}}]}), %% Kicked off ?recv1(#presence{from = MyNickJID, type = unavailable, sub_els = [#muc_user{items = [#muc_item{role = none, affiliation = none}], destroy = #muc_user_destroy{ reason = Subject}}]}), %% BUG: We should not receive any sub_els! ?recv1(#iq{type = result, id = I3, sub_els = [_|_]}), disconnect(Config). muc_slave(Config) -> MyJID = my_jid(Config), MyBareJID = jlib: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), PeerNick = ?config(master_nick, Config), PeerNickJID = jlib:jid_replace_resource(Room, PeerNick), Subject = ?config(room_subject, Config), Localhost = jlib:make_jid(<<"">>, <<"localhost">>, <<"">>), %% Receive an invite from the peer ?recv1(#message{from = Room, type = normal, sub_els = [#muc_user{invites = [#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, sub_els = [#disco_items{items = [#disco_item{jid = Room}]}]} = send_recv(Config, #iq{type = get, to = MUC, sub_els = [#disco_items{}]}), %% Now check if the peer is in the room. We check this via disco#items #iq{type = result, sub_els = [#disco_items{items = [#disco_item{jid = PeerNickJID, name = PeerNick}]}]} = send_recv(Config, #iq{type = get, to = Room, sub_els = [#disco_items{}]}), %% Now joining send(Config, #presence{to = MyNickJID, sub_els = [#muc{}]}), %% First presence is from the participant, i.e. from the peer ?recv1(#presence{ from = PeerNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ status_codes = [], items = [#muc_item{role = moderator, affiliation = owner}]}]}), %% The next is the self-presence (code 110 means it) ?recv1(#presence{ from = MyNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ status_codes = [110], items = [#muc_item{role = visitor, affiliation = none}]}]}), %% Receive the room subject ?recv1(#message{from = PeerNickJID, type = groupchat, body = [#text{data = Subject}], sub_els = [#delay{}]}), %% Receive MUC history lists:foreach( fun(N) -> Text = #text{data = jlib:integer_to_binary(N)}, ?recv1(#message{from = PeerNickJID, type = groupchat, body = [Text], sub_els = [#delay{}]}) end, lists:seq(1, 5)), %% Sending a voice request VoiceReq = #xdata{ type = submit, fields = [#xdata_field{ var = <<"FORM_TYPE">>, values = [<<"http://jabber.org/protocol/muc#request">>]}, #xdata_field{ var = <<"muc#role">>, type = 'text-single', values = [<<"participant">>]}]}, send(Config, #message{to = Room, sub_els = [VoiceReq]}), %% Becoming a participant ?recv1(#presence{from = MyNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{role = participant, affiliation = none}]}]}), %% Sending private message to the peer send(Config, #message{to = PeerNickJID, body = [#text{data = Subject}]}), %% Becoming a member ?recv1(#presence{from = MyNickJID, sub_els = [#vcard_xupdate{}, #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}]}), %% Receive this message back ?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 ?recv1(#presence{from = MyNickJID, type = unavailable, sub_els = [#muc_user{ status_codes = [307], items = [#muc_item{affiliation = member, role = none}]}]}), disconnect(Config). muc_register_nick(Config, MUC, PrevNick, Nick) -> {Registered, PrevNickVals} = if PrevNick /= <<"">> -> {true, [PrevNick]}; true -> {false, []} end, %% Request register form #iq{type = result, sub_els = [#register{registered = Registered, xdata = #xdata{type = form, fields = FsWithoutNick}}]} = send_recv(Config, #iq{type = get, to = MUC, sub_els = [#register{}]}), %% Check if 'nick' field presents #xdata_field{type = 'text-single', var = <<"nick">>, values = PrevNickVals} = lists:keyfind(<<"nick">>, #xdata_field.var, FsWithoutNick), X = #xdata{type = submit, fields = [#xdata_field{var = <<"nick">>, values = [Nick]}]}, %% Submitting form #iq{type = result, sub_els = [_|_]} = send_recv(Config, #iq{type = set, to = MUC, sub_els = [#register{xdata = X}]}), %% Check if the nick was registered #iq{type = result, sub_els = [#register{registered = true, xdata = #xdata{type = form, fields = FsWithNick}}]} = send_recv(Config, #iq{type = get, to = MUC, sub_els = [#register{}]}), #xdata_field{type = 'text-single', var = <<"nick">>, values = [Nick]} = lists:keyfind(<<"nick">>, #xdata_field.var, FsWithNick). muc_register_master(Config) -> MUC = muc_jid(Config), %% Register nick "master1" muc_register_nick(Config, MUC, <<"">>, <<"master1">>), %% Unregister nick "master1" via jabber:register #iq{type = result, sub_els = [_|_]} = send_recv(Config, #iq{type = set, to = MUC, sub_els = [#register{remove = true}]}), %% Register nick "master2" muc_register_nick(Config, MUC, <<"">>, <<"master2">>), %% Now register nick "master" muc_register_nick(Config, MUC, <<"master2">>, <<"master">>), disconnect(Config). muc_register_slave(Config) -> MUC = muc_jid(Config), %% Trying to register occupied nick "master" X = #xdata{type = submit, fields = [#xdata_field{var = <<"nick">>, values = [<<"master">>]}]}, #iq{type = error} = send_recv(Config, #iq{type = set, to = MUC, sub_els = [#register{xdata = X}]}), disconnect(Config). announce_master(Config) -> MyJID = my_jid(Config), ServerJID = server_jid(Config), MotdJID = jlib:jid_replace_resource(ServerJID, <<"announce/motd">>), MotdText = #text{data = <<"motd">>}, send(Config, #presence{}), ?recv1(#presence{from = MyJID}), %% Set message of the day send(Config, #message{to = MotdJID, body = [MotdText]}), %% Receive this message back ?recv1(#message{from = ServerJID, body = [MotdText]}), disconnect(Config). announce_slave(Config) -> MyJID = my_jid(Config), ServerJID = server_jid(Config), MotdDelJID = jlib:jid_replace_resource(ServerJID, <<"announce/motd/delete">>), MotdText = #text{data = <<"motd">>}, send(Config, #presence{}), ?recv2(#presence{from = MyJID}, #message{from = ServerJID, body = [MotdText]}), %% Delete message of the day send(Config, #message{to = MotdDelJID}), disconnect(Config). offline_master(Config) -> Peer = ?config(slave, Config), LPeer = jlib:jid_remove_resource(Peer), send(Config, #message{to = LPeer, body = [#text{data = <<"body">>}], subject = [#text{data = <<"subject">>}]}), disconnect(Config). offline_slave(Config) -> Peer = ?config(master, Config), send(Config, #presence{}), {_, #message{sub_els = SubEls}} = ?recv2(#presence{}, #message{from = Peer, body = [#text{data = <<"body">>}], subject = [#text{data = <<"subject">>}]}), true = lists:keymember(delay, 1, SubEls), disconnect(Config). carbons_master(Config) -> MyJID = my_jid(Config), MyBareJID = jlib:jid_remove_resource(MyJID), Peer = ?config(slave, Config), Txt = #text{data = <<"body">>}, true = is_feature_advertised(Config, ?NS_CARBONS_2), send(Config, #presence{priority = 10}), ?recv1(#presence{from = MyJID}), wait_for_slave(Config), ?recv1(#presence{from = Peer}), %% Enable carbons #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#carbons_enable{}]}), %% Send a message to bare and full JID send(Config, #message{to = MyBareJID, type = chat, body = [Txt]}), send(Config, #message{to = MyJID, type = chat, body = [Txt]}), send(Config, #message{to = MyBareJID, type = chat, body = [Txt], sub_els = [#carbons_private{}]}), send(Config, #message{to = MyJID, type = chat, body = [Txt], sub_els = [#carbons_private{}]}), %% Receive the messages back ?recv4(#message{from = MyJID, to = MyBareJID, type = chat, body = [Txt], sub_els = []}, #message{from = MyJID, to = MyJID, type = chat, body = [Txt], sub_els = []}, #message{from = MyJID, to = MyBareJID, type = chat, body = [Txt], sub_els = [#carbons_private{}]}, #message{from = MyJID, to = MyJID, type = chat, body = [Txt], sub_els = [#carbons_private{}]}), %% Disable carbons #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#carbons_disable{}]}), wait_for_slave(Config), %% Repeat the same and leave send(Config, #message{to = MyBareJID, type = chat, body = [Txt]}), send(Config, #message{to = MyJID, type = chat, body = [Txt]}), send(Config, #message{to = MyBareJID, type = chat, body = [Txt], sub_els = [#carbons_private{}]}), send(Config, #message{to = MyJID, type = chat, body = [Txt], sub_els = [#carbons_private{}]}), ?recv4(#message{from = MyJID, to = MyBareJID, type = chat, body = [Txt], sub_els = []}, #message{from = MyJID, to = MyJID, type = chat, body = [Txt], sub_els = []}, #message{from = MyJID, to = MyBareJID, type = chat, body = [Txt], sub_els = [#carbons_private{}]}, #message{from = MyJID, to = MyJID, type = chat, body = [Txt], sub_els = [#carbons_private{}]}), disconnect(Config). carbons_slave(Config) -> MyJID = my_jid(Config), MyBareJID = jlib:jid_remove_resource(MyJID), Peer = ?config(master, Config), Txt = #text{data = <<"body">>}, wait_for_master(Config), send(Config, #presence{priority = 5}), ?recv2(#presence{from = MyJID}, #presence{from = Peer}), %% Enable carbons #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#carbons_enable{}]}), %% Receive messages sent by the peer ?recv4( #message{from = MyBareJID, to = MyJID, type = chat, sub_els = [#carbons_sent{ forwarded = #forwarded{ sub_els = [#message{from = Peer, to = MyBareJID, type = chat, body = [Txt]}]}}]}, #message{from = MyBareJID, to = MyJID, type = chat, sub_els = [#carbons_sent{ forwarded = #forwarded{ sub_els = [#message{from = Peer, to = Peer, type = chat, body = [Txt]}]}}]}, #message{from = MyBareJID, to = MyJID, type = chat, sub_els = [#carbons_received{ forwarded = #forwarded{ sub_els = [#message{from = Peer, to = MyBareJID, type = chat, body = [Txt]}]}}]}, #message{from = MyBareJID, to = MyJID, type = chat, sub_els = [#carbons_received{ forwarded = #forwarded{ sub_els = [#message{from = Peer, to = Peer, type = chat, body = [Txt]}]}}]}), %% Disable carbons #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#carbons_disable{}]}), wait_for_master(Config), %% Now we should receive nothing but presence unavailable from the peer ?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), 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) 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 = [#mam_query{xmlns = NS, id = QID}]}); true -> ?recv1(#message{sub_els = [#mam_fin{complete = true, id = QID}]}) end. mam_query_with(Config, JID, NS) -> MyJID = my_jid(Config), Peer = ?config(slave, Config), {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}}, set} end, 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, 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 = [#mam_query{xmlns = NS}]}); true -> ?recv1(#message{sub_els = [#mam_fin{complete = true}]}) 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), Type = case NS of ?NS_MAM_TMP -> get; _ -> set end, %% Get the first 3 items out of 5 I1 = send(Config, #iq{type = Type, 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{ complete = false, 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 = Type, 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{ complete = false, rsm = #rsm_set{ count = 10, first = #rsm_first{data = First}}}]}) end, %% 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 = 3, 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(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{complete = true, rsm = #rsm_set{count = 10}}]}) end, %% Getting the item count. Should be 5 (or 10). I4 = send(Config, #iq{type = Type, 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{ complete = false, 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{complete = false, rsm = #rsm_set{count = 10}}]}) end. client_state_master(Config) -> true = ?config(csi, Config), Peer = ?config(slave, Config), Presence = #presence{to = Peer}, 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, ChatState), %% Should be queued (but see below): send(Config, Presence), %% 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 delivered, as the client is active again: send(Config, ChatState), disconnect(Config). client_state_slave(Config) -> Peer = ?config(master, Config), change_client_state(Config, inactive), wait_for_master(Config), ?recv1(#presence{from = Peer, type = unavailable, sub_els = [#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}]}), disconnect(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, jid = jlib:make_jid( <<"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)]), {ok, Sock} = gen_tcp:connect(binary_to_list(Host), Port, [binary, {active, false}]), Init = <>, InitAck = <>, Req = <>, Resp = <>, gen_tcp:send(Sock, Init), {ok, InitAck} = gen_tcp:recv(Sock, size(InitAck)), gen_tcp:send(Sock, Req), {ok, Resp} = gen_tcp:recv(Sock, size(Resp)), Sock. socks5_send(Sock, Data) -> ok = gen_tcp:send(Sock, Data). socks5_recv(Sock, Data) -> {ok, Data} = gen_tcp:recv(Sock, size(Data)). %%%=================================================================== %%% SQL stuff %%%=================================================================== create_sql_tables(sqlite, _BaseDir) -> ok; create_sql_tables(Type, BaseDir) -> {VHost, File} = case Type of mysql -> {?MYSQL_VHOST, "mysql.sql"}; pgsql -> {?PGSQL_VHOST, "pg.sql"} end, SQLFile = filename:join([BaseDir, "sql", File]), CreationQueries = read_sql_queries(SQLFile), DropTableQueries = drop_table_queries(CreationQueries), case ejabberd_odbc:sql_transaction( VHost, DropTableQueries ++ CreationQueries) of {atomic, ok} -> ok; Err -> ct:fail({failed_to_create_sql_tables, Type, Err}) end. read_sql_queries(File) -> case file:open(File, [read, binary]) of {ok, Fd} -> read_lines(Fd, File, []); Err -> ct:fail({open_file_failed, File, Err}) end. drop_table_queries(Queries) -> lists:foldl( fun(Query, Acc) -> case split(str:to_lower(Query)) of [<<"create">>, <<"table">>, Table|_] -> [<<"DROP TABLE IF EXISTS ", Table/binary, ";">>|Acc]; _ -> Acc end end, [], Queries). read_lines(Fd, File, Acc) -> case file:read_line(Fd) of {ok, Line} -> NewAcc = case str:strip(str:strip(Line, both, $\r), both, $\n) of <<"--", _/binary>> -> Acc; <<>> -> Acc; _ -> [Line|Acc] end, read_lines(Fd, File, NewAcc); eof -> QueryList = str:tokens(list_to_binary(lists:reverse(Acc)), <<";">>), lists:flatmap( fun(Query) -> case str:strip(str:strip(Query, both, $\r), both, $\n) of <<>> -> []; Q -> [<>] end end, QueryList); {error, _} = Err -> ct:fail({read_file_failed, File, Err}) end. split(Data) -> lists:filter( fun(<<>>) -> false; (_) -> true end, re:split(Data, <<"\s">>)). clear_riak_tables(Config) -> User = ?config(user, Config), Server = ?config(server, Config), Room = muc_room_jid(Config), {URoom, SRoom, _} = jlib:jid_tolower(Room), ejabberd_auth:remove_user(User, Server), ejabberd_auth:remove_user(<<"test_slave">>, Server), ejabberd_auth:remove_user(<<"test_master">>, Server), mod_muc:forget_room(Server, URoom, SRoom), ejabberd_riak:delete(muc_registered, {{<<"test_slave">>, Server}, SRoom}), ejabberd_riak:delete(muc_registered, {{<<"test_master">>, Server}, SRoom}), Config. ejabberd-16.01/test/ejabberd_SUITE_data/0000755000232200023220000000000012645157216020315 5ustar debalancedebalanceejabberd-16.01/test/ejabberd_SUITE_data/extauth.py0000755000232200023220000000154712645157216022363 0ustar debalancedebalanceimport sys import struct def read(): (pkt_size,) = struct.unpack('>H', sys.stdin.read(2)) pkt = sys.stdin.read(pkt_size).split(':') cmd = pkt[0] args_num = len(pkt) - 1 if cmd == 'auth' and args_num == 3: write(True) elif cmd == 'isuser' and args_num == 2: write(True) elif cmd == 'setpass' and args_num == 3: write(True) elif cmd == 'tryregister' and args_num == 3: write(True) elif cmd == 'removeuser' and args_num == 2: write(True) elif cmd == 'removeuser3' and args_num == 3: write(True) else: write(False) read() def write(result): if result: sys.stdout.write('\x00\x02\x00\x01') else: sys.stdout.write('\x00\x02\x00\x00') sys.stdout.flush() if __name__ == "__main__": try: read() except struct.error: pass ejabberd-16.01/test/ejabberd_SUITE_data/ejabberd.cfg0000644000232200023220000001455712645157216022550 0ustar debalancedebalance{loglevel, 4}. {hosts, ["localhost", "mnesia.localhost", "mysql.localhost", "pgsql.localhost", "sqlite.localhost", "extauth.localhost", "ldap.localhost"]}. {define_macro, 'CERTFILE', "cert.pem"}. {listen, [ {5222, ejabberd_c2s, [ {access, c2s}, {shaper, c2s_shaper}, starttls, zlib, {certfile, 'CERTFILE'}, {max_stanza_size, 65536} ]}, {5269, ejabberd_s2s_in, [ {shaper, s2s_shaper}, {max_stanza_size, 131072} ]}, {5280, ejabberd_http, [ captcha ]} ]}. {shaper, normal, {maxrate, 1000}}. {shaper, fast, {maxrate, 50000}}. {max_fsm_queue, 1000}. {acl, local, {user_regexp, ""}}. {access, max_user_sessions, [{10, all}]}. {access, max_user_offline_messages, [{5000, admin}, {100, all}]}. {access, local, [{allow, local}]}. {access, c2s, [{deny, blocked}, {allow, all}]}. {access, c2s_shaper, [{none, admin}, {normal, all}]}. {access, s2s_shaper, [{fast, all}]}. {access, announce, [{allow, admin}]}. {access, configure, [{allow, admin}]}. {access, muc_admin, [{allow, admin}]}. {access, muc_create, [{allow, local}]}. {access, muc, [{allow, all}]}. {access, pubsub_createnode, [{allow, local}]}. {access, register, [{allow, all}]}. {registration_timeout, infinity}. {language, "en"}. {modules, [ {mod_adhoc, []}, {mod_configure, []}, {mod_disco, []}, {mod_ping, []}, {mod_proxy65, []}, {mod_register, [ {welcome_message, {"Welcome!", "Hi.\nWelcome to this XMPP server."}} ]}, {mod_stats, []}, {mod_time, []}, {mod_version, []} ]}. {host_config, "localhost", [{auth_method, internal}]}. {host_config, "extauth.localhost", [{auth_method, external}, {extauth_program, "python extauth.py"}]}. {host_config, "mnesia.localhost", [{auth_method, internal}, {{add, modules}, [{mod_announce, [{db_type, internal}]}, {mod_blocking, [{db_type, internal}]}, {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, [{db_type, internal}]}, {mod_vcard, [{db_type, internal}]}]} ]}. {host_config, "mysql.localhost", [{auth_method, odbc}, {odbc_pool_size, 1}, {odbc_server, {mysql, "localhost", "ejabberd_test", "ejabberd_test", "ejabberd_test"}}, {{add, modules}, [{mod_announce, [{db_type, odbc}]}, {mod_blocking, [{db_type, odbc}]}, {mod_caps, [{db_type, odbc}]}, {mod_last, [{db_type, odbc}]}, {mod_muc, [{db_type, odbc}]}, {mod_offline, [{db_type, odbc}]}, {mod_privacy, [{db_type, odbc}]}, {mod_private, [{db_type, odbc}]}, {mod_pubsub, [{db_type, odbc}, {access_createnode, pubsub_createnode}, {ignore_pep_from_offline, true}, {last_item_cache, false}, {plugins, ["flat", "hometree", "pep"]}]}, {mod_roster, [{db_type, odbc}]}, {mod_vcard, [{db_type, odbc}]}]} ]}. {host_config, "pgsql.localhost", [{auth_method, odbc}, {odbc_pool_size, 1}, {odbc_server, {pgsql, "localhost", "ejabberd_test", "ejabberd_test", "ejabberd_test"}}, {{add, modules}, [{mod_announce, [{db_type, odbc}]}, {mod_blocking, [{db_type, odbc}]}, {mod_caps, [{db_type, odbc}]}, {mod_last, [{db_type, odbc}]}, {mod_muc, [{db_type, odbc}]}, {mod_offline, [{db_type, odbc}]}, {mod_privacy, [{db_type, odbc}]}, {mod_private, [{db_type, odbc}]}, {mod_pubsub, [{db_type, odbc}, {access_createnode, pubsub_createnode}, {ignore_pep_from_offline, true}, {last_item_cache, false}, {plugins, ["flat", "hometree", "pep"]}]}, {mod_roster, [{db_type, odbc}]}, {mod_vcard, [{db_type, odbc}]}]} ]}. {host_config, "sqlite.localhost", [{auth_method, odbc}, {odbc_pool_size, 1}, {odbc_server, {sqlite, "/tmp/ejabberd_test.db"}}, {{add, modules}, [{mod_announce, [{db_type, odbc}]}, {mod_blocking, [{db_type, odbc}]}, {mod_caps, [{db_type, odbc}]}, {mod_last, [{db_type, odbc}]}, {mod_muc, [{db_type, odbc}]}, {mod_offline, [{db_type, odbc}]}, {mod_privacy, [{db_type, odbc}]}, {mod_private, [{db_type, odbc}]}, {mod_pubsub, [{db_type, odbc}, {access_createnode, pubsub_createnode}, {ignore_pep_from_offline, true}, {last_item_cache, false}, {plugins, ["flat", "hometree", "pep"]}]}, {mod_roster, [{db_type, odbc}]}, {mod_vcard, [{db_type, odbc}]}]} ]}. {host_config, "ldap.localhost", [{auth_method, ldap}, {ldap_servers, ["localhost"]}, {ldap_port, 1389}, {ldap_rootdn, "cn=admin,dc=localhost"}, {ldap_password, "password"}, {ldap_base, "ou=users,dc=localhost"}, {{add, modules}, [{mod_vcard_ldap, []}]} ]}. %%% Local Variables: %%% mode: erlang %%% End: %%% vim: set filetype=erlang tabstop=8 foldmarker=%%%',%%%. foldmethod=marker: ejabberd-16.01/test/ejabberd_SUITE_data/ejabberd.ldif0000644000232200023220000000123312645157216022712 0ustar debalancedebalancedn: dc=localhost dc: localhost objectclass: dcObject dn: cn=admin,dc=localhost cn: admin objectclass: organizationalRole dn: ou=users,dc=localhost ou: users objectClass: organizationalUnit dn: uid=test_single,ou=users,dc=localhost uid: test_single mail: test_single@localhost objectClass: person jpegPhoto:: /9g= cn: Test Single password: password dn: uid=test_master,ou=users,dc=localhost uid: test_master mail: test_master@localhost objectClass: person jpegPhoto:: /9g= cn: Test Master password: password dn: uid=test_slave,ou=users,dc=localhost uid: test_slave mail: test_slave@localhost objectClass: person jpegPhoto:: /9g= cn: Test Slave password: password ejabberd-16.01/test/ejabberd_SUITE_data/cert.pem0000644000232200023220000000602312645157216021756 0ustar debalancedebalance-----BEGIN CERTIFICATE----- MIIDETCCAcmgAwIBAgIEUbsa1zANBgkqhkiG9w0BAQsFADAAMCIYDzIwMTMwNjE0 MTMzMDAwWhgPMjAyMzA2MTIxMzMwMDhaMAAwggFSMA0GCSqGSIb3DQEBAQUAA4IB PwAwggE6AoIBMQCXdtt12OFu2j8tlF4x2Da/kbxyMxFnovJXHNzpx7CE/cGthAR5 w7Cl92pECog2/d6ryIcjqzzCyCeOVQxIaE3Qz8z6+5UjKh3V/j6CKxcK5g1ER7Qe UgpE00ahHzvOpVANtrkYPGC0SFuTFL+PaylH4HW1xBSc1HD5/w7S1k1pDTz9x8ZC Z7JOb6NoYsz+rnmWYY2HOG6pyAyQBapIjgzCamgTStA6jTSgoXmCri/dZnJpqjZc V6AW7feNmMElhPvL30Cb3QB+9ODjN3pDXRR+Jqilu8ZSrpcvcFHOyKt943id1oC+ Qu8orA0/kVInX7IuV//TciKzcH5FWz75Kb7hORPzH8M2DQcIKqKKVIwNVeJLKmcG RcUGsgTaz2j0JTa6YLJoczuasDWgRMT0goQpAgMBAAGjLzAtMAwGA1UdEwEB/wQC MAAwHQYDVR0OBBYEFBW6Si5OY8NPLagdth/JD8R18WMnMA0GCSqGSIb3DQEBCwUA A4IBMQAPiHxamUumu203pSVwvpWkpgKKOC2EswyFWQbNC6DWQ3LUkiR7MCiFViYt yiIyEh9wtfymWNF9uwaR2nVrJD5mK9Rt7xDiaT5ZOgNjLzmLeYqSlG41mCU1bmqg VbxmI1hvPvv3gQ/+WM0lBC6gPGJbVbzlWAIQ1cmevtL1KqOMveZl3VBPxDJD/K9c Rbrtx2nBKFDEl6hBljz6gsn4o8pxH3CO7qWpgY/MLwqQzEtTKYnaS9ecywNvj+/F ZE4SMoekw6AGRyE14/3i2xW6EmIpxVU4O6ahEFq6r6ZFbdtWnog5vT0y+/tRMgXp kCw8puxT2VsYNeJNOybW1IcyN5yluS/FY8iJokdL1JwvhVBVIWaim+T6iwrva7wC q1E9Nj30F8UbEkbkNqOdC3UlHQW4 -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIIFegIBAAKCATEAl3bbddjhbto/LZReMdg2v5G8cjMRZ6LyVxzc6cewhP3BrYQE ecOwpfdqRAqINv3eq8iHI6s8wsgnjlUMSGhN0M/M+vuVIyod1f4+gisXCuYNREe0 HlIKRNNGoR87zqVQDba5GDxgtEhbkxS/j2spR+B1tcQUnNRw+f8O0tZNaQ08/cfG QmeyTm+jaGLM/q55lmGNhzhuqcgMkAWqSI4MwmpoE0rQOo00oKF5gq4v3WZyaao2 XFegFu33jZjBJYT7y99Am90AfvTg4zd6Q10UfiaopbvGUq6XL3BRzsirfeN4ndaA vkLvKKwNP5FSJ1+yLlf/03Iis3B+RVs++Sm+4TkT8x/DNg0HCCqiilSMDVXiSypn BkXFBrIE2s9o9CU2umCyaHM7mrA1oETE9IKEKQIDAQABAoIBMG8X8a4FbowFLhO7 YD+FC9sFBMhqZpiyLrfwZqReID3bdeRUEYhSHU4OI/ZWF0Tmfh1Xjq992Koxbrn5 7XFqd7DxybJJN0E8kfe0bJrDCjqnNBHh2d3nZLrIkGR7aT2PiSEV5bs+BdwVun0t 2bdS7UtX+l5gvJGvTFJBXtkL8GleGV822Vc5gdIAFkXpOdyPkoTXdpw4qwqBnL8/ TXMYBIgCrXMhEawcNbgPu4iFev2idoU9vXc7ZYD7+8jWB5LJ34cNngguGrnOjLoE 9c3nZy6uYhhMWtcrSsQlrbN5MtY8w2fPH8nhfA651IxXXVxEajd24t2Csttnl7Vz WS5c+oPaWwt67naMrYCWG3q1zWhDqZUAulZR4DzWzGP+idLS/ojCRdTZO9D1O+XP fPi0wJECgZkAxh0rTSMCyrJ3VJqEgSPw3yAa1R9cdrTRvV4vRf13Dh8REaHtWt8W JeT5WLXL7dOii1St1Fgjo82+4iMqx3PQ2eR/1I6dA7Uy71PaSQTCQnupca2Xx8nT 5KcrASBkDAudiKog01eC+zYrW+CbUb9AogMZLJzZinlWQ36pJVkWd9SOv25Eqcv6 zJEmzYKpnow/m8WKNogVGpUCgZkAw7hQxs5VYVLp2XtDqRSmxfJsfsbUVo7tZnSU wmejgeNRs7415ZuT142k7qBImrFdYzFcfh2OZnf6D/VIz4Rl7u5YRYRCha/HOGIy wTe1huDckJ6lH/BkZ/6f9WSzXnNSNeXQY14WymU5V5qYCAdwECSf+xNuBYNwzA7o vOxPE690w3Ox2qghzRjzsBqAMgvqSyKlBpoMckUCgZhyKgD39IL5V5qYcGqHGLUH fzK3OdlItq5e19WaGZPv2Us2w/9JbGEQ+UAPNMQNivWSIPwC77+p9zhWjDlssnrZ 9WkMjhpBNrvhWorhpRJkyWo9jfF3OgEXNJX9kjLVFiRzysYbw8RBC1g1G9ulYfbW 5b4uDTz3JTDmuCi00v+1khGoktySlG80TzjzGKayLNPC6jTZc9XleQKBmA0STUrJ 0wf5+qZMxjsPpwfHZhmde+cACrjyBlFpjJELNpSzmnPoTRpzWlWZnN/AAsWyMUQ3 AyCy2J+iOSeq5wfrITgbWjoFgF+yp0MiTlxgvjpmbg7RBlOvvM0t2ZDwUMhKvf00 9n6z/f1s1MSMgp6BY7HoHUv++FSYllCv06Qz7q9zFajN29wP046qZm9xPkegW7cy KKylAoGYTg94GOWlUTz7Pe9PDrDSFVEAi0LcDmul0ntorvEFDvU2pCRK14gyvl9O IJKVyYcDAqA3uvT+zMAniuf8KXNUCcYeEpfzpT+e2eznhczO8hI14M5U0X0LA8P2 vn0Y+yUWb9Ppu/dcjvaUA+qR/UTHqjAlAr3hFTKRxXFoGwwzTXCXvZGKOnzJRTpj LpjI1RG7Weeoyx/8qDs= -----END RSA PRIVATE KEY----- ejabberd-16.01/test/ejabberd_SUITE_data/ejabberd.yml0000644000232200023220000001762712645157216022613 0ustar debalancedebalancehost_config: "pgsql.localhost": odbc_username: "@@pgsql_user@@" odbc_type: pgsql odbc_server: "@@pgsql_server@@" odbc_port: @@pgsql_port@@ odbc_pool_size: 1 odbc_password: "@@pgsql_pass@@" odbc_database: "@@pgsql_db@@" auth_method: odbc modules: mod_announce: db_type: odbc access: local mod_blocking: [] mod_caps: db_type: odbc mod_last: db_type: odbc mod_muc: db_type: odbc mod_offline: db_type: odbc mod_privacy: db_type: odbc mod_private: db_type: odbc mod_pubsub: db_type: odbc 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: odbc mod_mam: db_type: odbc mod_vcard: db_type: odbc mod_vcard_xupdate: db_type: odbc 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: [] mod_version: [] "sqlite.localhost": odbc_type: sqlite auth_method: odbc modules: mod_announce: db_type: odbc access: local mod_blocking: [] mod_caps: db_type: odbc mod_last: db_type: odbc mod_muc: db_type: odbc mod_offline: db_type: odbc mod_privacy: db_type: odbc mod_private: db_type: odbc mod_pubsub: db_type: odbc 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: odbc mod_mam: db_type: odbc mod_vcard: db_type: odbc mod_vcard_xupdate: db_type: odbc 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: [] mod_version: [] "mysql.localhost": odbc_username: "@@mysql_user@@" odbc_type: mysql odbc_server: "@@mysql_server@@" odbc_port: @@mysql_port@@ odbc_pool_size: 1 odbc_password: "@@mysql_pass@@" odbc_database: "@@mysql_db@@" auth_method: odbc modules: mod_announce: db_type: odbc access: local mod_blocking: [] mod_caps: db_type: odbc mod_last: db_type: odbc mod_muc: db_type: odbc mod_offline: db_type: odbc mod_privacy: db_type: odbc mod_private: db_type: odbc mod_pubsub: db_type: odbc 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: odbc mod_mam: db_type: odbc mod_vcard: db_type: odbc mod_vcard_xupdate: db_type: odbc 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: [] mod_version: [] "mnesia.localhost": auth_method: internal 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: [] mod_version: [] "riak.localhost": auth_method: riak modules: mod_announce: db_type: riak access: local mod_blocking: [] mod_caps: db_type: riak mod_last: db_type: riak mod_muc: db_type: riak mod_offline: db_type: riak mod_privacy: db_type: riak mod_private: db_type: riak mod_roster: versioning: true store_current_id: true db_type: riak mod_vcard: db_type: riak mod_vcard_xupdate: db_type: riak 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: [] mod_version: [] "localhost": auth_method: internal "ldap.localhost": ldap_servers: - "localhost" ldap_rootdn: "cn=admin,dc=localhost" ldap_port: 1389 ldap_password: "password" ldap_base: "ou=users,dc=localhost" auth_method: ldap modules: mod_vcard_ldap: [] 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: [] mod_version: [] "extauth.localhost": extauth_program: "python extauth.py" auth_method: external hosts: - "localhost" - "mnesia.localhost" - "mysql.localhost" - "pgsql.localhost" - "extauth.localhost" - "ldap.localhost" - "riak.localhost" - "sqlite.localhost" access: announce: admin: allow c2s: blocked: deny all: allow c2s_shaper: admin: none all: normal configure: admin: allow local: local: allow max_user_offline_messages: admin: 5000 all: 100 max_user_sessions: all: 10 muc: all: allow muc_admin: admin: allow muc_create: local: allow pubsub_createnode: local: allow register: all: allow s2s_shaper: all: fast acl: local: user_regexp: "" define_macro: CERTFILE: "cert.pem" language: "en" listen: - port: @@c2s_port@@ module: ejabberd_c2s max_stanza_size: 65536 certfile: CERTFILE zlib: true starttls: true shaper: c2s_shaper access: c2s - port: @@s2s_port@@ module: ejabberd_s2s_in - port: @@web_port@@ module: ejabberd_http captcha: true loglevel: 4 max_fsm_queue: 1000 modules: 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: [] mod_version: [] registration_timeout: infinity shaper: fast: 50000 normal: 1000 ejabberd-16.01/test/suite.erl0000644000232200023220000003662412645157216016465 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov <> %%% @copyright (C) 2013, Evgeniy Khramtsov %%% @doc %%% %%% @end %%% Created : 27 Jun 2013 by Evgeniy Khramtsov <> %%%------------------------------------------------------------------- -module(suite). %% API -compile(export_all). -include("suite.hrl"). %%%=================================================================== %%% API %%%=================================================================== init_config(Config) -> DataDir = proplists:get_value(data_dir, Config), PrivDir = proplists:get_value(priv_dir, Config), [_, _|Tail] = lists:reverse(filename:split(DataDir)), BaseDir = filename:join(lists:reverse(Tail)), 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}, {s2s_port, 5269}, {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), application:set_env(ejabberd, config, ConfigPath), application:set_env(ejabberd, log_path, LogPath), application:set_env(sasl, sasl_error_logger, {file, SASLPath}), application:set_env(mnesia, dir, MnesiaDir), [{server_port, ct:get_config(c2s_port, 5222)}, {server_host, "localhost"}, {server, ?COMMON_VHOST}, {user, <<"test_single">>}, {master_nick, <<"master_nick">>}, {slave_nick, <<"slave_nick">>}, {room_subject, <<"hello, world!">>}, {certfile, CertFile}, {base_dir, BaseDir}, {resource, <<"resource">>}, {master_resource, <<"master_resource">>}, {slave_resource, <<"slave_resource">>}, {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), ?config(server_port, Config), [binary, {packet, 0}, {active, false}]), init_stream(set_opt(socket, Sock, Config)). 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), #stream_features{sub_els = Fs} = recv(), Mechs = lists:flatmap( fun(#sasl_mechanisms{list = Ms}) -> Ms; (_) -> [] end, Fs), lists:foldl( fun(#feature_register{}, Acc) -> set_opt(register, true, Acc); (#starttls{}, Acc) -> set_opt(starttls, true, Acc); (#compression{methods = Ms}, Acc) -> set_opt(compression, Ms, Acc); (_, Acc) -> Acc end, set_opt(mechs, Mechs, Config), Fs). disconnect(Config) -> Socket = ?config(socket, Config), ok = ejabberd_socket:send(Socket, ?STREAM_TRAILER), {xmlstreamend, <<"stream:stream">>} = recv(), ejabberd_socket:close(Socket), Config. close_socket(Config) -> Socket = ?config(socket, Config), ejabberd_socket:close(Socket), Config. starttls(Config) -> send(Config, #starttls{}), #starttls_proceed{} = recv(), TLSSocket = ejabberd_socket:starttls( ?config(socket, Config), [{certfile, ?config(certfile, Config)}, connect]), init_stream(set_opt(socket, TLSSocket, Config)). zlib(Config) -> send(Config, #compress{methods = [<<"zlib">>]}), #compressed{} = recv(), ZlibSocket = ejabberd_socket:compress(?config(socket, Config)), init_stream(set_opt(socket, ZlibSocket, Config)). auth(Config) -> Mechs = ?config(mechs, Config), HaveMD5 = lists:member(<<"DIGEST-MD5">>, Mechs), HavePLAIN = lists:member(<<"PLAIN">>, Mechs), if HavePLAIN -> auth_SASL(<<"PLAIN">>, Config); HaveMD5 -> auth_SASL(<<"DIGEST-MD5">>, Config); true -> ct:fail(no_sasl_mechanisms_available) end. bind(Config) -> #iq{type = result, sub_els = [#bind{}]} = send_recv( Config, #iq{type = set, sub_els = [#bind{resource = ?config(resource, Config)}]}), Config. open_session(Config) -> #iq{type = result, sub_els = []} = send_recv(Config, #iq{type = set, sub_els = [#session{}]}), Config. auth_SASL(Mech, Config) -> {Response, SASL} = sasl_new(Mech, ?config(user, Config), ?config(server, Config), ?config(password, Config)), send(Config, #sasl_auth{mechanism = Mech, text = Response}), wait_auth_SASL_result(set_opt(sasl, SASL, Config)). wait_auth_SASL_result(Config) -> case recv() of #sasl_success{} -> ejabberd_socket:reset_stream(?config(socket, Config)), 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), #stream_features{sub_els = Fs} = recv(), lists:foldl( fun(#feature_sm{}, ConfigAcc) -> set_opt(sm, true, ConfigAcc); (#feature_csi{}, ConfigAcc) -> set_opt(csi, true, ConfigAcc); (_, ConfigAcc) -> ConfigAcc end, Config, Fs); #sasl_challenge{text = ClientIn} -> {Response, SASL} = (?config(sasl, Config))(ClientIn), send(Config, #sasl_response{text = Response}), wait_auth_SASL_result(set_opt(sasl, SASL, Config)); #sasl_failure{} -> ct:fail(sasl_auth_failed) end. re_register(Config) -> User = ?config(user, Config), Server = ?config(server, Config), Pass = ?config(password, 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]). recv() -> receive {'$gen_event', {xmlstreamelement, El}} -> Pkt = xmpp_codec:decode(fix_ns(El)), ct:pal("recv: ~p ->~n~s", [El, xmpp_codec:pp(Pkt)]), Pkt; {'$gen_event', Event} -> Event end. fix_ns(#xmlel{name = Tag, attrs = Attrs} = El) when Tag == <<"stream:features">>; Tag == <<"stream:error">> -> NewAttrs = [{<<"xmlns">>, <<"http://etherx.jabber.org/streams">>} |lists:keydelete(<<"xmlns">>, 1, Attrs)], El#xmlel{attrs = NewAttrs}; fix_ns(#xmlel{name = Tag, attrs = Attrs} = El) when Tag == <<"message">>; Tag == <<"iq">>; Tag == <<"presence">> -> NewAttrs = [{<<"xmlns">>, <<"jabber:client">>} |lists:keydelete(<<"xmlns">>, 1, Attrs)], El#xmlel{attrs = NewAttrs}; fix_ns(El) -> El. send_text(Config, Text) -> ejabberd_socket:send(?config(socket, Config), Text). send(State, Pkt) -> {NewID, NewPkt} = case Pkt of #message{id = I} -> ID = id(I), {ID, Pkt#message{id = ID}}; #presence{id = I} -> ID = id(I), {ID, Pkt#presence{id = ID}}; #iq{id = I} -> ID = id(I), {ID, Pkt#iq{id = ID}}; _ -> {undefined, 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)), NewID. send_recv(State, IQ) -> ID = send(State, IQ), #iq{id = ID} = recv(). sasl_new(<<"PLAIN">>, User, Server, Password) -> {<>, fun (_) -> {error, <<"Invalid SASL challenge">>} end}; sasl_new(<<"DIGEST-MD5">>, User, Server, Password) -> {<<"">>, fun (ServerIn) -> case cyrsasl_digest:parse(ServerIn) of bad -> {error, <<"Invalid SASL challenge">>}; KeyVals -> Nonce = xml:get_attr_s(<<"nonce">>, KeyVals), CNonce = id(), Realm = proplists:get_value(<<"realm">>, KeyVals, Server), DigestURI = <<"xmpp/", Realm/binary>>, NC = <<"00000001">>, QOP = <<"auth">>, AuthzId = <<"">>, MyResponse = response(User, Password, Nonce, AuthzId, Realm, CNonce, DigestURI, NC, QOP, <<"AUTHENTICATE">>), Resp = <<"username=\"", User/binary, "\",realm=\"", Realm/binary, "\",nonce=\"", Nonce/binary, "\",cnonce=\"", CNonce/binary, "\",nc=", NC/binary, ",qop=", QOP/binary, ",digest-uri=\"", DigestURI/binary, "\",response=\"", MyResponse/binary, "\"">>, {Resp, fun (ServerIn2) -> case cyrsasl_digest:parse(ServerIn2) of bad -> {error, <<"Invalid SASL challenge">>}; _KeyVals2 -> {<<"">>, fun (_) -> {error, <<"Invalid SASL challenge">>} end} end end} end end}. hex(S) -> p1_sha:to_hexlist(S). response(User, Passwd, Nonce, AuthzId, Realm, CNonce, DigestURI, NC, QOP, A2Prefix) -> A1 = case AuthzId of <<"">> -> <<((erlang:md5(<>)))/binary, ":", Nonce/binary, ":", CNonce/binary>>; _ -> <<((erlang:md5(<>)))/binary, ":", Nonce/binary, ":", CNonce/binary, ":", AuthzId/binary>> end, A2 = case QOP of <<"auth">> -> <>; _ -> <> end, T = <<(hex((erlang:md5(A1))))/binary, ":", Nonce/binary, ":", NC/binary, ":", CNonce/binary, ":", QOP/binary, ":", (hex((erlang:md5(A2))))/binary>>, hex((erlang:md5(T))). my_jid(Config) -> jlib:make_jid(?config(user, Config), ?config(server, Config), ?config(resource, Config)). server_jid(Config) -> jlib:make_jid(<<>>, ?config(server, Config), <<>>). pubsub_jid(Config) -> Server = ?config(server, Config), jlib:make_jid(<<>>, <<"pubsub.", Server/binary>>, <<>>). proxy_jid(Config) -> Server = ?config(server, Config), jlib:make_jid(<<>>, <<"proxy.", Server/binary>>, <<>>). muc_jid(Config) -> Server = ?config(server, Config), jlib:make_jid(<<>>, <<"conference.", Server/binary>>, <<>>). muc_room_jid(Config) -> Server = ?config(server, Config), jlib:make_jid(<<"test">>, <<"conference.", Server/binary>>, <<>>). id() -> id(undefined). id(undefined) -> randoms:get_string(); id(ID) -> ID. get_features(Config) -> get_features(Config, server_jid(Config)). get_features(Config, To) -> #iq{type = result, sub_els = [#disco_info{features = Features}]} = send_recv(Config, #iq{type = get, sub_els = [#disco_info{}], to = To}), Features. is_feature_advertised(Config, Feature) -> is_feature_advertised(Config, Feature, server_jid(Config)). is_feature_advertised(Config, Feature, To) -> Features = get_features(Config, To), lists:member(Feature, Features). set_opt(Opt, Val, Config) -> [{Opt, Val}|lists:keydelete(Opt, 1, Config)]. wait_for_master(Config) -> put_event(Config, slave_ready), master_ready = get_event(Config). wait_for_slave(Config) -> put_event(Config, master_ready), slave_ready = get_event(Config). make_iq_result(#iq{from = From} = IQ) -> IQ#iq{type = result, to = From, from = undefined, sub_els = []}. %%%=================================================================== %%% Clients puts and gets events via this relay. %%%=================================================================== start_event_relay() -> spawn(fun event_relay/0). stop_event_relay(Config) -> Pid = ?config(event_relay, Config), exit(Pid, normal). event_relay() -> event_relay([], []). event_relay(Events, Subscribers) -> receive {subscribe, From} -> From ! {ok, self()}, lists:foreach( fun(Event) -> From ! {event, Event, self()} end, Events), event_relay(Events, [From|Subscribers]); {put, Event, From} -> From ! {ok, self()}, lists:foreach( fun(Pid) when Pid /= From -> Pid ! {event, Event, self()}; (_) -> ok end, Subscribers), event_relay([Event|Events], Subscribers) end. subscribe_to_events(Config) -> Relay = ?config(event_relay, Config), Relay ! {subscribe, self()}, receive {ok, Relay} -> ok end. put_event(Config, Event) -> Relay = ?config(event_relay, Config), Relay ! {put, Event, self()}, receive {ok, Relay} -> ok end. get_event(Config) -> Relay = ?config(event_relay, Config), receive {event, Event, Relay} -> Event end. ejabberd-16.01/test/suite.hrl0000644000232200023220000000612512645157216016461 0ustar debalancedebalance-include_lib("common_test/include/ct.hrl"). -include_lib("p1_xml/include/xml.hrl"). -include("ns.hrl"). -include("ejabberd.hrl"). -include("mod_proxy65.hrl"). -include("xmpp_codec.hrl"). -define(STREAM_HEADER, <<"">>). -define(STREAM_TRAILER, <<"">>). -define(PUBSUB(Node), <<(?NS_PUBSUB)/binary, "#", Node>>). -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 {P1, P2} -> {R1, R2}; {P2, P1} -> {R2, R1}; {P1, V1} -> suite:match_failure([V1], [P2]); {P2, V2} -> suite:match_failure([V2], [P1]); {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)()). -define(recv3(P1, P2, P3), (fun() -> 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)); V -> suite:match_failure([V], [P1, P2, P3]) end end)()). -define(recv4(P1, P2, P3, P4), (fun() -> case R4 = recv() of 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)); V -> suite:match_failure([V], [P1, P2, P3, P4]) end end)()). -define(recv5(P1, P2, P3, P4, P5), (fun() -> case R5 = recv() of P1 -> insert(R5, 1, ?recv4(P2, P3, P4, P5)); 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)); V -> suite:match_failure([V], [P1, P2, P3, P4, P5]) end end)()). -define(COMMON_VHOST, <<"localhost">>). -define(MNESIA_VHOST, <<"mnesia.localhost">>). -define(MYSQL_VHOST, <<"mysql.localhost">>). -define(PGSQL_VHOST, <<"pgsql.localhost">>). -define(SQLITE_VHOST, <<"sqlite.localhost">>). -define(LDAP_VHOST, <<"ldap.localhost">>). -define(EXTAUTH_VHOST, <<"extauth.localhost">>). -define(RIAK_VHOST, <<"riak.localhost">>). insert(Val, N, Tuple) -> L = tuple_to_list(Tuple), {H, T} = lists:split(N-1, L), list_to_tuple(H ++ [Val|T]). ejabberd-16.01/test/ejabberd_hooks_test.exs0000644000232200023220000001541112645157216021340 0ustar debalancedebalance# ---------------------------------------------------------------------- # # 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. # # ---------------------------------------------------------------------- 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 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 :ok = :ejabberd_hooks.add(hookname, @host, @self, callback, 40) [{40, @self, _callback}] = :ejabberd_hooks.get_handlers(hookname, @host) end test "An anonymous function can be removed from hook handlers" do hookname = :test_fun_hook 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) end test "An module function can be removed from hook handlers" do hookname = :test_mod_hook callback = :hook_callback :ok = :ejabberd_hooks.add(hookname, @host, @self, callback, 40) :ok = :ejabberd_hooks.delete(hookname, @host, @self, callback, 40) [] = :ejabberd_hooks.get_handlers(hookname, @host) # TODO: Check that removed function is not call anymore end test "'Run hook' call registered handler once" do test_result = :hook_result run_hook([], fn -> test_result end, test_result) end test "'Run hook' can call registered handler with parameters" do test_result = :hook_result_with_params run_hook([:hook_params], fn _ -> test_result end, test_result) 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) end test "Run fold hooks accumulate state in correct order through handlers" do # setup test hookname = :test_mod_hook 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 test "Hook run_fold are executed based on priority order, not registration order" do # setup test hookname = :test_mod_hook modulename = :hook_module mock(modulename, :hook_callback1, fn(_acc) -> :first end) mock(modulename, :hook_callback2, fn(_acc) -> :second end) :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 hookname = :test_mod_hook modulename = :hook_module mock(modulename, :hook_callback1, fn(_acc) -> :stop end) mock(modulename, :hook_callback2, fn(_acc) -> :executed end) :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback2, 50) :stopped = :ejabberd_hooks.run_fold(hookname, @host, :started, []) # Only one module has been called [{_pid, {^modulename, :hook_callback1, [:started]}, :stop}] = :meck.history(modulename) end test "Error in run_fold is ignored" do run_fold_crash(fn(_acc) -> raise "crashed" end) end test "Throw in run_fold is ignored" do run_fold_crash(fn(_acc) -> throw :crashed end) end 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 # 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) end def run_fold_crash(crash_fun) do # setup test hookname = :test_mod_hook modulename = :hook_module mock(modulename, :hook_callback1, crash_fun) mock(modulename, :hook_callback2, fn(_acc) -> :final end) :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback2, 50) :final = :ejabberd_hooks.run_fold(hookname, @host, :started, []) # Both handlers were called 2 = length(:meck.history(modulename)) end # TODO refactor: Move to ejabberd_test_mock def mock(module, function, fun) do try do :meck.new(module, [:non_strict]) catch :error, {:already_started, _pid} -> :ok end :meck.expect(module, function, fun) end end ejabberd-16.01/test/README0000644000232200023220000000252512645157216015501 0ustar debalancedebalanceYou need MySQL, PostgreSQL and Riak up and running. MySQL should be accepting TCP connections on localhost:3306. PostgreSQL should be accepting TCP connections on localhost:5432. Riak should be accepting TCP connections on localhost:8087. MySQL and PostgreSQL should grant full access to user 'ejabberd_test' with password 'ejabberd_test' on database 'ejabberd_test'. Riak should be configured with leveldb as a database backend and -pz should be pointed to the directory with ejabberd BEAM files. Here is a quick setup example: ------------------ PostgreSQL ------------------ $ psql template1 template1=# CREATE USER ejabberd_test WITH PASSWORD 'ejabberd_test'; template1=# CREATE DATABASE ejabberd_test; template1=# GRANT ALL PRIVILEGES ON DATABASE ejabberd_test TO ejabberd_test; ------------------- MySQL ------------------- $ mysql mysql> CREATE USER 'ejabberd_test'@'localhost' IDENTIFIED BY 'ejabberd_test'; mysql> CREATE DATABASE ejabberd_test; mysql> GRANT ALL ON ejabberd_test.* TO 'ejabberd_test'@'localhost'; ------------------- Riak ------------------- $ cat /etc/riak/vm.args ... ## Map/Reduce path -pz /path/to/ejabberd/ebin ... For version < 2.x: $ cat /etc/riak/app.config: ... {riak_kv, [ {storage_backend, riak_kv_eleveldb_backend}, ... For version >= 2.x: $ cat /etc/riak/riak.conf: ... storage_backend = leveldb ... ejabberd-16.01/test/ldap_srv.erl0000644000232200023220000003413412645157216017140 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov %%% @copyright (C) 2013, Evgeniy Khramtsov %%% @doc %%% Simple LDAP server intended for LDAP modules testing %%% @end %%% Created : 21 Jun 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- -module(ldap_srv). -behaviour(gen_server). %% API -export([start/1, load_ldif/1, equalityMatch/3, greaterOrEqual/3, lessOrEqual/3, approxMatch/3]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("ELDAPv3.hrl"). -define(INFO_MSG(Fmt, Args), error_logger:info_msg(Fmt, Args)). -define(ERROR_MSG(Fmt, Args), error_logger:error_msg(Fmt, Args)). -define(TCP_SEND_TIMEOUT, 32000). -define(SERVER, ?MODULE). -record(state, {listener = make_ref() :: reference()}). %%%=================================================================== %%% API %%%=================================================================== start(LDIFFile) -> gen_server:start({local, ?SERVER}, ?MODULE, [LDIFFile], []). %%%=================================================================== %%% gen_server callbacks %%%=================================================================== init([LDIFFile]) -> case gen_tcp:listen(1389, [binary, {packet, asn1}, {active, false}, {reuseaddr, true}, {nodelay, true}, {send_timeout, ?TCP_SEND_TIMEOUT}, {send_timeout_close, true}, {keepalive, true}]) of {ok, ListenSocket} -> case load_ldif(LDIFFile) of {ok, Tree} -> ?INFO_MSG("LDIF tree loaded, " "ready to accept connections", []), {_Pid, MRef} = spawn_monitor( fun() -> accept(ListenSocket, Tree) end ), {ok, #state{listener = MRef}}; {error, Reason} -> {stop, Reason} end; {error, Reason} = Err -> ?ERROR_MSG("failed to fetch sockname: ~p", [Err]), {stop, Reason} end. handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({'DOWN', MRef, _Type, _Object, Info}, #state{listener = MRef} = State) -> ?ERROR_MSG("listener died with reason ~p, terminating", [Info]), {stop, normal, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%%=================================================================== %%% Internal functions %%%=================================================================== accept(ListenSocket, Tree) -> case gen_tcp:accept(ListenSocket) of {ok, Socket} -> spawn(fun() -> process(Socket, Tree) end), accept(ListenSocket, Tree); Err -> ?ERROR_MSG("failed to accept: ~p", [Err]), Err end. process(Socket, Tree) -> case gen_tcp:recv(Socket, 0) of {ok, B} -> case asn1rt:decode('ELDAPv3', 'LDAPMessage', B) of {ok, Msg} -> Replies = process_msg(Msg, Tree), Id = Msg#'LDAPMessage'.messageID, lists:foreach( fun(ReplyOp) -> Reply = #'LDAPMessage'{messageID = Id, protocolOp = ReplyOp}, %%?DEBUG("sent:~n~p", [Reply]), {ok, Bytes} = asn1rt:encode( 'ELDAPv3', 'LDAPMessage', Reply), gen_tcp:send(Socket, Bytes) end, Replies), process(Socket, Tree); Err -> ?ERROR_MSG("failed to decode msg: ~p", [Err]), Err end; Err -> Err end. process_msg(#'LDAPMessage'{protocolOp = Op} = _Msg, TopTree) -> %%?DEBUG("got:~n~p", [Msg]), case Op of {bindRequest, #'BindRequest'{name = DN}} -> ResCode = case find_obj(DN, TopTree) of {ok, _} -> success; error -> invalidCredentials %%success end, [{bindResponse, #'BindResponse'{resultCode = ResCode, matchedDN = <<"">>, errorMessage = <<"">>}}]; {searchRequest, #'SearchRequest'{baseObject = DN, scope = Scope, filter = Filter, attributes = Attrs}} -> DNs = process_dn_filter(DN, Scope, Filter, TopTree), Es = lists:map( fun(D) -> make_entry(D, TopTree, Attrs) end, DNs), Es ++ [{searchResDone, #'LDAPResult'{resultCode = success, matchedDN = <<"">>, errorMessage = <<"">>}}]; {extendedReq, _} -> [{extendedResp, #'ExtendedResponse'{matchedDN = <<"">>, errorMessage = <<"Not Implemented">>, resultCode = operationsError}}]; _ -> RespOp = case Op of {modifyRequest, _} -> modifyResponse; {addRequest, _} -> addResponse; {delRequest, _} -> delResponse; {modDNRequest, _} -> modDNResponse; {compareRequest, _} -> compareResponse; _ -> undefined end, case RespOp of undefined -> []; _ -> [{RespOp, #'LDAPResult'{matchedDN = <<"">>, errorMessage = <<"Not implemented">>, resultCode = operationsError}}] end end. make_entry(DN, Tree, Attrs) -> KVs = case ets:lookup(Tree, {dn, DN}) of [{_, _KVs}|_] -> _KVs; _ -> [] end, NewKVs = if Attrs /= [], Attrs /= [<<"*">>] -> lists:filter( fun({A, _V}) -> member(A, Attrs) end, KVs); true -> KVs end, KVs1 = dict:to_list( lists:foldl( fun({A, V}, D) -> dict:append(A, V, D) end, dict:new(), NewKVs)), {searchResEntry, #'SearchResultEntry'{ objectName = str:join(DN, <<",">>), attributes = [#'PartialAttributeList_SEQOF'{type = T, vals = V} || {T, V} <- KVs1]}}. process_dn_filter(DN, Level, F, Tree) -> DN1 = str:tokens(DN, <<",">>), Fun = filter_to_fun(F), filter(Fun, DN1, Tree, Level). filter_to_fun({'and', Fs}) -> fun(KVs) -> lists:all( fun(F) -> (filter_to_fun(F))(KVs) end, Fs) end; filter_to_fun({'or', Fs}) -> fun(KVs) -> lists:any( fun(F) -> (filter_to_fun(F))(KVs) end, Fs) end; filter_to_fun({present, Attr}) -> fun(KVs) -> present(Attr, KVs) end; filter_to_fun({Tag, #'AttributeValueAssertion'{attributeDesc = Attr, assertionValue = Val}}) when Tag == equalityMatch; Tag == greaterOrEqual; Tag == lessOrEqual; Tag == approxMatch -> fun(KVs) -> apply(?MODULE, Tag, [Attr, Val, KVs]) end; filter_to_fun({substrings, #'SubstringFilter'{type = A, substrings = Ss}}) -> Re = substrings_to_regexp(Ss), fun(KVs) -> substrings(A, Re, KVs) end; filter_to_fun({'not', F}) -> fun(KVs) -> not (filter_to_fun(F))(KVs) end. find_obj(DN, Tree) -> case ets:lookup(Tree, {dn, str:tokens(DN, <<",">>)}) of [{_, Obj}|_] -> {ok, Obj}; [] -> error end. present(A, R) -> case keyfind(A, R) of [] -> false; _ -> true end. equalityMatch(A, V, R) -> Vs = keyfind(A, R), member(V, Vs). lessOrEqual(A, V, R) -> lists:any( fun(X) -> str:to_lower(X) =< str:to_lower(V) end, keyfind(A, R)). greaterOrEqual(A, V, R) -> lists:any( fun(X) -> str:to_lower(X) >= str:to_lower(V) end, keyfind(A, R)). approxMatch(A, V, R) -> equalityMatch(A, V, R). substrings(A, Re, R) -> lists:any( fun(V) -> case re:run(str:to_lower(V), Re) of {match, _} -> true; _ -> false end end, keyfind(A, R)). substrings_to_regexp(Ss) -> ReS = lists:map( fun({initial, S}) -> [S, <<".*">>]; ({any, S}) -> [<<".*">>, S, <<".*">>]; ({final, S}) -> [<<".*">>, S] end, Ss), ReS1 = str:to_lower(list_to_binary([$^, ReS, $$])), {ok, Re} = re:compile(ReS1), Re. filter(F, BaseDN, Tree, Level) -> KVs = case ets:lookup(Tree, {dn, BaseDN}) of [{_, _KVs}|_] -> _KVs; [] -> [] end, Rest = case Level of baseObject -> []; _ -> NewLevel = if Level /= wholeSubtree -> baseObject; true -> Level end, lists:flatmap( fun({_, D}) -> NewDN = if BaseDN == [] -> D; true -> [D|BaseDN] end, filter(F, NewDN, Tree, NewLevel) end, ets:lookup(Tree, BaseDN)) end, if BaseDN == [], Level /= baseObject -> Rest; true -> case F(KVs) of true -> [BaseDN|Rest]; false -> Rest end end. keyfind(K, KVs) -> keyfind(str:to_lower(K), KVs, []). keyfind(K, [{K1, V}|T], Acc) -> case str:to_lower(K1) of K -> keyfind(K, T, [V|Acc]); _ -> keyfind(K, T, Acc) end; keyfind(_, [], Acc) -> Acc. member(E, Es) -> member1(str:to_lower(E), Es). member1(E, [H|T]) -> case str:to_lower(H) of E -> true; _ -> member1(E, T) end; member1(_, []) -> false. load_ldif(Path) -> case file:open(Path, [read, binary]) of {ok, Fd} -> {ok, resort(format(read_lines(Fd, []), [], []))}; Err -> ?ERROR_MSG("failed to read LDIF file: ~p", [Err]), Err end. read_lines(Fd, Acc) -> case file:read_line(Fd) of {ok, Str} -> Line = process_line(str:strip(Str, right, $\n)), read_lines(Fd, [Line|Acc]); eof -> Acc; Err -> Err end. process_line(<> = L) when C/=$ , C/=$\t, C/=$\n -> case str:chr(L, $:) of 0 -> <<>>; Pos -> NewPos = Pos - 1, case L of <> -> {Val, base64, str:strip(Rest, left, $ )}; <> -> {Val, plain, str:strip(Rest, left, $ )} end end; process_line([_|L]) -> L; process_line(_) -> <<>>. format([{Val, Type, L}|T], Ls, Acc) -> Str1 = iolist_to_binary([L|Ls]), Str2 = case Type of plain -> Str1; base64 -> base64:decode(Str1) end, format(T, [], [{Val, Str2}|Acc]); format([<<"-">>|T], Ls, Acc) -> format(T, Ls, Acc); format([L|T], Ls, Acc) -> format(T, [L|Ls], Acc); format([], _, Acc) -> lists:reverse(Acc). resort(T) -> resort(T, [], [], ets:new(ldap_tree, [named_table, public, bag])). resort([{<<"dn">>, S}|T], Ls, DNs, Tree) -> case proplists:get_value(<<"changetype">>, Ls, <<"add">>) of <<"add">> -> [H|Rest] = DN = str:tokens(S, <<",">>), ets:insert(Tree, {{dn, DN}, Ls}), ets:insert(Tree, {Rest, H}), resort(T, [], [DN|DNs], Tree); _ -> resort(T, [], DNs, Tree) end; resort([AttrVal|T], Ls, DNs, Acc) -> resort(T, [AttrVal|Ls], DNs, Acc); resort([], _, DNs, Tree) -> {_, TopDNs} = lists:foldl( fun(D, {L, Acc}) -> NewL = length(D), if NewL < L -> {NewL, [D]}; NewL == L -> {L, [D|Acc]}; true -> {L, Acc} end end, {unlimited, []}, DNs), Attrs = lists:map( fun(TopDN) -> ets:insert(Tree, {[], TopDN}), {<<"namingContexts">>, str:join(TopDN, <<",">>)} end, TopDNs), Attrs1 = [{<<"supportedLDAPVersion">>, <<"3">>}, {<<"objectClass">>, <<"top">>}|Attrs], ets:insert(Tree, {{dn, []}, Attrs1}), Tree. ejabberd-16.01/test/elixir_SUITE.erl0000644000232200023220000000365512645157216017577 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Mickael Remond %%% @copyright (C) 2002-2015, ProcessOne %%% @doc %%% This is a common test wrapper to run our ejabberd tests written in %%% Elixir from standard common test code. %%% %%% Example: Is run with: %%% ./rebar skip_deps=true ct suites=elixir %%% or from ejabber overall test suite: %%% make test %%% @end %%% Created : 19 Feb 2015 by Mickael Remond %%%------------------------------------------------------------------- -module(elixir_SUITE). -compile(export_all). init_per_testcase(_TestCase, Config) -> process_flag(error_handler, ?MODULE), Config. all() -> case is_elixir_available() of true -> Dir = test_dir(), filelib:fold_files(Dir, ".*\.exs", false, fun(Filename, Acc) -> [list_to_atom(filename:basename(Filename)) | Acc] end, []); false -> [] end. is_elixir_available() -> case catch elixir:module_info() of {'EXIT',{undef,_}} -> false; ModInfo when is_list(ModInfo) -> true end. undefined_function(?MODULE, Func, Args) -> case lists:suffix(".exs", atom_to_list(Func)) of true -> run_elixir_test(Func); false -> error_handler:undefined_function(?MODULE, Func, Args) end; undefined_function(Module, Func, Args) -> error_handler:undefined_function(Module, Func,Args). run_elixir_test(Func) -> 'Elixir.ExUnit':start([]), '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). test_dir() -> {ok, CWD} = file:get_cwd(), filename:join(CWD, "../../test"). ejabberd-16.01/examples/0000755000232200023220000000000012645157216015454 5ustar debalancedebalanceejabberd-16.01/examples/transport-configs/0000755000232200023220000000000012645157216021136 5ustar debalancedebalanceejabberd-16.01/examples/transport-configs/init-scripts/0000755000232200023220000000000012645157216023566 5ustar debalancedebalanceejabberd-16.01/examples/transport-configs/init-scripts/msn-transport0000755000232200023220000000217412645157216026347 0ustar debalancedebalance#!/bin/sh ######################################################### # # msn-transport -- script to start MSN Transport. # ######################################################### DAEMON=/usr/local/sbin/jabberd-msn-transport CONF=/etc/jabber/msn-transport.xml NAME=jabberd-msn-transport HOME=/etc/jabber/ USER=ejabberd ######################################################### if [ "`/usr/bin/whoami`" != "$USER" ]; then echo "You need to be" $USER "user to run this script." exit 1 fi case "$1" in strace) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME in strace mode." strace -o /opt/ejabberd/var/log/jabber/strace.log $DAEMON -H $HOME -c $CONF & ;; debug) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME in debugging mode." $DAEMON -D -H $HOME -c $CONF & ;; start) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME." $DAEMON -H $HOME -c $CONF & ;; stop) echo "Stopping $NAME." killall $NAME & ;; restart|reload) $0 stop sleep 3 $0 start ;; *) echo "Usage: $0 {debug|start|stop|restart}" exit 1 esac ejabberd-16.01/examples/transport-configs/init-scripts/yahoo-transport-20000755000232200023220000000173512645157216027032 0ustar debalancedebalance#!/bin/sh ############################################################## # # yahoo-transport-2 -- script to start Yahoo-transport-2. # ############################################################# DAEMON=/usr/local/sbin/jabberd-yahoo-transport-2 CONF=/etc/jabber/yahoo-transport-2.xml NAME=jabberd-yahoo-transport-2 HOME=/etc/jabber/ USER=ejabberd ############################################################# if [ "`/usr/bin/whoami`" != "$USER" ]; then echo "You need to be" $USER "user to run this script." exit 1 fi case "$1" in debug) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME in debugging mode." $DAEMON -D -H $HOME -c $CONF & ;; start) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME." $DAEMON -H $HOME -c $CONF & ;; stop) echo "Stopping $NAME." killall $NAME & ;; restart|reload) $0 stop sleep 3 $0 start ;; *) echo "Usage: $0 {debug|start|stop|restart}" exit 1 esac ejabberd-16.01/examples/transport-configs/init-scripts/jabber-gg-transport0000755000232200023220000000172312645157216027371 0ustar debalancedebalance#!/bin/sh ######################################################### # # jabber-gg-transport -- script to start jabber-gg-transport. # ######################################################### DAEMON=/usr/local/sbin/jggtrans CONF=/etc/jabber/jabber-gg-transport.xml NAME=jggtrans HOME=/etc/jabber/ USER=ejabberd ######################################################### if [ "`/usr/bin/whoami`" != "$USER" ]; then echo "You need to be" $USER "user to run this script." exit 1 fi case "$1" in debug) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME in debugging mode." $DAEMON -D -H $HOME -c $CONF & ;; start) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME." $DAEMON $CONF & ;; stop) echo "Stopping $NAME." killall $NAME & rm /var/run/jabber/jabber-gg-transport.pid ;; restart|reload) $0 stop sleep 3 $0 start ;; *) echo "Usage: $0 {debug|start|stop|restart}" exit 1 esac ejabberd-16.01/examples/transport-configs/init-scripts/ile0000755000232200023220000000141012645157216024261 0ustar debalancedebalance#!/bin/sh ######################################################### # # ile -- script to start ILE. # ######################################################### DAEMON=/usr/local/sbin/ile.pl NAME=ile.pl CONF=/etc/jabber/ile.xml USER=ejabberd ######################################################### if [ "`/usr/bin/whoami`" != "$USER" ]; then echo "You need to be" $USER "user to run this script." exit 1 fi case "$1" in debug) echo "Not implemented yet. Starting in normal mode" $0 start ;; start) test -f $DAEMON || exit 0 echo "Starting $NAME." $DAEMON $CONF & ;; stop) echo "Stopping $NAME." killall $NAME & ;; restart|reload) $0 stop sleep 3 $0 start ;; *) echo "Usage: $0 {debug|start|stop|status|restart}" exit 1 esac ejabberd-16.01/examples/transport-configs/init-scripts/aim-transport0000755000232200023220000000166512645157216026324 0ustar debalancedebalance#!/bin/sh ######################################################### # # aim-transport -- script to start aim-transport. # ######################################################### DAEMON=/usr/local/sbin/jabberd-aim-transport CONF=/etc/jabber/aim-transport.xml NAME=jabberd-aim-transport HOME=/etc/jabber/ USER=ejabberd ######################################################### if [ "`/usr/bin/whoami`" != "$USER" ]; then echo "You need to be" $USER "user to run this script." exit 1 fi case "$1" in debug) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME in debugging mode." $DAEMON -D -H $HOME -c $CONF & ;; start) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME." $DAEMON -H $HOME -c $CONF & ;; stop) echo "Stopping $NAME." killall $NAME & ;; restart|reload) $0 stop sleep 3 $0 start ;; *) echo "Usage: $0 {debug|start|stop|restart}" exit 1 esac ejabberd-16.01/examples/transport-configs/init-scripts/jit0000755000232200023220000000161412645157216024304 0ustar debalancedebalance#!/bin/sh ######################################################### # # jit -- script to start JIT. # ######################################################### DAEMON=/usr/local/sbin/wpjabber-jit CONF=/etc/jabber/jit.xml NAME=wpjabber-jit HOME=/etc/jabber/ USER=ejabberd ######################################################### if [ "`/usr/bin/whoami`" != "$USER" ]; then echo "You need to be" $USER "user to run this script." exit 1 fi case "$1" in debug) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME in debugging mode." $DAEMON -D -H $HOME -c $CONF & ;; start) test -f $DAEMON -a -f $CONF || exit 0 echo "Starting $NAME." $DAEMON -H $HOME -c $CONF & ;; stop) echo "Stopping $NAME." killall $NAME & ;; restart|reload) $0 stop sleep 3 $0 start ;; *) echo "Usage: $0 {debug|start|stop|restart}" exit 1 esac ejabberd-16.01/examples/transport-configs/configs/0000755000232200023220000000000012645157216022566 5ustar debalancedebalanceejabberd-16.01/examples/transport-configs/configs/aim-transport.xml0000644000232200023220000000363412645157216026116 0ustar debalancedebalance %d: [%t] (%h): %s /var/log/jabber/aim-transport-error.log record %d %h %s /var/log/jabber/aim-transport-record.log /usr/local/lib/jabber/libjabberdxdbfile.so /var/spool/jabber AIM/ICQ Transport This is the AIM/ICQ Transport. EMAIL@ADDRESS.COM http://aim-transport.jabberstudio.org/ cp1252 /usr/local/lib/jabber/aim-transport.so 127.0.0.1 5233 SECRET /var/run/jabber/aim-transport.pid ejabberd-16.01/examples/transport-configs/configs/msn-transport.xml0000644000232200023220000000765512645157216026154 0ustar debalancedebalance %d: [%t] (%h): %s /var/log/jabber/msn-transport-error.log record %d %h %s /var/log/jabber/msn-transport-record.log /usr/local/lib/jabber/libjabberdxdbfile.so /var/spool/jabber Fill in your MSN account and password (eg: user1@hotmail.com). A nickname is optional. MSN Transport This is the MSN Transport. EMAIL@ADDRESS.COM http://msn-transport.jabberstudio.org/ More than one user entered this chat session. Enter this room to switch to groupchat modus. is available has leaved the room /usr/local/lib/jabber/msn-transport.so 127.0.0.1 5235 SECRET /var/run/jabber/msn-transport.pid ejabberd-16.01/examples/transport-configs/configs/yahoo-transport-2.xml0000644000232200023220000000470212645157216026623 0ustar debalancedebalance %d: [%t] (%h): %s /var/log/jabber/yahoo-transport-2-error.log /usr/local/lib/jabber/libjabberdxdbfile.so /var/spool/jabber Yahoo! Transport vCard not implemented in current version This is the Yahoo! transport. EMAIL@ADDRESS.COM http://yahoo-transport-2.jabberstudio.org/ Fill in your YAHOO! Messenger username and password to register on this transport. scs.msg.yahoo.com 5050 CP1252 /usr/local/lib/jabber/yahoo-transport-2.so 127.0.0.1 5236 SECRET /var/run/jabber/yahoo-transport-2.pid ejabberd-16.01/examples/transport-configs/configs/jabber-gg-transport.xml0000644000232200023220000001232212645157216027162 0ustar debalancedebalance 127.0.0.1 5237 SECRET Fill in your GG number (after "username") and password to register on the transport.

To change your information in the GaduGadu directory you need to fill in the other fields.

To remove registration you need to leave the form blank. To search people:
First fill in surname or family name, nickname, city, birthyear or range of birthyears (eg. 1950-1960) and gender (you may fill in more fields at once).
or
Fill in phone number
or
Fill in the GG number of the person you are searching.
Please fill in the GaduGadu number of the person you want to add. GG Nummer Gadu-Gadu Transport This is the Gadu-Gadu Transport. EMAIL@ADDRESS.COM http://www.jabberstudio.org/projects/jabber-gg-transport/ /var/log/jabber/jabber-gg-transport.log 60 10 315360000 300 60 5 /var/spool/jabber/gg.SERVER.COM/ /var/run/jabber/jabber-gg-transport.pid GG_TRANSPORT_ADMIN@SERVER.COM ejabberd-16.01/examples/transport-configs/configs/ile.xml0000644000232200023220000001460112645157216024063 0ustar debalancedebalance 127.0.0.1 5238 SECRET ile.SERVER.COM 7 en I Love Email With this service you can receive email notifications. Security warning: Be careful when using this. Your password will travel in clear from your client to your jabber server if you don't use SSL and it will probably travel in clear from the jabber server to your email server. Use with care. This shouldn't be an issue in your Intranet, but it is if you use an ILE installed in a foreign jabber server. EMAIL@ADDRESS.COM http://ile.jabberstudio.org/ /var/log/jabber/ile.log 1 10 20 /var/spool/jabber/ile.SERVER.COM/users.db /var/spool/jabber/ile.SERVER.COM/passwords.db /var/spool/jabber/ile.SERVER.COM/hosts.db /var/spool/jabber/ile.SERVER.COM/types.db /var/spool/jabber/ile.SERVER.COM/notifyxa.db /var/spool/jabber/ile.SERVER.COM/notifydnd.db /var/spool/jabber/ile.SERVER.COM/urls.db

Please fill in the fields,according to your email account settings and notification preferences ILE: Email notification service Email account settings Username Password Hostname Type You have received NUM email messages since last time I checked, which was CHECKINTERVAL minutes ago. There was an error while trying to check mail for ACCOUNT. Notification Options Notify even when Xtended Away (XA) Notify even when Do Not Disturb (DND) Webmail URL Login to ACCOUNT ILE: an email notifier component: http://ile.jabberstudio.org Por favor, rellene los campos del formulario. ILE: Servicio de notificación de correo Configuración de la cuenta de correo Usuario Clave Host Tipo Ha recibido NUM email(s) desde la última comprobación que fue hace CHECKINTERVAL minutos Ha habido un error en la comprobación del correo para la cuenta ACCOUNT. Opciones de notificación Notificar incluso si muy ausente (XA) Notificar incluso si no molestar (DND) Webmail URL Leer correo de ACCOUNT ILE: un notificador de nuevo email - http://ile.jabberstudio.org Ompli els camps del formulari. ILE: Servei de notificació de nou email Dades del compte de mail Usuari Clau Host Tipus Ha rebut NUM email(s) des de la última comprobació que va ser fa CHECKINTERVAL minuts. S'ha produit un error en la comprobació del correu per al compte ACCOUNT. Opcions de notificació Notificar si molt absent (XA) Notificar si no molestar (DND) Webmail URL Llegir correu de ACCOUNT ILE: un notificador de nou email - http://ile.jabberstudio.org Va rog completati urmatoarele campuri I Love Email: new email notification service Email account settings Nume utilizator Parola Nume gazda Tip Ati primit NUM mesaj(e) de la ultima verificare, care a fost acum CHECKINTERVAL minute. A fost eroare in timp ce incercam sa verific posta pentru ACCOUNT. Notification Options Notify even when Xtended Away (XA) Notify even when Do Not Disturb (DND) Webmail URL Login to ACCOUNT ILE: an email notifier component: http://ile.jabberstudio.org Vul volgende velden in. ILE: Dienst voor e-mailnotificaties Instellingen van e-mailaccount Gebruikersnaam Wachtwoord Inkomende mailserver Type verbinding U hebt NUM berichten ontvangen sinds CHECKINTERVAL minuten geleden. Fout tijdens controle op nieuwe e-mails bij ACCOUNT. ILE zal deze account niet meer opnieuw controleren tot u uw registratiegegevens wijzigt of opnieuw aanmeldt. Notificatie-instellingen Notificeer ook in de status Niet Beschikbaar (XA) Notificeer ook in de status Niet Storen (DND) URL van webmail Aanmelden op ACCOUNT ILE: een dienst om e-mailnotificaties te ontvangen: http://ile.jabberstudio.org
ejabberd-16.01/examples/transport-configs/configs/jit.xml0000644000232200023220000000704712645157216024106 0ustar debalancedebalance /var/log/jabber/jit-error record /var/log/jabber/jit-record /usr/local/lib/jabber/xdb_file.so /var/spool/jabber sms.icq.SERVER.COM sms.icq.SERVER.COM away Fill in your UIN and password. Search ICQ users. ICQ Transport (JIT) This is the Jabber ICQ Transport. EMAIL@ADDRESS.COM http://jit.jabberstudio.org/ 3907 /var/spool/jabber/jit-count 5 5 18000 windows-1252 login.icq.com /usr/local/lib/jabber/jit.so SERVER.COM 127.0.0.1 5234 SECRET /var/run/jabber/jit.pid ejabberd-16.01/examples/extauth/0000755000232200023220000000000012645157216017136 5ustar debalancedebalanceejabberd-16.01/examples/extauth/check_pass_null.pl0000755000232200023220000000266312645157216022642 0ustar debalancedebalance#!/usr/bin/perl use Unix::Syslog qw(:macros :subs); my $domain = $ARGV[0] || "example.com"; while(1) { # my $rin = '',$rout; # vec($rin,fileno(STDIN),1) = 1; # $ein = $rin; # my $nfound = select($rout=$rin,undef,undef,undef); my $buf = ""; syslog LOG_INFO,"waiting for packet"; my $nread = sysread STDIN,$buf,2; do { syslog LOG_INFO,"port closed"; exit; } unless $nread == 2; my $len = unpack "n",$buf; my $nread = sysread STDIN,$buf,$len; my ($op,$user,$host,$password) = split /:/,$buf; #$user =~ s/\./\//og; my $jid = "$user\@$domain"; my $result; syslog(LOG_INFO,"request (%s)", $op); SWITCH: { $op eq 'auth' and do { $result = 1; },last SWITCH; $op eq 'setpass' and do { $result = 1; },last SWITCH; $op eq 'isuser' and do { # password is null. Return 1 if the user $user\@$domain exitst. $result = 1; },last SWITCH; $op eq 'tryregister' and do { $result = 1; },last SWITCH; $op eq 'removeuser' and do { # password is null. Return 1 if the user $user\@$domain exitst. $result = 1; },last SWITCH; $op eq 'removeuser3' and do { $result = 1; },last SWITCH; }; my $out = pack "nn",2,$result ? 1 : 0; syswrite STDOUT,$out; } closelog; ejabberd-16.01/examples/mtr/0000755000232200023220000000000012645157216016256 5ustar debalancedebalanceejabberd-16.01/examples/mtr/ejabberd-netbsd.sh0000644000232200023220000000412112645157216021623 0ustar debalancedebalance#!/bin/sh echo '1. fetch, compile, and install erlang' if [ ! pkg_info erlang 1>/dev/null 2>&1 ]; then cd /usr/pkgsrc/lang/erlang make fetch-list|sh make make install fi if pkg_info erlang | grep -q erlang-9.1nb1; then else echo "erlang-9.1nb1 not installed" 1>&2 exit 1 fi echo '2. install crypt_drv.so' if [ ! -d /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib ] ; then mkdir -p /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib fi if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/crypto_drv.so ]; then cp work/otp*/lib/crypto/priv/*/*/crypto_drv.so \ /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib fi echo '3. compile and install elibcrypto.so' if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/elibcrypto.so ]; then cd /usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/crypto/c_src ld -r -u CRYPTO_set_mem_functions -u MD5 -u MD5_Init -u MD5_Update \ -u MD5_Final -u SHA1 -u SHA1_Init -u SHA1_Update -u SHA1_Final \ -u des_set_key -u des_ncbc_encrypt -u des_ede3_cbc_encrypt \ -L/usr/lib -lcrypto -o ../priv/obj/i386--netbsdelf/elibcrypto.o cc -shared \ -L/usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/erl_interface/obj/i386--netbsdelf \ -o ../priv/obj/i386--netbsdelf/elibcrypto.so \ ../priv/obj/i386--netbsdelf/elibcrypto.o -L/usr/lib -lcrypto cp ../priv/obj/i386--netbsdelf/elibcrypto.so \ /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib fi echo '4. compile and install ssl_esock' if [ ! -f /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/bin/ssl_esock ]; then cd /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/obj/ make fi echo '5. initial ejabberd configuration' cd /usr/pkg/jabber/ejabberd/src ./configure echo '6. edit ejabberd Makefiles' for M in Makefile mod_*/Makefile; do if [ ! -f $M.orig ]; then mv $M $M.orig sed -e s%/usr/local%/usr/pkg%g < $M.orig > $M fi done echo '7. compile ejabberd' gmake for A in mod_irc mod_muc mod_pubsub; do (cd $A; gmake) done echo '' echo 'now edit ejabberd.cfg' echo '' echo 'to start ejabberd: erl -sname ejabberd -s ejabberd' ejabberd-16.01/examples/mtr/ejabberd.cfg0000644000232200023220000000361012645157216020475 0ustar debalancedebalance% jabber.dbc.mtview.ca.us override_acls. {acl, admin, {user, "mrose", "jabber.dbc.mtview.ca.us"}}. {access, announce, [{allow, admin}, {deny, all}]}. {access, c2s, [{deny, blocked}, {allow, all}]}. {access, c2s_shaper, [{none, admin}, {normal, all}]}. {access, configure, [{allow, admin}, {deny, all}]}. {access, disco_admin, [{allow, admin}, {deny, all}]}. {access, muc_admin, [{allow, admin}, {deny, all}]}. {access, register, [{deny, all}]}. {access, s2s_shaper, [{fast, all}]}. {auth_method, internal}. {host, "jabber.dbc.mtview.ca.us"}. {outgoing_s2s_port, 5269}. {shaper, normal, {maxrate, 1000}}. {shaper, fast, {maxrate, 50000}}. {welcome_message, none}. {listen, [{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]}, {5223, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}, {ssl, [{certfile, "/etc/openssl/certs/ejabberd.pem"}]}]}, {5269, ejabberd_s2s_in, [{shaper, s2s_shaper}]}]}. {modules, [ {mod_register, []}, {mod_roster, []}, {mod_privacy, []}, {mod_configure, []}, {mod_disco, []}, {mod_stats, []}, {mod_vcard, []}, {mod_offline, []}, {mod_echo, [{host, "echo.jabber.dbc.mtview.ca.us"}]}, {mod_private, []}, % {mod_irc, []}, {mod_muc, []}, {mod_pubsub, []}, {mod_time, []}, {mod_last, []}, {mod_version, []} ]}. % Local Variables: % mode: erlang % End: ejabberd-16.01/examples/mtr/ejabberd0000644000232200023220000000315412645157216017742 0ustar debalancedebalance#!/bin/sh # # PROVIDE: ejabberd # REQUIRE: DAEMON # KEYWORD: shutdown # HOME=/usr/pkg/jabber D=/usr/pkg/jabber/ejabberd export HOME name="ejabberd" rcvar=$name if [ -r /etc/rc.conf ] then . /etc/rc.conf else eval ${rcvar}=YES fi # $flags from environment overrides ${rcvar}_flags if [ -n "${flags}" ] then eval ${rcvar}_flags="${flags}" fi checkyesno() { eval _value=\$${1} case $_value in [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0 ;; [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1 ;; *) echo "\$${1} is not set properly." return 1 ;; esac } cmd=${1:-start} case ${cmd} in force*) cmd=${cmd#force} eval ${rcvar}=YES ;; esac if checkyesno ${rcvar} then else exit 0 fi case ${cmd} in start) if [ -x $D/src ]; then echo "Starting ${name}." cd $D/src ERL_MAX_PORTS=32000 export ERL_MAX_PORTS ulimit -n $ERL_MAX_PORTS su jabber -c "/usr/pkg/bin/erl -sname ejabberd -s ejabberd -heart -detached -sasl sasl_error_logger '{file, \"ejabberd-sasl.log\"}' &" \ 1>/dev/null 2>&1 fi ;; stop) echo "rpc:call('ejabberd@`hostname -s`', init, stop, [])." | \ su jabber -c "/usr/pkg/bin/erl -sname ejabberdstop" ;; restart) echo "rpc:call('ejabberd@`hostname -s`', init, restart, [])." | \ su jabber -c "/usr/pkg/bin/erl -sname ejabberdrestart" ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 esac ejabberd-16.01/priv/0000755000232200023220000000000012645157216014616 5ustar debalancedebalanceejabberd-16.01/priv/msgs/0000755000232200023220000000000012645157216015567 5ustar debalancedebalanceejabberd-16.01/priv/msgs/uk.msg0000644000232200023220000010501512645157216016720 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"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","Додати Jabber ID"}. {"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?","Чи дозволити цьому Jabber ID підпиÑатиÑÑŒ новини наданого вузла"}. {"Allow users to change the subject","Дозволити кориÑтувачам змінювати тему"}. {"Allow users to query other users","Дозволити iq-запити до кориÑтувачів"}. {"Allow users to send invites","Дозволити кориÑтувачам надÑилати запрошеннÑ"}. {"Allow users to send private messages","Дозволити приватні повідомленнÑ"}. {"Allow visitors to change nickname","Дозволити відвідувачам змінювати пÑевдонім"}. {"Allow visitors to send status text in presence updates","Дозволити відвідувачам відÑилати текÑÑ‚ ÑтатуÑу в оновленнÑÑ… приÑутноÑті"}. {"All Users","Ð’ÑÑ– кориÑтувачі"}. {"Announcements","СповіщеннÑ"}. {"anyone","вÑім учаÑникам"}. {"A password is required to enter this room","Щоб зайти в цю конференцію, необхідно ввеÑти пароль"}. {"April","квітнÑ"}. {"August","ÑерпнÑ"}. {"Backup Management","ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¸Ð¼ копіюваннÑм"}. {"Backup to File at ","Резервне ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð² файл на "}. {"Backup","Резервне копіюваннÑ"}. {"Bad format","Ðеправильний формат"}. {"Birthday","День народженнÑ"}. {"CAPTCHA web page","ÐдреÑа капчі"}. {"Change Password","Змінити пароль"}. {"Change User Password","Змінити Пароль КориÑтувача"}. {"Characters not allowed:","Заборонені Ñимволи:"}. {"Chatroom configuration modified","ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸ змінилаÑÑŒ"}. {"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","Виберіть модулі, Ñкі необхідно зупинити"}. {"Choose storage type of tables","Оберіть тип Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†ÑŒ"}. {"Choose whether to approve this entity's subscription.","Вирішіть, чи задовольнити запит цього об'єкту на підпиÑку"}. {"City","МіÑто"}. {"Commands","Команди"}. {"Conference room does not exist","ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ñ–Ñ Ð½Ðµ Ñ–Ñнує"}. {"Configuration of room ~s","ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸ ~s"}. {"Configuration","КонфігураціÑ"}. {"Connected Resources:","Підключені реÑурÑи:"}. {"Connections parameters","Параметри з'єднаннÑ"}. {"Country","Країна"}. {"CPU Time:","ПроцеÑорний чаÑ:"}. {"Database Tables Configuration at ","ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†ÑŒ бази даних на "}. {"Database","База даних"}. {"December","груднÑ"}. {"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","ДоÑтавлÑти разом з повідомленнÑми про публікації Ñамі публікації"}. {"Description:","ОпиÑ:"}. {"Disc only copy","Тільки диÑк"}. {"Displayed Groups:","Видимі групи:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Ðікому не кажіть Ñвій пароль, навіть адмініÑтраторам Ñервера."}. {"Dump Backup to Text File at ","ÐšÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð² текÑтовий файл на "}. {"Dump to Text File","ÐšÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð² текÑтовий файл"}. {"Edit Properties","Змінити параметри"}. {"ejabberd IRC module","ejabberd IRC модуль"}. {"ejabberd MUC module","ejabberd MUC модуль"}. {"ejabberd Publish-Subscribe module","Модуль ejabberd Публікації-ПідпиÑки"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}. {"ejabberd vCard module","ejabberd vCard модуль"}. {"ejabberd Web Admin","Веб-Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÐдмініÑÑ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ ejabberd"}. {"Elements","Елементи"}. {"Email","Електронна пошта"}. {"Enable logging","Включити журнал роботи"}. {"Encoding for server ~b","ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñервера ~b"}. {"End User Session","Закінчити Ð¡ÐµÐ°Ð½Ñ ÐšÐ¾Ñ€Ð¸Ñтувача"}. {"Enter list of {Module, [Options]}","Введіть перелік такого виду {Module, [Options]}"}. {"Enter nickname you want to register","Введіть пÑевдонім, Ñкий ви хочете зареєÑтрувати"}. {"Enter path to backup file","Введіть шлÑÑ… до резервного файла"}. {"Enter path to jabberd14 spool dir","Введіть шлÑÑ… до директорії Ñпула jabberd14"}. {"Enter path to jabberd14 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-Ñерверів"}. {"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","ПропуÑкати ці Jabber ID без 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):"}. {"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 (Додайте * в кінець Ð¿Ð¾Ð»Ñ Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ підрÑдка)"}. {"Friday","П'ÑтницÑ"}. {"From ~s","Від ~s"}. {"From","Від кого"}. {"Full Name","Повне ім'Ñ"}. {"Get Number of Online Users","Отримати КількіÑть Підключених КориÑтувачів"}. {"Get Number of Registered Users","Отримати КількіÑть ЗареєÑтрованих КориÑтувачів"}. {"Get User Last Login Time","Отримати Ð§Ð°Ñ ÐžÑтаннього ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ ÐšÐ¾Ñ€Ð¸Ñтувача"}. {"Get User Password","Отримати Пароль КориÑтувача"}. {"Get User Statistics","Отримати СтатиÑтику по КориÑтувачу"}. {"Groups","Групи"}. {"Group ","Група "}. {"has been banned","заборонили вхід в кімнату"}. {"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 been kicked","вигнали з кімнати"}. {" has set the subject to: "," вÑтановив(ла) тему: "}. {"Host","ХоÑÑ‚"}. {"If you don't see the CAPTCHA image here, visit the 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.","Щоб вказати різні порти, паролі та ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ€Ñ–Ð·Ð½Ð¸Ñ… Ñерверів IRC, заповніть ÑпиÑок значеннÑми в форматі '{\"irc server\", \"encoding\", port, \"password\"}'. За замовчуваннÑм Ñ†Ñ Ñлужба викориÑтовує \"~s\" кодуваннÑ, порт ~p, пуÑтий пароль."}. {"Import Directory","Імпорт з директорії"}. {"Import File","Імпорт з файла"}. {"Import user data from jabberd14 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:","Імпорт кориÑтувачів з діректорії Ñпула 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 адреÑи"}. {"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","змінив(ла) пÑевдонім на"}. {"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 недопуÑтимий"}. {"January","ÑічнÑ"}. {"Join IRC channel","ПриєднатиÑÑ Ð´Ð¾ каналу IRC"}. {"joins the room","увійшов(ла) в кімнату"}. {"Join the IRC channel here.","ПриєднатиÑÑ Ð´Ð¾ каналу IRC"}. {"Join the IRC channel in this Jabber ID: ~s","ПриєднатиÑÑ Ð´Ð¾ каналу IRC з Jabber ID: ~s"}. {"July","липнÑ"}. {"June","червнÑ"}. {"Last Activity","ОÑтаннє підключеннÑ"}. {"Last login","ОÑтаннє підключеннÑ"}. {"Last month","За оÑтанній міÑÑць"}. {"Last year","За оÑтанній рік"}. {"leaves the room","вийшов(ла) з кімнати"}. {"Listened Ports at ","Відкриті порти на "}. {"Listened Ports","Відкриті порти"}. {"List of modules to start","СпиÑок завантажуваних модулів"}. {"Low level update script","Ðизькорівневий Ñценарій поновленнÑ"}. {"Make participants list public","Зробити ÑпиÑок учаÑників видимим вÑім"}. {"Make room CAPTCHA protected","Зробити кімнату захищеною капчею"}. {"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","МакÑимальний розмір кориÑного Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð² байтах"}. {"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","Модулі"}. {"Module","Модуль"}. {"Monday","Понеділок"}. {"Name:","Ðазва:"}. {"Name","Ðазва"}. {"Never","Ðіколи"}. {"New Password:","Ðовий Пароль:"}. {"Nickname Registration at ","РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð¿Ñевдоніма на "}. {"Nickname ~s does not exist in the room","ПÑевдонім ~s в кімнаті відÑутній"}. {"Nickname","ПÑевдонім"}. {"No body provided for announce message","Тіло Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð¼Ð°Ñ” бути непуÑтим"}. {"No Data","Ðемає даних"}. {"Node ID","ID вузла"}. {"Node not found","Вузол не знайдено"}. {"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","ПовідомлÑти абонентів про Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð±Ñ–Ñ€Ð½Ð¸ÐºÐ°"}. {"November","лиÑтопада"}. {"Number of occupants","КількіÑть приÑутніх"}. {"Number of online users","КількіÑть підключених кориÑтувачів"}. {"Number of registered users","КількіÑть зареєÑтрованих кориÑтувачів"}. {"October","груднÑ"}. {"Offline Messages:","Офлайнові повідомленнÑ:"}. {"Offline Messages","Офлайнові повідомленнÑ"}. {"OK","Продовжити"}. {"Old Password:","Старий пароль:"}. {"Online Users:","Підключені кориÑтувачі:"}. {"Online Users","Підключені кориÑтувачі"}. {"Online","Підключений"}. {"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-з'єднаннÑ"}. {"Owner privileges required","Ðеобхідні права влаÑника"}. {"Packet","Пакет"}. {"Password ~b","Пароль ~b"}. {"Password Verification:","Перевірка ПаролÑ:"}. {"Password Verification","Перевірка ПаролÑ"}. {"Password:","Пароль:"}. {"Password","Пароль"}. {"Path to Dir","ШлÑÑ… до директорії"}. {"Path to File","ШлÑÑ… до файла"}. {"Pending","ОчікуваннÑ"}. {"Period: ","Період"}. {"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), то його резервне ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±Ð½Ð¾ робити окремо."}. {"Pong","Понг"}. {"Port ~b","Порт ~b"}. {"Port","Порт"}. {"Present real Jabber IDs to","Зробити реальні Jabber ID учаÑників видимими"}. {"private, ","приватна, "}. {"Protocol","Протокол"}. {"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","ЗареєÑтровані кориÑтувачі"}. {"Register","РеєÑтраціÑ"}. {"Registration in mod_irc for ","РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð² mod_irc Ð´Ð»Ñ "}. {"Remote copy","не зберігаетьÑÑ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾"}. {"Remove All Offline Messages","Видалити вÑÑ– офлайнові повідомленнÑ"}. {"Remove User","Видалити кориÑтувача"}. {"Remove","Видалити"}. {"Replaced by new connection","Замінено новим з'єднаннÑм"}. {"Resources","РеÑурÑи"}. {"Restart Service","ПерезапуÑтити СервіÑ"}. {"Restart","ПерезапуÑтити"}. {"Restore Backup from File at ","Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð· резервної копії на "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Відновити з бінарної резервної копії при наÑтупному запуÑку (потребує менше пам'Ñті):"}. {"Restore binary backup immediately:","Відновити з бінарної резервної копії негайно:"}. {"Restore plain text backup immediately:","Відновити з текÑтової резервної копії негайно:"}. {"Restore","Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð· резервної копії"}. {"Room Configuration","ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸"}. {"Room creation is denied by service policy","Створювати конференцію заборонено політикою Ñлужби"}. {"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 ","Результати пошуку в "}. {"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:","Сервер:"}. {"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 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","ЗапуÑк модулів"}. {"Start","ЗапуÑтити"}. {"Statistics of ~p","СтатиÑтика вузла ~p"}. {"Statistics","СтатиÑтика"}. {"Stop Modules at ","Зупинка модулів на "}. {"Stop Modules","Зупинка модулів"}. {"Stopped Nodes","Зупинені вузли"}. {"Stop","Зупинити"}. {"Storage Type","Тип таблиці"}. {"Store binary backup:","Зберегти бінарну резервну копію:"}. {"Store plain text backup:","Зберегти текÑтову резервну копію:"}. {"Subject","Тема"}. {"Submitted","Відправлено"}. {"Submit","Відправити"}. {"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: ","Помилка при зміні паролÑ: "}. {"There was an error creating the account: ","Помилка при Ñтворенні акаунту:"}. {"There was an error deleting the account: ","Помилка при видаленні акаунту: "}. {"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-Ñервера."}. {"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","Видалити"}. {"Update message of the day (don't send)","Оновити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ (не надÑилати)"}. {"Update message of the day on all hosts (don't send)","Оновити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ Ð½Ð° вÑÑ–Ñ… хоÑтах (не надÑилати)"}. {"Update plan","План поновленнÑ"}. {"Update script","Сценарій поновленнÑ"}. {"Update","Обновити"}. {"Uptime:","Ð§Ð°Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸:"}. {"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"}. ejabberd-16.01/priv/msgs/id.po0000644000232200023220000014410412645157216016527 0ustar debalancedebalance# , 2010. msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "PO-Revision-Date: 2011-02-15 07:09+0800\n" "Last-Translator: Irfan Mahfudz Guntur \n" "Language-Team: SmartCommunity \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Indonesian (Bahasa Indonesia)\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Penggunaan STARTTLS diperlukan" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Tidak ada sumber daya yang disediakan" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Diganti dengan koneksi baru" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Masukkan teks yang Anda lihat" #: 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: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:227 msgid "CAPTCHA web page" msgstr "CAPTCHA laman web" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Captcha ini benar." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Layanan:" #: 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" #: 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 "Ditolak" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Admin Web ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administrasi" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "mentah" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Aturan Akses" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s aturan akses konfigurasi" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtual Hosts" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Pengguna" #: 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:971 msgid "Users Last Activity" msgstr "Aktifitas terakhir para pengguna" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periode:" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Akhir bulan" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Akhir tahun" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Semua aktifitas" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Tampilkan Tabel Normal" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Tampilkan Tabel Terpisah" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistik" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Tidak Ditemukan" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Node tidak ditemukan" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Tambah Baru" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Pengguna Terdaftar" #: 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:1459 msgid "Offline Messages" msgstr "Pesan Offline" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Aktifitas Terakhir" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Tidak Pernah" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Online" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Pengguna Terdaftar:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Koneksi s2s yang keluar:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Koneksi s2s yang keluar:" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Pengguna" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Sumber Daya Terhubung:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Kata Sandi:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Hapus Pengguna" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Tidak Ada Data" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Node-node" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Menjalankan Node" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Menghentikan node" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Node" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Backup" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Port Terdeteksi" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Memperbarui" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Jalankan Ulang" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Hentikan" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modul" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Panggilan Kesalahan RPC" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabel Database pada" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nama" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Jenis Penyimpanan" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elemen-elemen" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memori" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Kesalahan" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Cadangan dari" #: 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 "" "Harap dicatat bahwa pilihan ini hanya akan membuat cadangan builtin Mnesia " "database. Jika Anda menggunakan modul ODBC, anda juga perlu untuk membuat " "cadangan database SQL Anda secara terpisah." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Penyimpanan cadangan yang berpasangan:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Segera mengembalikan cadangan yang berpasangan:" #: 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:1999 msgid "Store plain text backup:" msgstr "Simpan cadangan teks biasa:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Segera mengembalikan cadangan teks biasa:" #: 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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Импорт пользовательÑких данных из буферной директории jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Mendeteksi Port-port di" #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "modul-modul di" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "statistik dari ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Sampai saat:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Waktu CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaksi yang dilakukan:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaksi yang dibatalkan:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaksi yang dijalankan ulang:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaksi yang ditempuh:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Memperbarui " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Rencana Perubahan" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Modifikasi modul-modul" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Perbarui naskah" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Perbaruan naskah tingkat rendah" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Periksa naskah" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocol" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Pilihan-pilihan" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Mulai" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Perintah" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Benar-benar ingin menghapus pesan harian?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Subyek" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Isi Pesan" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Tidak ada isi pesan yang disediakan untuk mengirimkan pesan" #: mod_announce.erl:662 msgid "Announcements" msgstr "Pengumuman" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Kirim pengumuman untuk semua pengguna" #: 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:668 msgid "Send announcement to all online users" msgstr "Kirim pengumuman untuk semua pengguna yang online" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Rubah pesan harian (tidak dikirim)" #: 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:680 msgid "Delete message of the day" msgstr "Hapus pesan harian" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Hapus pesan harian pada semua host" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Pengaturan" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Memulai Modul" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Hentikan Modul" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Mengembalikan" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Dump menjadi File Teks" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Impor File" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Impor Direktori" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Restart Layanan" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Shut Down Layanan" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Hapus Pengguna" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Akhir Sesi Pengguna" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Ubah User Password" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Dapatkan Statistik Pengguna" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Dapatkan Jumlah Pengguna Yang Terdaftar" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Dapatkan Jumlah User Yang Online" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Manajemen Pengguna" #: mod_configure.erl:525 msgid "All Users" msgstr "Semua Pengguna" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Koneksi Keluar s2s" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Manajemen Backup" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Impor Pengguna Dari jabberd14 Spool File" #: mod_configure.erl:762 msgid "To ~s" msgstr "Kepada ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Dari ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Database Tabel Konfigurasi pada" #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Pilih jenis penyimpanan tabel" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Hanya salinan dari disc" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM dan disc salinan" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Salinan RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Salinan Remote" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Hentikan Modul pada" #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Pilih Modul untuk berhenti" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Mulai Modul pada" #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Masukkan daftar {Modul, [Options]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Daftar modul untuk memulai" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Backup ke File pada" #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Masukkan path untuk file cadangan" #: 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:1115 msgid "Restore Backup from File at " msgstr "Kembalikan Backup dari File pada" #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Dump Backup ke File Teks di" #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Masukkan path ke file teks" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Impor Pengguna dari File pada" #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Masukkan path ke file jabberd14 spool" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Impor Pengguna dari Dir di" #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Masukkan path ke direktori spool jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Jalur ke Dir" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Waktu tunda" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfigurasi Daftar Akses Pengendalian" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Daftar Pengendalian Akses" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Akses Konfigurasi" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verifikasi Sandi" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Jumlah pengguna terdaftar" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Jumlah pengguna online" #: mod_configure.erl:1936 msgid "Last login" msgstr "Terakhir Login" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Ukuran Daftar Kontak" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Alamat IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Sumber daya" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administrasi" #: mod_configure.erl:2100 msgid "Action on user" msgstr "Tindakan pada pengguna" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Ganti Properti" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modul" #: 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:653 msgid "Registration in mod_irc for " msgstr "Pendaftaran di mod_irc untuk" #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "Masukkan username, pengkodean, port dan sandi yang ingin Anda gunakan untuk " "menghubungkan ke layanan IRC" #: mod_irc.erl:667 msgid "IRC Username" msgstr "Nama Pengguna IRC" #: 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." msgstr "" "Jika Anda ingin menentukan port yang berbeda, sandi, pengkodean untuk " "layanan IRC, isi daftar ini dengan nilai-nilai dalam format '{\"server irc " "\", \"encoding \", port, \"sandi \"}'. Secara default ini menggunakan " "layanan \"~s \" pengkodean, port ~p, kata sandi kosong." #: 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 "" "Contoh: [{\"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 "Parameter Koneksi" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Gabung channel IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Channel IRC (tidak perlu menempatkan # sebelumnya)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Layanan IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Gabung ke channel IRC disini" #: 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:1046 msgid "IRC settings" msgstr "Pengaturan IRC" #: 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 "" "Masukkan username dan pengkodean yang ingin Anda gunakan untuk menghubungkan " "ke layanan IRC. Tekan 'Selanjutnya' untuk mendapatkan lagi formulir kemudian " "Tekan 'Lengkap' untuk menyimpan pengaturan." #: mod_irc.erl:1060 msgid "IRC username" msgstr "Nama Pengguna IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Kata Sandi ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Pengkodean untuk layanan ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Layanan ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Pendaftaran Julukan pada" #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Nama Julukan" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Ruangan Chat" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "meninggalkan ruangan" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Pengguna Terdaftar" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Konfigurasi ruang chat diubah" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "bergabung ke ruangan" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "meninggalkan ruangan" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "telah dibanned" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "telah dikick karena perubahan afiliasi" #: 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:445 msgid "has been kicked because of a system shutdown" msgstr "telah dikick karena sistem shutdown" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "sekarang dikenal sebagai" #: 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:493 msgid "Chatroom is created" msgstr "Ruang chat telah dibuat" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Ruang chat dilenyapkan" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Ruang chat dimulai" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Ruang chat dihentikan" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Senin" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Selasa" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Rabu" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Kamis" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Jumat" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sabtu" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Minggu" #: mod_muc_log.erl:513 msgid "January" msgstr "Januari" #: mod_muc_log.erl:514 msgid "February" msgstr "Februari" #: mod_muc_log.erl:515 msgid "March" msgstr "Maret" #: mod_muc_log.erl:516 msgid "April" msgstr "April" #: mod_muc_log.erl:517 msgid "May" msgstr "Mei" #: mod_muc_log.erl:518 msgid "June" msgstr "Juni" #: mod_muc_log.erl:519 msgid "July" msgstr "Juli" #: mod_muc_log.erl:520 msgid "August" msgstr "Agustus" #: mod_muc_log.erl:521 msgid "September" msgstr "September" #: mod_muc_log.erl:522 msgid "October" msgstr "Oktober" #: mod_muc_log.erl:523 msgid "November" msgstr "Nopember" #: mod_muc_log.erl:524 msgid "December" msgstr "Desember" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Konfigurasi Ruangan" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Penghuni Ruangan" #: 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" msgstr "" "Hanya moderator dan peserta yang diizinkan untuk mengganti topik pembicaraan " "di ruangan ini" #: 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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Nama Julukan ~s tidak berada di dalam ruangan" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliasi tidak valid: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Peran tidak valid: ~s" #: 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:3359 msgid "Room title" msgstr "Nama Ruangan" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Keterangan ruangan" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Buat ruangan menjadi permanent" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Buat ruangan dapat dicari" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Buat daftar participant diketahui oleh public" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Buat ruangan yang dilindungi dengan kata sandi" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maksimum Jumlah Penghuni" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Tidak terbatas" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Tampilkan Jabber ID secara lengkap" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "Hanya moderator" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "Siapapun" #: 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:3516 msgid "Make room moderated" msgstr "Buat ruangan hanya untuk moderator saja" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "pengguna pertama kali masuk sebagai participant" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Perbolehkan pengguna untuk mengganti topik" #: 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:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Perbolehkan pengguna untuk mengetahui pengguna lain" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Perbolehkan pengguna mengirimkan undangan" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Perbolehkan visitor mengganti nama julukan" #: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Perbolehkan pengguna mengirimkan undangan" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Buat ruangan dilindungi dengan CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Aktifkan catatan" #: 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:4190 msgid "Number of occupants" msgstr "Jumlah Penghuni" #: mod_muc_room.erl:4260 msgid "private, " msgstr "pribadi, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Pengguna" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s mengundang anda ke ruangan ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "kata sandi yaitu:" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "Waktu" #: mod_offline.erl:812 msgid "From" msgstr "Dari" #: mod_offline.erl:813 msgid "To" msgstr "Kepada" #: mod_offline.erl:814 msgid "Packet" msgstr "Paket" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Pesan Offline:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Hapus Semua Pesan Offline" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "modul ejabberd SOCKS5 Bytestreams" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Setujui-Pertemanan" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Modul ejabberd Setujui-Pertemanan" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Permintaan pertemanan PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Pilih apakah akan menyetujui hubungan pertemanan ini." #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID Node" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Alamat Pertemanan" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Memberikan muatan dengan pemberitahuan acara" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Memberikan pemberitahuan acara" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Beritahu pelanggan ketika ada perubahan konfigurasi node" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Beritahu pelanggan ketika node dihapus" #: 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:3755 msgid "Persist items to storage" msgstr "Pertahankan item ke penyimpanan" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Nama yang dikenal untuk node" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Max item untuk bertahan" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Apakah diperbolehkan untuk berlangganan" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Tentukan model akses" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Kelompok kontak yang diizinkan untuk berlangganan" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Tentukan model penerbitan" #: 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:3771 msgid "Specify the event message type" msgstr "Tentukan jenis acara pesan" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Max kapasitas ukuran dalam bytes" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Ketika untuk mengirim item terakhir yang dipublikasikan" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Hanya mengirimkan pemberitahuan kepada pengguna yang tersedia" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Koleksi dengan yang berafiliasi dengan sebuah node" #: 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: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" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Ada kesalahan saat membuat akun:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Jabber akun Anda berhasil dihapus." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Ada kesalahan saat menghapus akun:" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Kata sandi pada akun Jabber Anda telah berhasil diubah." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Ada kesalahan dalam mengubah password:" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Pendaftaran Akun Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Daftarkan sebuah akun jabber" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Nonaktifkan akun jabber" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nama Pengguna:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Pada bagian ini huruf besar dan kecil tidak dibedakan: Misalnya macbeth " "adalah sama dengan MacBeth juga Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Karakter tidak diperbolehkan:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Layanan:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Jangan memberitahukan kata sandi Anda ke siapapun, bahkan para administrator " "dari layanan Jabber." #: 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: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 "" "Beberapa klien Jabber dapat menyimpan password di komputer Anda. Gunakan " "fitur itu hanya jika Anda mempercayai komputer Anda aman." #: 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 "" "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." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verifikasi Kata Sandi:" #: mod_register_web.erl:269 msgid "Register" msgstr "Mendaftar" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Password Lama:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Password Baru:" #: 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:480 msgid "Unregister" msgstr "Nonaktifkan" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Berlangganan" #: mod_roster.erl:1437 msgid "Pending" msgstr "Tertunda" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grup" #: mod_roster.erl:1476 msgid "Validate" msgstr "Mengesahkan" #: mod_roster.erl:1485 msgid "Remove" msgstr "Menghapus" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontak dari" #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Tambah Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Kontak" #: 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:1232 msgid "Name:" msgstr "Nama:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Keterangan:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Anggota:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Tampilkan Grup:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grup" #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Layanan Erlang Jabber" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Hari Lahir" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Kota" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Negara" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Nama Keluarga (marga)" #: 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 "" "Isi formulir untuk pencarian pengguna Jabber yang cocok (Tambahkan * ke " "mengakhiri pengisian untuk menyamakan kata)" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nama Lengkap" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Nama Tengah" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nama Organisasi" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unit Organisasi" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Pencarian pengguna dalam" #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard Pencarian Pengguna" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Modul ejabberd vCard" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Hasil Pencarian untuk" #: 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 "Outgoing s2s Servers:" #~ msgstr "Layanan s2s yang keluar:" #~ msgid "Delete" #~ msgstr "Hapus" #~ msgid "This room is not anonymous" #~ msgstr "Ruangan ini tidak dikenal" #~ 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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Participant ini dikick dari ruangan karena ia mengirim pesan kesalahan ke " #~ "participant lain" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Проверка капчи прошла уÑпешно." ejabberd-16.01/priv/msgs/he.po0000644000232200023220000016001512645157216016526 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: ejabberd 2.1.x\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: Isratine Citizen \n" "Language-Team: Rahut \n" "Language: he\n" "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" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Source-Language: en\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "נדרש שימוש של STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "×œ× ×¡×•×¤×§ מש×ב" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "הוחלף בחיבור חדש" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "הזן ×ת הכיתוב ש×תה רו××”" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "ההודעות שלך לערוץ ~s הינן חסומות. כדי לבטל ×ת חסימתן, בקר בכתובת ~s" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "×× ×ינך רו××” תמונת CAPTCHA ×›×ן, בקר בעמוד רשת." #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "עמוד רשת CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "â€CAPTCHA ×”×™× ×” תקפה." #: 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 "משתמש" #: ejabberd_oauth.erl:256 msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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 "מנהל רשת ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "הנהלה" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "גולמי" # × ×‘×—×¨×™× #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "כללי גישה" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s תצורת כללי גישה" # וירטו××œ×™×™× #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "מ××¨×—×™× ×ž×“×•×ž×™×" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "משתמשי×" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "פעילות ×ž×©×ª×ž×©×™× ×חרונה" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "משך זמן: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "חודש ×חרון" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "שנה ×חרונה" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "כל פעילות" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "הצג טבלה רגילה" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "הצג טבלה ×ינטגרלית" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "סטטיסטיקה" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "×œ× × ×ž×¦×" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "צומת ×œ× × ×ž×¦×" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "הוסף חדש" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "מ×רח" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "×ž×©×ª×ž×©×™× ×¨×©×•×ž×™×" #: 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:1459 msgid "Offline Messages" msgstr "הודעות ×œ× ×ž×§×•×•× ×•×ª" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "פעילות ×חרונה" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "××£ פע×" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "מקוון" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "×ž×©×ª×ž×©×™× ×¨×©×•×ž×™×:" #: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 #: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×:" #: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "חיבורי s2s יוצ××™×:" #: ejabberd_web_admin.erl:1559 msgid "Incoming s2s Connections:" 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 msgid "None" msgstr "×ין" #: 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:1673 msgid "User ~s" msgstr "משתמש ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "מש××‘×™× ×ž×—×•×‘×¨×™×:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "סיסמה:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "הסר משתמש" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "×ין מידע" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "צמתי×" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "×¦×ž×ª×™× ×ž×•×¨×¦×™×" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "×¦×ž×ª×™× ×©× ×¤×¡×§×•" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "צומת ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "מסד נתוני×" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "גיבוי" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "×¤×•×¨×˜×™× ×ž×•××–× ×™×" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "עדכן" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "×תחל" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "הפסק" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "מודולי×" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "שגי×ת קרי×ת RPC" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "טבל×ות מסד × ×ª×•× ×™× ×צל ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "ש×" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "טיפוס ×חסון" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "×למנטי×" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "זיכרון" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "שגי××”" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "גיבוי של ~p" # ×”×ינטגרלי לחוד #: 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 "" "×× × ×©×™× ×œ×‘ ×›×™ ×פשרויות ×לו יגבו ×ת מסד ×”× ×ª×•× ×™× ×”×ž×•×‘× ×” Mnesia בלבד. ×× ×”×™× ×š " "עושה שימוש במודול ODBC, עליך ×’× ×œ×’×‘×•×ª ×ת מסד ×”× ×ª×•× ×™× SQL ×שר מצוי ברשותך " "בנפרד." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "×חסן גיבוי בינ×רי:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "שחזר גיבוי בינ×רי ל×לתר:" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "שחזר גיבוי בינ×רי ל×חר ×”×תחול ×”×‘× ×©×œ ejabberd (מצריך פחות זיכרון):" # תמליל ברור #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "×חסן גיבוי טקסט גלוי (plain text):" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "שחזר גיבוי טקסט גלוי (plain text) ל×לתר:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "×™×‘× ×ž×™×“×¢ ×ž×©×ª×ž×©×™× ×ž×ª×•×š קובץ PIEFXIS â€(XEP-0227):" #: 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:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "×™×¦× ×ž×™×“×¢ של כל ×”×ž×©×ª×ž×©×™× ×©×‘×ª×•×š מ×רח לתוך קבצי PIEFXIS â€(XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "×™×¦× ×ת כל הטבל×ות בתור ש×ילתות SQL לתוך קובץ:" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "×™×‘× × ×ª×•× ×™ משתמש מתוך קובץ סליל (spool file) של jabberd14:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "×™×‘× × ×ª×•× ×™ ×ž×©×ª×ž×©×™× ×ž×ª×•×š מדור סליל (spool directory) של jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "×¤×•×¨×˜×™× ×ž×•××–× ×™× ×צל " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "×ž×•×“×•×œ×™× ×צל ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "סטטיסטיקות של ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "זמן פעילות:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "זמן מחשב (CPU):" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "טרנזקציות שבוצעו:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "טרנזקציות שבוטלו:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "טרנזקציות שהותחלו מחדש:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "טרנזקציות שנרשמו:" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "עדכון ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "תכנית עדכון" # adjusted #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "×ž×•×“×•×œ×™× ×©×”×•×ª×מו" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "תסריט עדכון" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "תסריט עדכון Low level" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "בדיקת תסריט" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "‫IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "פורט" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "פרוטוקול" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "מודול" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "×פשרויות" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "התחל" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "פקודות" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "פינג" #: mod_adhoc.erl:279 msgid "Pong" msgstr "פונג" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "ב×מת למחוק ×ת בשורת היו×?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "נוש×" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "גוף הודעה" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "×œ× ×¡×•×¤×§ גוף עבור הודעת בשורה" #: mod_announce.erl:662 msgid "Announcements" msgstr "בשורות" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "שלח בשורה לכל המשתמשי×" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "שלח בשורה לכל ×”×ž×©×ª×ž×©×™× ×‘×›×œ המ×רחי×" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "שלח בשורה לכל ×”×ž×©×ª×ž×©×™× ×”×ž×§×•×•× ×™×" #: 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:672 msgid "Set message of the day and send to online users" msgstr "קבע ×ת בשורת ×”×™×•× ×•×©×œ×— ×œ×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "קבע ×ת בשורת ×”×™×•× ×‘×›×œ המ××¨×—×™× ×•×©×œ×— ×œ×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "עדכן ×ת בשורת ×”×™×•× (×ל תשלח)" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "עדכן ×ת בשורת ×”×™×•× ×‘×›×œ המ××¨×—×™× (×ל תשלח)" #: mod_announce.erl:680 msgid "Delete message of the day" msgstr "מחק ×ת בשורת היו×" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "מחק ×ת בשורת ×”×™×•× ×‘×›×œ המ×רחי×" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "תצורה" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "התחל מודולי×" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "הפסק מודולי×" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "שחזר" # הטל ×ל קובץ תמליל #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "השלך לקובץ טקסט" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "×™×™×‘×•× ×§×•×‘×¥" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "×™×™×‘×•× ×ž×“×•×¨" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "×תחל שירות" # שירות כיבוי #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "כבה שירות" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "מחק משתמש" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "×¡×™×™× ×¡×©×Ÿ משתמש" #: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 #: mod_configure.erl:1473 msgid "Get User Password" msgstr "השג סיסמת משתמש" #: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "שנה סיסמת משתמש" # התחברות #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "השג זמן כניסה ×חרון של משתמש" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "השג סטטיסטיקת משתמש" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "השג מספר של ×ž×©×ª×ž×©×™× ×¨×©×•×ž×™×" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "השג מספר של ×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "ניהול משתמשי×" #: mod_configure.erl:525 msgid "All Users" msgstr "כל המשתמשי×" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "חיבורי s2s יוצ××™×" #: mod_configure.erl:615 msgid "Backup Management" msgstr "ניהול גיבוי" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "×™×‘× ×ž×©×ª×ž×©×™× ×ž×ª×•×š קבצי סליל (Spool Files) של jabberd14" #: mod_configure.erl:762 msgid "To ~s" msgstr "×ל ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "מ×ת ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "תצורת טבל×ות מסד × ×ª×•× ×™× ×צל " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "בחר טיפוס ×חסון של טבל×ות" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "העתק של תקליטור בלבד" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "העתק RAM ×•×’× ×ª×§×œ×™×˜×•×¨" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "העתק RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "העתק מרוחק" # at (time)? בשעה #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "הפסק ×ž×•×“×•×œ×™× ×צל " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "בחר ×ž×•×“×•×œ×™× ×œ×”×¤×¡×§×”" # at (time)? בשעה #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "התחל ×ž×•×“×•×œ×™× ×צל " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "הזן רשימה של {מודול, [×פשרויות]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "רשימה של ×ž×•×“×•×œ×™× ×œ×”×¤×¢×œ×”" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "גבה לקובץ ×צל " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "הזן נתיב לקובץ גיבוי" #: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "נתיב לקובץ" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "שחזר גיבוי מתוך קובץ ×צל " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "השלך גיבוי לקובץ טקסט ×צל " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "הזן נתיב לקובץ טקסט" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "×™×™×‘×•× ×ž×©×ª×ž×© מתוך קובץ ×צל " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "הזן נתיב לקובץ סליל (spool file) של jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "×™×™×‘×•× ×ž×©×ª×ž×©×™× ×ž×ª×•×š מדור ×צל " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "הזן נתיב למדור סליל (spool dir) של jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "נתיב למדור" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "זמן שיהוי" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "תצורת רשימת בקרת גישה" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "רשימות בקרת גישה" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "תצורת גישה" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "מזהה Jabber" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "×ימות סיסמה" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "מספר של ×ž×©×ª×ž×©×™× ×¨×©×•×ž×™×" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "מספר של ×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×" #: mod_configure.erl:1936 msgid "Last login" msgstr "כניסה ×חרונה" #: mod_configure.erl:1963 msgid "Roster size" msgstr "גודל רשימה" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "כתובות IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "מש×בי×" #: mod_configure.erl:2095 msgid "Administration of " msgstr "ניהול של " #: mod_configure.erl:2100 msgid "Action on user" msgstr "פעולה על משתמש" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "ערוך מ×פייני×" #: 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_http_upload.erl:587 msgid "Please specify file size." msgstr "×× × ×¦×™×™×Ÿ גודל קובץ." #: mod_http_upload.erl:591 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:220 mod_muc.erl:467 msgid "Access denied by service policy" msgstr "גישה נדחתה על ידי פוליסת שירות" #: mod_irc.erl:439 msgid "IRC Transport" msgstr "טרנספורט IRC" #: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "מודול IRC של ejabberd" #: 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:653 msgid "Registration in mod_irc for " msgstr "×¨×™×©×•× ×‘×ª×•×š mod_irc עבור " #: 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:667 msgid "IRC Username" msgstr "×©× ×ž×©×ª×ž×© IRC" #: 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." msgstr "" "×× ×‘×¨×¦×•× ×š לציין פורטי×, סיסמ×ות, ×§×™×“×•×“×™× ××—×¨×™× ×¢×‘×•×¨ ×©×¨×ª×™× ×©×œ IRC, ×ž×œ× ×ת " "רשימה זו ×¢× ×¢×¨×›×™× ×‘×¤×•×¨×ž×˜ '{\"irc server\", \"encoding\", port, \"password" "\"}'. ב×ופן שגרתי שירות ×–×” משתמש בקידוד \"~s\", פורט ~p, סיסמה ריקה." #: 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 "" "דוגמ×: [{\"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 "×¤×¨×ž×˜×¨×™× ×©×œ חיבור" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "הצטרף לערוץ IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "ערוץ IRC (×ל ×ª×©×™× ×¡×™×ž×Ÿ # ר×שון)" #: mod_irc.erl:903 msgid "IRC server" msgstr "שרת IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "הצטרף לערוץ IRC ×›×ן." #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "הצטרף לערוץ IRC במזהה Jabber ×–×”: ~s" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "הגדרות IRC" # ×”×©×œ× #: 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 "" "הזן ×©× ×ž×©×ª×ž×© ×•×§×™×“×•×“×™× ×‘×”× ×‘×¨×¦×•× ×š להשתמש לצורך התחברות לשרתי IRC. לחץ 'הב×' " "כדי להשיג עוד שדות למילוי. לחץ 'סיי×' כדי לשמור הגדרות." #: mod_irc.erl:1060 msgid "IRC username" msgstr "×©× ×ž×©×ª×ž×© IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "סיסמה ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "פורט ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "קידוד עבור שרת ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "שרת ~b" #: 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:779 msgid "Empty Rooms" msgstr "×—×“×¨×™× ×¨×™×§×™×" # to register nickname #: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "עליך להשתמש בלקוח ×שר תומך x:data כדי ×œ×¨×©×•× ×ת ×”×©× ×›×™× ×•×™" #: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "×¨×™×©×•× ×©× ×›×™× ×•×™ ×צל " #: mod_muc.erl:947 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_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 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" #: 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:249 msgid "Total rooms" msgstr "×—×“×¨×™× ×¡×”×´×›" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "×—×“×¨×™× ×§×‘×•×¢×™×" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "שמות כינוי רשומי×" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "רשימה של חדרי×" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "תצורת חדר שיחה שונתה" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "נכנס/ת ×ל החדר" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "עוזב/ת ×ת החדר" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "× ×סר/×”" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "נבעט/×” ×ž×©×•× ×©×™× ×•×™ סינוף" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "נבעט/×” ×ž×©×•× ×©×”×—×“×¨ שונה ×ל חברי×-בלבד" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "נבעט/×” ×ž×©×•× ×›×™×‘×•×™ מערכת" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "ידועה כעת בכינוי" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " הגדיר/×” ×ת ×”× ×•×©× ×ל: " #: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "חדר שיחה נוצר כעת" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "חדר שיחה הינו הרוס" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "חדר שיחה מותחל כעת" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "חדר שיחה הינו מופסק" #: mod_muc_log.erl:503 msgid "Monday" msgstr "×™×•× ×©× ×™" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "×™×•× ×©×œ×™×©×™" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "×™×•× ×¨×‘×™×¢×™" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "×™×•× ×—×ž×™×©×™" #: mod_muc_log.erl:507 msgid "Friday" msgstr "×™×•× ×©×™×©×™" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "×™×•× ×©×‘×ª" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "×™×•× ×¨×שון" #: mod_muc_log.erl:513 msgid "January" msgstr "ינו×ר" #: mod_muc_log.erl:514 msgid "February" msgstr "פברו×ר" #: mod_muc_log.erl:515 msgid "March" msgstr "מרץ" #: mod_muc_log.erl:516 msgid "April" msgstr "×פריל" #: mod_muc_log.erl:517 msgid "May" msgstr "מ××™" #: mod_muc_log.erl:518 msgid "June" msgstr "יוני" #: mod_muc_log.erl:519 msgid "July" msgstr "יולי" #: mod_muc_log.erl:520 msgid "August" msgstr "×וגוסט" #: mod_muc_log.erl:521 msgid "September" msgstr "ספטמבר" #: mod_muc_log.erl:522 msgid "October" msgstr "×וקטובר" #: mod_muc_log.erl:523 msgid "November" msgstr "נובמבר" #: mod_muc_log.erl:524 msgid "December" msgstr "דצמבר" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "תצורת חדר" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "נוכחי חדר" # נעברה #: 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. 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 "×ין ×–×” מותר לשלוח הודעות פרטיות לועידה" #: 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:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "רק ×חר××™× ×¨×©××™× ×œ×©× ×•×ª ×ת ×”× ×•×©× ×‘×—×“×¨ ×–×”" # רש××™× #: 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:2772 msgid "Nickname ~s does not exist in the room" msgstr "×©× ×›×™× ×•×™ ~s ×œ× ×§×™×™× ×‘×—×“×¨" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "סינוף שגוי: ~s" #: 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:3348 msgid "Configuration of room ~s" msgstr "תצורת חדר ~s" #: mod_muc_room.erl:3359 msgid "Room title" msgstr "כותרת חדר" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "תי×ור חדר" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "הפוך חדר לחדר קבוע" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "הפוך חדר לחדר שנתון לחיפוש פומבי" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "הפוך רשימת ×ž×©×ª×ª×¤×™× ×œ×¤×•×ž×‘×™×ª" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "הפוך חדר לחדר מוגן במילת מעבר" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "מספר מרבי של נוכחי×" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "×œ×œ× ×”×’×‘×œ×”" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "הצג כתובות Jabber ממשיות" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "ל×חר××™× ×‘×œ×‘×“" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "לכל ×חד" #: 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:3516 msgid "Make room moderated" msgstr "הפוך חדר לחדר מבוקר" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "×ž×©×ª×ž×©×™× ×©×’×¨×ª×™×™× ×›×ž×©×ª×ª×¤×™×" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "התר ×œ×ž×©×ª×ž×©×™× ×œ×©× ×•×ª ×ת הנוש×" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "התר ×œ×ž×©×ª×ž×©×™× ×œ×©×œ×•×— הודעות פרטיות" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "התר ×œ×ž×‘×§×¨×™× ×œ×©×œ×•×— הודעות פרטיות ×ל" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "××£ ×חד" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "התר ×œ×ž×©×ª×ž×©×™× ×œ×ª×©×ל ×ž×©×ª×ž×©×™× ×חרי×" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "התר ×œ×ž×©×ª×ž×©×™× ×œ×©×œ×•×— הזמנות" #: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "התר ×œ×ž×‘×§×¨×™× ×œ×©×œ×•×— טקסט מצב בתוך עדכוני נוכחות" #: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "התר ×œ×ž×‘×§×¨×™× ×œ×©× ×•×ª ×©× ×›×™× ×•×™" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "התר ×œ×ž×‘×§×¨×™× ×œ×©×œ×•×— בקשות ביטוי" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "תדירות מינימלית בין בקשות ביטוי (בשניות)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "הפוך חדר לחדר מוגן CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "×פשר ×חסון הודעות" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "×”×•×¦× ×›×ª×•×‘×•×ª Jabber מתוך ×תגר CAPTCHA" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "×פשר ×¨×™×©×•× ×¤×¢×™×œ×•×ª" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "עליך להשתמש בלקוח ×שר מסוגל להבין x:data כדי להגדיר חדר" #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "מספר של נוכחי×" #: mod_muc_room.erl:4260 msgid "private, " msgstr "פרטי, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "בקשת ביטוי" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "×שר ×ו דחה בקשת ביטוי." #: mod_muc_room.erl:4349 msgid "User JID" msgstr "â€JID משתמש" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "להעניק ביטוי ל×ישיות זו?" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "‫~s מזמינך לחדר ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "הסיסמה ×”×™×" #: mod_multicast.erl:291 msgid "Multicast" msgstr "שידור מרובב" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "שירות שידור מרובב של ejabberd" # תור הודעות ×œ× ×ž×§×•×•× ×•×ª של הקשר שלך הינו #: 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:811 msgid "Time" msgstr "זמן" #: mod_offline.erl:812 msgid "From" msgstr "מ×ת" #: mod_offline.erl:813 msgid "To" msgstr "לכבוד" #: mod_offline.erl:814 msgid "Packet" msgstr "חבילת מידע" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "הודעות ×œ× ×ž×§×•×•× ×•×ª:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "הסר ×ת כל ההודעות ×”×œ× ×ž×§×•×•× ×•×ª" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "מודול SOCKS5 Bytestreams של ejabberd" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "‫Publish-Subscribe" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "מודול Publish-Subscribe של ejabberd" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "בקשת מנוי PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "בחר ×”×× ×œ×שר ×ת ההרשמה של ישות זו." #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "מזהה צומת (NID)" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "כתובת מנוי" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "להתיר למזהה Jabber ×–×” ×œ×”×™×¨×©× ×œ×¦×•×ž×ª PubSub ×–×”?" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "מסור מטעני ייעוד (מטע״ד) יחד ×¢× ×”×ª×¨×ות ×ירוע" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "מסור התר×ות ×ירוע" # ×ž×©×ª×ž×©×™× ×¨×©×•×ž×™× #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "הודע ×ž× ×•×™×™× ×›×שר תצורת הצומת משתנה" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "הודע ×ž× ×•×™×™× ×›×שר הצומת נמחק" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "הודע ×ž× ×•×™×™× ×›×שר ×¤×¨×™×˜×™× ×ž×•×¡×¨×™× ×ž×ª×•×š הצומת" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "×¤×¨×™×˜×™× ×§×‘×•×¢×™× ×œ×חסון" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "×©× ×™×“×™×“×•×ª×™ עבור הצומת" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "מספר מרבי של ×¤×¨×™×˜×™× ×œ×§×™×‘×•×¢" # בין ×× #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "×”×× ×œ×”×ª×™×¨ הרשמות" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "ציין מודל גישה" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "קבוצות רשימה מורשות להירש×" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "ציין מודל פרסו×" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "טהר ×ת כל ×”×¤×¨×™×˜×™× ×›×שר ×”×ž×¤×¨×¡× ×”×¨×œ×•×•× ×˜×™ הופך לבלתי מקוון" #: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "ציין טיפוס הודעת ×ירוע" # ×‘×‘×ª×™× ×‘×‘×™×™×˜×™× (bytes) #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "גודל מרבי של מטען ייעוד (payload) ביחידות מידה של byte" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "מתי לשלוח ×ת הפריט ×”×ž×¤×•×¨×¡× ×”×חרון" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "מסור התר×ות ×œ×ž×©×ª×ž×©×™× ×–×ž×™× ×™× ×‘×œ×‘×“" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "×”××•×¡×¤×™× ×¢×ž× ×¦×•×ž×ª מסונף" #: 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: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 נוצר בהצלחה." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "×ירעה שגי××” ביצירת החשבון: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "חשבון Jabber נמחק בהצלחה." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "×ירעה שגי××” במחיקת החשבון: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "סיסמת חשבון Jabber שונתה בהצלחה." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "×ירעה שגי××” בשינוי הסיסמה: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "×¨×™×©×•× ×—×©×‘×•×Ÿ Jabber" # Why masculine form matters. #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "×¨×©×•× ×—×©×‘×•×Ÿ Jabber" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "בטל ×¨×™×©×•× ×—×©×‘×•×Ÿ Jabber" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "עמוד ×–×” מתיר ליצור חשבון Jabber בשרת Jabber ×–×”. כתובת JID â€(Jabber " "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." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "×ª×•×•×™× ×œ× ×ž×•×¨×©×™×:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "שרת:" #: 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:249 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 ×שר ×ž×¡×•×’×œ×™× ×œ×חסן ×ת הסיסמה שלך בתוך המחשב, ××•×œ× ×¢×œ×™×š " "לעשות ×–×ת רק בתוך המחשב ×”×ישי שלך מסיבות ביטחוניות." # תישכח #: 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 "" "שנן ×ת הסיסמה שלך, ×ו ×¨×©×•× ×ותה בנייר שמור ×‘×ž×§×•× ×‘×˜×•×—. ×צל Jabber ×ין דרך " "×וטומטית לשחזר ×ת הסיסמה שלך במידה וזו תישמט מתוך זיכרונך." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "×ימות סיסמה:" # ×¨×©×•× #: mod_register_web.erl:269 msgid "Register" msgstr "הרש×" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "סיסמה ישנה:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "סיסמה חדשה:" #: 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:480 msgid "Unregister" msgstr "בטל רישו×" #: mod_roster.erl:1436 msgid "Subscription" msgstr "הרשמה" #: mod_roster.erl:1437 msgid "Pending" msgstr "ממתינות" #: mod_roster.erl:1438 msgid "Groups" msgstr "קבוצות" #: mod_roster.erl:1476 msgid "Validate" msgstr "×”×¢× ×§ תוקף" #: mod_roster.erl:1485 msgid "Remove" msgstr "הסר" #: mod_roster.erl:1490 msgid "Roster of " msgstr "רשימה של " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "הוסף מזהה Jabber" #: mod_roster.erl:1622 msgid "Roster" msgstr "רשימה" #: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 #: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "קבוצות רשימה משותפות" #: mod_shared_roster.erl:1232 msgid "Name:" msgstr "ש×:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "תי×ור:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "חברי×:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "קבוצות מוצגות:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "קבוצה " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "שרת ג׳×בּר Erlang" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "×™×•× ×”×•×œ×“×ª" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "עיר" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "×רץ" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "דו×״ל" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "×©× ×ž×©×¤×—×”" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "×©× ×ž×œ×" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "×©× ×מצעי" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "×©× ×רגון" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "יחידת ×יגוד" # בקרב #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "חיפוש ×ž×©×ª×ž×©×™× ×צל " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "חיפוש משתמש vCard" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "מודול vCard של ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "תוצ×ות חיפוש עבור " # שקול #: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "×ž×œ× ×ת שדות ×לו כדי לחפש עבור כל משתמש Jabber מבוקש" #~ msgid "Outgoing s2s Servers:" #~ msgstr "שרתי s2s יוצ××™×:" #~ msgid "Code Update" #~ msgstr "עדכון קוד" #~ msgid "Delete" #~ msgstr "מחק" #~ msgid "This room is not anonymous" #~ msgstr "חדר ×–×” ×ינו ×נונימי" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "משתתף ×–×” נבעט מתוך החדר מכיוון ×©×”×•× ×©×œ×— הודעת שגי××”" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "משתתף ×–×” נבעט מתוך החדר ×ž×©×•× ×©×”×•× ×©×œ×— הודעת שגי××” ×ל משתתף ×חר" # שגי×ת נוכחות # נוכחות שגויה #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "משתתף ×–×” נבעט מתוך החדר ×ž×©×•× ×©×”×•× ×©×œ×— נוכחות שגי××”" #~ msgid "Notify owners about new subscribers and unsubscribers" #~ msgstr "הודע ×‘×¢×œ×™× ×ודות ×ž× ×•×™×™× ×—×“×©×™× ×•×ž× ×•×™×™× ×©×‘×™×˜×œ×• מנוי" #~ msgid "" #~ "The type of node data, usually specified by the namespace of the payload " #~ "(if any)" #~ msgstr "סוג מידע ממסר, לרוב מצוין לפי מרחב־שמות של מטען הייעוד (×× ×‘×›×œ×œ)" #~ msgid "Group ID:" #~ msgstr "קבוצה (GID):" #~ msgid "vCard" #~ msgstr "‫vCard" #~ msgid "vCard Photo:" #~ msgstr "×ª×¦×œ×•× vCard:" #~ msgid "Remove vCard" #~ msgstr "הסרת vCard" #~ msgid "vCard size (characters):" #~ msgstr "גודל vCard (תווי×):" ejabberd-16.01/priv/msgs/es.po0000644000232200023220000014672212645157216016552 0ustar debalancedebalance# translation of es.po to # Badlop , 2009. msgid "" msgstr "" "Project-Id-Version: es\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2015-09-07 14:02+0100\n" "Last-Translator: Badlop \n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Spanish (castellano)\n" "X-Generator: Poedit 1.6.10\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Es obligatorio usar STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "No se ha proporcionado recurso" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Reemplazado por una nueva conexión" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Teclea el texto que ves" #: 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: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:227 msgid "CAPTCHA web page" msgstr "Página web de CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "El CAPTCHA es válido." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "No autorizado" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administración" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Crudo" #: 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: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:913 msgid "~s access rule configuration" msgstr "Configuración de las Regla de Acceso ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Dominios Virtuales" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Usuarios" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Usuarios conectados" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Última actividad de los usuarios" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periodo: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Último mes" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Último año" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Toda la actividad" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrar Tabla Ordinaria" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrar Tabla Integral" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estadísticas" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "No encontrado" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo no encontrado" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Añadir nuevo" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Dominio" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Usuarios registrados" #: 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:1459 msgid "Offline Messages" msgstr "Mensajes diferidos" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última actividad" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nunca" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Conectado" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Usuarios registrados:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Conexiones S2S salientes:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Conexiones S2S salientes:" #: 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: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:1673 msgid "User ~s" msgstr "Usuario ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos conectados:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Contraseña:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminar usuario" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Sin datos" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodos" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos funcionando" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos detenidos" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Nodo ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de datos" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Guardar copia de seguridad" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Puertos de escucha" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Actualizar" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Detener" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Error en la llamada RPC" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Tablas de la base de datos en ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nombre" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo de almacenamiento" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementos" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memoria" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Error" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Copia de seguridad de ~p" #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Guardar copia de seguridad binaria:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Restaurar inmediatamente copia de seguridad binaria:" #: 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:1999 msgid "Store plain text backup:" msgstr "Guardar copia de seguridad en texto plano:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restaurar copias de seguridad 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 (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 los usuarios del 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 de un dominio a ficheros PIEFXIS (XEP-0227):" #: 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:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importar usuario de fichero spool de jabberd14:" #: 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:2115 msgid "Listened Ports at " msgstr "Puertos de escucha en " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Módulos en ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Estadísticas de ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tiempo desde el inicio:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tiempo consumido de CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transacciones finalizadas:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transacciones abortadas:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transacciones reiniciadas:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transacciones registradas:" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Actualizar ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan de actualización" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Módulos modificados" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script de actualización" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script de actualización a bajo nivel" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Comprobación de script" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Puerto" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocolo" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Módulo" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opciones" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Iniciar" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandos" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "¿Está seguro de quere borrar el mensaje del dia?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Asunto" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Cuerpo del mensaje" #: 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:662 msgid "Announcements" msgstr "Anuncios" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Enviar anuncio a todos los usuarios" #: 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:668 msgid "Send announcement to all online users" msgstr "Enviar anuncio a todos los usuarios conectados" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Actualizar mensaje del dia, pero no enviarlo" #: 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:680 msgid "Delete message of the day" msgstr "Borrar mensaje del dia" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Configuración" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar módulos" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Detener módulos" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar a fichero de texto" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar fichero" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar directorio" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reiniciar el servicio" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Detener el servicio" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Borrar usuario" #: 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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Cambiar contraseña de usuario" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Ver estadísticas de usuario" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Ver número de usuarios registrados" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Ver número de usuarios conectados" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Administración de usuarios" #: mod_configure.erl:525 msgid "All Users" msgstr "Todos los usuarios" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Conexiones S2S salientes" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestión de copia de seguridad" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuarios de ficheros spool de jabberd-1.4" #: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuración de tablas de la base de datos en " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selecciona tipo de almacenamiento de las tablas" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copia en disco solamente" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copia en RAM y disco" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copia en RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copia remota" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Detener módulos en " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecciona módulos a detener" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar módulos en " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introduce lista de {módulo, [opciones]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista de módulos a iniciar" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Guardar copia de seguridad en fichero en " #: 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:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Ruta al fichero" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaura copia de seguridad desde el fichero en " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Exporta copia de seguridad a fichero de texto en " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introduce ruta al fichero de texto" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importa usuario desde fichero en " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Introduce ruta al fichero jabberd14 spool" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar usuarios desde el directorio en " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Introduce la ruta al directorio de jabberd14 spools" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Ruta al directorio" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Retraso temporal" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuración de la Lista de Control de Acceso" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listas de Control de Acceso" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuración de accesos" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verificación de la contraseña" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Número de usuarios registrados" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Número de usuarios conectados" #: mod_configure.erl:1936 msgid "Last login" msgstr "Última conexión" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Tamaño de la lista de contactos" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Direcciones IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Recursos" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administración de " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Acción en el usuario" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propiedades" #: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" 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: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:476 msgid "ejabberd IRC module" 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 "" "Necesitas un cliente con soporte de x:data para configurar las opciones de " "mod_irc" #: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registro en mod_irc para" #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" 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:667 msgid "IRC Username" msgstr "Nombre de usuario en IRC" #: 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." msgstr "" "Si quieres especificar distintos codificaciones de carácteres, contraseñas o " "puertos para cada servidor IRC rellena esta lista con valores en el formato " "'{\"servidor irc\", \"codificación\", \"puerto\", \"contrasela\"}'. Este " "servicio usa por defecto la codificación \"~s\", puerto ~p, sin contraseña." #: 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 "" "Ejemplo: [{\"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 "Parámetros de conexiones" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Entrar en canal IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canal IRC (no pongas el # del principio)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Servidor IRC" #: 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: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:1046 msgid "IRC settings" msgstr "Opciones de IRC" #: 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 "" "Introduce el nombre de usuario y codificaciones de carácteres que quieras " "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:1060 msgid "IRC username" msgstr "Nombre de usuario en IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Contraseña ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Puerto ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codificación del servidor ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servidor ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registro del apodo en " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Apodo" #: 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" #: 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:249 msgid "Total rooms" msgstr "Salas totales" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Salas permanentes" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Apodos registrados" #: mod_muc_admin.erl:254 msgid "List of rooms" 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" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "entra en la sala" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "sale de la sala" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "ha sido bloqueado" #: 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: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: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:450 msgid "is now known as" msgstr "se cambia el nombre a" #: 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:493 msgid "Chatroom is created" msgstr "Se ha creado la sala" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Se ha destruido la sala" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Se ha iniciado la sala" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Se ha detenido la sala" #: mod_muc_log.erl:503 msgid "Monday" msgstr "lunes" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "martes" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "miércoles" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "jueves" #: mod_muc_log.erl:507 msgid "Friday" msgstr "viernes" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "sábado" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "domingo" #: mod_muc_log.erl:513 msgid "January" msgstr "enero" #: mod_muc_log.erl:514 msgid "February" msgstr "febrero" #: mod_muc_log.erl:515 msgid "March" msgstr "marzo" #: mod_muc_log.erl:516 msgid "April" msgstr "abril" #: mod_muc_log.erl:517 msgid "May" msgstr "mayo" #: mod_muc_log.erl:518 msgid "June" msgstr "junio" #: mod_muc_log.erl:519 msgid "July" msgstr "julio" #: mod_muc_log.erl:520 msgid "August" msgstr "agosto" #: mod_muc_log.erl:521 msgid "September" msgstr "septiembre" #: mod_muc_log.erl:522 msgid "October" msgstr "octubre" #: mod_muc_log.erl:523 msgid "November" msgstr "noviembre" #: mod_muc_log.erl:524 msgid "December" msgstr "diciembre" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuración de la sala" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Ocupantes de la sala" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "El apodo ~s no existe en la sala" #: 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:2846 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 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:3359 msgid "Room title" msgstr "Título de la sala" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descripción de la sala" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Sala permanente" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Sala públicamente visible" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "La lista de participantes es pública" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Proteger la sala con contraseña" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Sin límite" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Los Jabber ID reales pueden verlos" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "solo moderadores" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "cualquiera" #: 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:3516 msgid "Make room moderated" msgstr "Sala moderada" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Los usuarios son participantes por defecto" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permitir a los usuarios cambiar el asunto" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permitir a los usuarios enviar mensajes privados" #: 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:3551 msgid "nobody" msgstr "nadie" #: 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:3579 msgid "Allow users to send invites" msgstr "Permitir a los usuarios enviar invitaciones" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Permitir a los visitantes cambiarse el apodo" #: 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:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervalo mínimo entre peticiones de voz (en segundos)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Proteger la sala con CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Activar el almacenamiento de mensajes" #: 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:3621 msgid "Enable logging" msgstr "Guardar históricos" #: 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:4190 msgid "Number of occupants" msgstr "Número de ocupantes" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privado" #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Petición de voz" #: 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:4349 msgid "User JID" msgstr "Jabber ID del usuario" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "¿Conceder voz a esta persona?" #: 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:4507 msgid "the password is" msgstr "la contraseña es" #: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "Servicio Multicast de ejabberd" #: 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:811 msgid "Time" msgstr "Fecha" #: mod_offline.erl:812 msgid "From" msgstr "De" #: mod_offline.erl:813 msgid "To" msgstr "Para" #: mod_offline.erl:814 msgid "Packet" msgstr "Paquete" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Mensajes diferidos:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Borrar todos los mensajes diferidos" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Módulo SOCKS5 Bytestreams para ejabberd" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Servicio de Publicar-Subscribir" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo de Publicar-Subscribir de ejabberd" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Petición de subscriptor de PubSub" #: 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:1559 msgid "Node ID" msgstr "Nodo ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Dirección del subscriptor" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Enviar contenidos junto con las notificaciones de eventos" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Entregar notificaciones de eventos" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptores cuando el nodo se borra" #: 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:3755 msgid "Persist items to storage" msgstr "Persistir elementos al almacenar" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nombre sencillo para el nodo" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persisten" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Permitir subscripciones" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Especifica el modelo de acceso" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Grupos de contactos que pueden suscribirse" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Especificar el modelo del publicante" #: 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:3771 msgid "Specify the event message type" msgstr "Especifica el tipo del mensaje de evento" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Máximo tamaño del contenido en bytes" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Cuando enviar el último elemento publicado" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Solo enviar notificaciones a los usuarios disponibles" #: 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: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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Hubo uno error al crear la cuenta:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Tu cuenta Jabber se ha borrado correctamente." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Hubo un error borrando la cuenta." #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "La contraseña de tu cuenta Jabber se ha cambiado correctamente." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Hubo un error cambiando la contraseña." #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Registro de Cuenta Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Registrar una cuenta Jabber" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nombre de usuario:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "No importa si usas mayúsculas: macbeth es lo mismo que MacBeth y Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Caracteres no permitidos:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Servidor:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "No le digas tu contraseña a nadie, ni siquiera a los administradores del " "servidor Jabber." #: 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: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 "" "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: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 "" "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:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verificación de la contraseña:" #: mod_register_web.erl:269 msgid "Register" msgstr "Registrar" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Contraseña antigua:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nueva contraseña:" #: 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:480 msgid "Unregister" msgstr "Borrar" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscripción" #: mod_roster.erl:1437 msgid "Pending" msgstr "Pendiente" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grupos" #: mod_roster.erl:1476 msgid "Validate" msgstr "Validar" #: mod_roster.erl:1485 msgid "Remove" msgstr "Borrar" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista de contactos de " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Añadir Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Lista de contactos" #: 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:1232 msgid "Name:" msgstr "Nombre:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descripción:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Miembros:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Mostrar grupos:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupo " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Jabber en Erlang" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Cumpleaños" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Ciudad" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "País" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "correo" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Apellido" #: 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 "" "Rellena el formulario para buscar usuarios Jabber. Añade * al final de un " "campo para buscar subcadenas." #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nombre completo" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Segundo nombre" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nombre de la organización" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unidad de la organización" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Buscar usuarios en " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Buscar vCard de usuario" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Módulo vCard para ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Buscar resultados por " #: 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 "Outgoing s2s Servers:" #~ msgstr "Servidores S2S salientes:" #~ msgid "Delete" #~ msgstr "Eliminar" #~ msgid "This room is not anonymous" #~ msgstr "Sala no anónima" #~ 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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Este participante ha sido expulsado de la sala porque envió un mensaje de " #~ "error a otro participante" #~ 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" ejabberd-16.01/priv/msgs/pt-br.po0000644000232200023220000014622112645157216017161 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "Last-Translator: Otávio Fernandes\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: Renato Botelho\n" "X-Additional-Translator: Lucius Curado\n" "X-Additional-Translator: Felipe Brito Vasconcellos\n" "X-Additional-Translator: Victor Hugo dos Santos\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "É obrigatório uso de STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nenhum recurso foi informado" #: ejabberd_c2s.erl:1349 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 msgid "has been kicked" msgstr "foi removido" #: 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: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: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: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:227 msgid "CAPTCHA web page" msgstr "CAPTCHA web page" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "O CAPTCHA é inválido." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "Não Autorizado" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administração" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Intocado" #: 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: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:913 msgid "~s access rule configuration" msgstr "Configuração da Regra de Acesso ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Hosts virtuais" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Usuários" #: 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:971 msgid "Users Last Activity" msgstr "Ultimas atividades dos usuários" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Período: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Último mês" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Último ano" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Todas atividades" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrar Tabela Ordinária" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrar Tabela Integral" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Não encontrado" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nó não encontrado" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Adicionar novo" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Máquina" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Usuários Registrados" #: 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:1459 msgid "Offline Messages" msgstr "Mensagens offline" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última atividade" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nunca" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Conectado" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Usuários registrados" #: 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:1556 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" #: 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: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:1673 msgid "User ~s" msgstr "Usuário ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos conectados:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Senha:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Remover usuário" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Nenhum dado" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nós" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nos em execução" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nos parados" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Nó ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de dados" #: 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:1845 msgid "Listened Ports" msgstr "Portas escutadas" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Atualizar" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Parar" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Erro de chamada RPC" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Tabelas do bancod de dados em ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo de armazenamento" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementos" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memória" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Erro" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Backup de ~p" #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Armazenar backup binário:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Restaurar backup binário imediatamente" #: 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:1999 msgid "Store plain text backup:" msgstr "Armazenar backup em texto:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restaurar backup formato texto imediatamente:" #: 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: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: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: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:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importar dados dos usuários de uma fila jabberd14:" #: 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:2115 msgid "Listened Ports at " msgstr "Portas abertas em " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Módulos em ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Estatísticas de ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Uptime:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tempo de CPU" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transações salvas:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transações abortadas:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transações reiniciadas:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transações de log:" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Atualizar ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plano de Atualização" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Módulos atualizados" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script de atualização" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script de atualização low level" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Verificação de Script" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Porta" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Porta" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Módulo" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opções" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Iniciar" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandos" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 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 msgid "Subject" msgstr "Assunto" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Corpo da mensagem" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Nenhum corpo de texto fornecido para anunciar mensagem" #: mod_announce.erl:662 msgid "Announcements" msgstr "Anúncios" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Enviar anúncio a todos os usuários" #: 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:668 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 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Atualizar mensagem do dia (não enviar)" #: 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:680 msgid "Delete message of the day" msgstr "Apagar mensagem do dia" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Configuração" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar módulos" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Parar módulos" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar para arquivo texto" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar arquivo" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar diretório" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reiniciar Serviço" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Parar Serviço" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Deletar Usuário" #: 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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Alterar Senha do Usuário" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Obter Estatísticas do Usuário" #: 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:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Obter Número de Usuários Online" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gerenciamento de Usuários" #: mod_configure.erl:525 msgid "All Users" msgstr "Todos os usuários" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Conexões que partam de s2s" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestão de Backup" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuários de arquivos jabberd14 (spool files)" #: mod_configure.erl:762 msgid "To ~s" msgstr "Para ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuração de Tabelas de Base de dados em " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selecione o tipo de armazenamento das tabelas" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Somente copia em disco" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copias na RAM e disco rígido" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copia em RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copia remota" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Parar módulos em " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecione módulos a parar" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar módulos em " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introduza lista de {módulo, [opções]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Listas de módulos para inicializar" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Salvar backup para arquivo em " #: 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:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Caminho do arquivo" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaurar backup a partir do arquivo em " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Exportar backup para texto em " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introduza caminho para o arquivo texto" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importar usuário a partir do arquivo em " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Insira o caminho para a fila (arquivo) do jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar usuários a partir do diretório em " #: 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:1184 msgid "Path to Dir" msgstr "Caminho para o diretório" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Intervalo (Tempo)" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuração da Lista de Controle de Acesso" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listas de Controle de Acesso" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuração de Acesso" #: mod_configure.erl:1356 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_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verificação de Senha" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Número de usuários registrados" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Número de usuários online" #: mod_configure.erl:1936 msgid "Last login" msgstr "Último login" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Tamanho da Lista" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Endereços IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Recursos" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administração de " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Ação no usuário" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propriedades" #: mod_fail2ban.erl:95 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_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: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:476 msgid "ejabberd IRC module" 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 " "mod_irc" #: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registro em mod_irc para " #: mod_irc.erl:659 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 " "usar nos servidores IRC" #: mod_irc.erl:667 msgid "IRC Username" msgstr "Usuário IRC" #: 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." msgstr "" "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)" #: 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 "" "Exemplo: [{\"irc.teste.net\", \"koi8-r\"}, 6667, \"senha\"}, {\"dominio.foo." "net\", \"iso8859-1\", 7000}, {\"irc.servidordeteste.net\", \"utf-8\"}]." #: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parâmetros para as Conexões" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Juntar-se ao canal IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canal IRC (não coloque o #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Servidor IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Aqui! Juntar-se ao canal IRC." #: 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:1046 msgid "IRC settings" msgstr "Configurações do IRC" #: 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 "" "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." #: mod_irc.erl:1060 msgid "IRC username" msgstr "Usuário IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Senha ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Porta ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codificação para o servidor ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servidor ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registro do apelido em " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Apelido" #: 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" #: 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:249 msgid "Total rooms" msgstr "Salas no total" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Salas permanentes" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Usuários registrados" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Lista de salas" #: 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:410 msgid "joins the room" msgstr "Entrar na sala" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "Sair da sala" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "foi banido" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "foi desconectado porque o sistema foi desligado" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "é agora conhecido como" #: 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:493 msgid "Chatroom is created" msgstr "A sala de chat está criada" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "A sala de chat está destruída" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "A sala de chat está inciada" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "A sala de chat está parada" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Segunda" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Terça" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Quarta" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Quinta" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Sexta" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sábado" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Domingo" #: mod_muc_log.erl:513 msgid "January" msgstr "Janeiro" #: mod_muc_log.erl:514 msgid "February" msgstr "Fevereiro" #: mod_muc_log.erl:515 msgid "March" msgstr "Março" #: mod_muc_log.erl:516 msgid "April" msgstr "Abril" #: mod_muc_log.erl:517 msgid "May" msgstr "Maio" #: mod_muc_log.erl:518 msgid "June" msgstr "Junho" #: mod_muc_log.erl:519 msgid "July" msgstr "Julho" #: mod_muc_log.erl:520 msgid "August" msgstr "Agosto" #: mod_muc_log.erl:521 msgid "September" msgstr "Setembro" #: mod_muc_log.erl:522 msgid "October" msgstr "Outubro" #: mod_muc_log.erl:523 msgid "November" msgstr "Novembro" #: mod_muc_log.erl:524 msgid "December" msgstr "Dezembro" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuração de salas" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Número de participantes" #: 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" msgstr "" "Somente os moderadores e os participamentes podem alterar o assunto desta " "sala" #: 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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "O nick ~s não existe em la sala" #: 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:2846 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 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:3359 msgid "Room title" msgstr "Título da sala" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descrição da Sala" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Tornar sala persistente" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Tornar sala pública possível de ser encontrada" #: mod_muc_room.erl:3378 msgid "Make participants list public" 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" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Número máximo de participantes" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Ilimitado" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Tornar o Jabber ID real visível por" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "apenas moderadores" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "qualquer um" #: 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:3516 msgid "Make room moderated" msgstr "Tornar a sala moderada" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Usuários padrões como participantes" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permitir a usuários modificar o assunto" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permitir a usuários enviarem mensagens privadas" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Permitir visitantes enviar mensagem privada para" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "ninguém" #: 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:3579 msgid "Allow users to send invites" msgstr "Permitir a usuários envio de convites" #: 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:3586 msgid "Allow visitors to change nickname" 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" #: 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:3599 msgid "Make room CAPTCHA protected" msgstr "Tornar protegida a senha da sala" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Habilitar arquivamento de mensagens" #: 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:3621 msgid "Enable logging" 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" #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Número de participantes" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privado, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Requisição de voz" #: 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:4349 msgid "User JID" msgstr "Usuário JID" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Dar 'voice' a esta usuário?" #: 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:4507 msgid "the password is" msgstr "a senha é" #: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast service" #: 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:811 msgid "Time" msgstr "Tempo" #: mod_offline.erl:812 msgid "From" msgstr "De" #: mod_offline.erl:813 msgid "To" msgstr "Para" #: mod_offline.erl:814 msgid "Packet" msgstr "Pacote" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Mensagens offline" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Remover Todas as Mensagens Offline" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Modulo ejabberd SOCKS5 Bytestreams" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publicação de Tópico" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo para Publicar Tópicos do ejabberd" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub requisição de assinante" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Aprovar esta assinatura." #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID do Tópico" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Endereço dos Assinantes" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads junto com as notificações de eventos" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Entregar as notificações de evento" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscritores quando o nodo se elimine" #: 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:3755 msgid "Persist items to storage" msgstr "Persistir elementos ao armazenar" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Um nome familiar para o nó" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persistem" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Permitir subscrições" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Especificar os modelos de acesso" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Listar grupos autorizados" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Especificar o modelo do publicante" #: 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:3771 msgid "Specify the event message type" msgstr "Especificar o tipo de mensagem para o evento" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Máximo tamanho do payload em bytes" #: mod_pubsub.erl:3775 msgid "When to send the last published item" 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" #: 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: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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Houveram erras ao criar esta conta: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." 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: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." 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: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Registros de Contas Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Registrar uma conta Jabber" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Deletar conta Jabber" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Usuário:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Não é 'case insensitive': macbeth é o mesmo que MacBeth e ainda Macbeth. " #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Caracteres não aceitos:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Servidor:" #: mod_register_web.erl:245 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 " "servidor Jabber." #: 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: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 "" "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: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 "" "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." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verificação de Senha" #: mod_register_web.erl:269 msgid "Register" msgstr "Registrar" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Senha Antiga:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nova Senha:" #: 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:480 msgid "Unregister" msgstr "Deletar registro" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscrição" #: mod_roster.erl:1437 msgid "Pending" msgstr "Pendente" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grupos" #: mod_roster.erl:1476 msgid "Validate" msgstr "Validar" #: mod_roster.erl:1485 msgid "Remove" msgstr "Remover" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista de contatos de " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Adicionar ID jabber" #: mod_roster.erl:1622 msgid "Roster" msgstr "Lista de contatos" #: 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:1232 msgid "Name:" msgstr "Nome:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descrição:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membros:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Grupos Exibidos:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupo " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Jabber em Erlang" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Aniversário" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Cidade" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "País" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Sobrenome" #: 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 "" "Preencha o formulário para buscar usuários Jabber. Agrega * ao final de um " "campo para buscar sub-palavras." #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nome completo" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Nome do meio" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nome da organização" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Departamento/Unidade" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Procurar usuários em " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Busca de Usuário vCard" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Módulo vCard para ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Resultados de pesquisa para " #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Este participante foi desconectado da sala de chat por ter enviado uma " #~ "mensagem de erro para outro usuário." #~ 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 "Captcha test failed" #~ msgstr "O CAPTCHA é inválido." ejabberd-16.01/priv/msgs/sk.msg0000644000232200023220000006461612645157216016731 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Konfigurácia prístupu"}. {"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"}. {"Add Jabber ID","PridaÅ¥ Jabber ID"}. {"Add New","PridaÅ¥ nový"}. {"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?"}. {"Allow users to change the subject","PovoliÅ¥ užívateľom meniÅ¥ tému"}. {"Allow users to query other users","PovoliÅ¥ užívateľom dotazovaÅ¥ sa informácie o iných užívateľoch"}. {"Allow users to send invites","PovoliÅ¥ používateľom posielanie pozvánok"}. {"Allow users to send private messages","PovoliÅ¥ užívateľom odosielaÅ¥ súkromné správy"}. {"Allow visitors to change nickname","NávÅ¡tevníci môžu meniÅ¥ prezývky"}. {"Allow visitors to send private messages to","PovoliÅ¥ užívateľom odosielaÅ¥ súkromné správy"}. {"Allow visitors to send status text in presence updates","NávÅ¡tevníci môžu posielaÅ¥ textové informácie v stavových správach"}. {"Allow visitors to send voice requests","PovoliÅ¥ používateľom posielanie pozvánok"}. {"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"}. {"Backup to File at ","Záloha do súboru na "}. {"Backup","ZálohovaÅ¥"}. {"Bad format","Zlý formát"}. {"Birthday","Dátum narodenia"}. {"CAPTCHA web page","Webová stránka CAPTCHA"}. {"Change Password","ZmeniÅ¥ heslo"}. {"Change User Password","ZmeniÅ¥ heslo užívateľa"}. {"Characters not allowed:","Nepovolené znaky:"}. {"Chatroom configuration modified","Nastavenie diskusnej miestnosti bolo zmenené"}. {"Chatroom is created","Diskusná miestnosÅ¥ je vytvorená"}. {"Chatroom is destroyed","Diskusná miestnosÅ¥ je zruÅ¡ená"}. {"Chatroom is started","Diskusná miestnosÅ¥ je obnovená"}. {"Chatroom is stopped","Diskusná miestnosÅ¥ je pozastavená"}. {"Chatrooms","Diskusné miestnosti"}. {"Choose a username and password to register with this server","Zvolte meno užívateľa a heslo pre registráciu na tomto servere"}. {"Choose modules to stop","Vyberte moduly, ktoré majú byÅ¥ zastavené"}. {"Choose storage type of tables","Vyberte typ úložiska pre tabuľky"}. {"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:"}. {"Connections parameters","Parametre spojenia"}. {"Country","Krajina"}. {"CPU Time:","ÄŒas procesoru"}. {"Database","Databáza"}. {"Database Tables Configuration at ","Konfigurácia databázových tabuliek "}. {"December","December"}. {"Default users as participants","Užívatelia sú implicitne Älenmi"}. {"Delete message of the day on all hosts","ZmazaÅ¥ správu dňa na vÅ¡etkých serveroch"}. {"Delete message of the day","ZmazaÅ¥ správu dňa"}. {"Delete Selected","ZmazaÅ¥ vybrané"}. {"Delete User","VymazaÅ¥ užívateľa"}. {"Deliver event notifications","DoruÄiÅ¥ oznamy o udalosti"}. {"Deliver payloads with event notifications","DoruÄiÅ¥ náklad s upozornením na udalosÅ¥"}. {"Description:","Popis:"}. {"Disc only copy","Len kópia disku"}. {"Displayed Groups:","Zobrazené skupiny:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Nevyzrádzajte heslo nikomu, ani administrátorom tohoto Jabber servera."}. {"Dump Backup to Text File at ","UložiÅ¥ zálohu do textového súboru na "}. {"Dump to Text File","UložiÅ¥ do textového súboru"}. {"Edit Properties","EditovaÅ¥ vlastnosti"}. {"Either approve or decline the voice request.","Povolte alebo zamietnite žiadosÅ¥ o Voice."}. {"ejabberd IRC module","ejabberd IRC modul"}. {"ejabberd MUC module","ejabberd MUC modul"}. {"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","ejabberd Web Admin"}. {"Elements","Prvky"}. {"Email","E-mail"}. {"Enable logging","Zapnúť zaznamenávanie histórie"}. {"Encoding for server ~b","Kódovanie pre server ~b"}. {"End User Session","UkonÄiÅ¥ reláciu užívateľa"}. {"Enter list of {Module, [Options]}","Vložte zoznam modulov {Modul, [Parametre]}"}. {"Enter nickname you want to register","Zadajte prezývku, ktorú chcete registrovaÅ¥"}. {"Enter path to backup file","Zadajte cestu k súboru so zálohou"}. {"Enter path to jabberd14 spool dir","Zadajte cestu k jabberd14 spool adresáru"}. {"Enter path to jabberd14 spool file","Zadajte cestu k spool súboru jabberd14"}. {"Enter path to text file","Zadajte cestu k textovému súboru"}. {"Enter the text you see","Zadajte zobrazený text"}. {"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.","Vložte meno používateľa a kódovanie, ktoré chcete používaÅ¥ pri pripojení na IRC servery. Kliknutím na tlaÄítko 'ÄŽalej' môžete zadaÅ¥ niektoré ÄalÅ¡ie hodnoty. Pomocou 'UkonÄiÅ¥ ' uložíte nastavenia."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Vložte meno používateľa, kódovanie, porty a heslo ktoré chcete používaÅ¥ pri pripojení na IRC server"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"Error","Chyba"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Príklad: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Pre vyhľadanie Jabber používateľa vyplňte formulár (pridajte znak * na koniec, pre vyhľadanie podreÅ¥azca)"}. {"Friday","Piatok"}. {"From","Od"}. {"From ~s","Od ~s"}. {"Full Name","Celé meno: "}. {"Get Number of Online Users","ZobraziÅ¥ poÄet pripojených užívateľov"}. {"Get Number of Registered Users","ZobraziÅ¥ poÄet registrovaných užívateľov"}. {"Get User Last Login Time","ZobraziÅ¥ Äas posledného prihlásenia"}. {"Get User Password","ZobraziÅ¥ heslo užívateľa"}. {"Get User Statistics","ZobraziÅ¥ Å¡tatistiku užívateľa"}. {"Grant voice to this person?","PrideltiÅ¥ Voice tejto osobe?"}. {"Group ","Skupina "}. {"Groups","Skupiny"}. {"has been banned","bol(a) zablokovaný(á)"}. {"has been kicked because of an affiliation change","bol vyhodený(á) kvôli zmene priradenia"}. {"has been kicked because of a system shutdown","bol vyhodený(á) kvôli reÅ¡tartu systému"}. {"has been kicked because the room has been changed to members-only","bol vyhodený(á), pretože miestnosÅ¥ bola vyhradená len pre Älenov"}. {"has been kicked","bol(a) vyhodený(á) z miestnosti"}. {" has set the subject to: ","zmenil(a) tému na: "}. {"Host","Server"}. {"If you don't see the CAPTCHA image here, visit the web page.","Pokiaľ nevidíte obrázok CAPTCHA, navÅ¡tívte webovú stránku."}. {"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.","Ak chcete zadaÅ¥ iné porty, heslá a kódovania pre IRC servery, vyplnte zoznam s hodnotami vo formáte '{\"irc server\",\"kódovanie\", \"port\", \"heslo\"}'. Predvolenéi hodnoty pre túto službu sú: kódovanie \"~s\", port ~p a žiadne heslo."}. {"Import Directory","Import adresára"}. {"Import File","Import súboru"}. {"Import user data from jabberd14 spool file:","ImportovaÅ¥ dáta užívateľov z jabberd14 spool súboru:"}. {"Import User from File at ","ImportovaÅ¥ užívateľa zo súboru na "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importovat dáta užívateľov zo súboru PIEFXIS (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","IRC kanál (bez poÄiatoÄnej #)"}. {"IRC server","IRC server"}. {"IRC settings","Nastavania IRC"}. {"IRC Transport","IRC Transport"}. {"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é"}. {"January","Január"}. {"Join IRC channel","Pripojit IRC kanál"}. {"joins the room","vstúpil(a) do miestnosti"}. {"Join the IRC channel here.","PropojiÅ¥ IRC kanál sem."}. {"Join the IRC channel in this Jabber ID: ~s","Pripojit IRC kanál k tomuto Jabber ID: ~s"}. {"July","Júl"}. {"June","Jún"}. {"Last Activity","Posledná aktivita"}. {"Last login","Posledné prihlásenie"}. {"Last month","Posledný mesiac"}. {"Last year","Posledný rok"}. {"leaves the room","odiÅ¡iel(a) z miestnosti"}. {"Listened Ports at ","Otvorené porty na "}. {"Listened Ports","Otvorené portov"}. {"List of modules to start","Zoznam modulov, ktoré majú byÅ¥ spustené"}. {"Low level update script","Nízkoúrovňový aktualizaÄný skript"}. {"Make participants list public","NastaviÅ¥ zoznam zúÄastnených ako verejný"}. {"Make room CAPTCHA protected","ChrániÅ¥ miestnosÅ¥ systémom CAPTCHA"}. {"Make room members-only","NastaviÅ¥ miestnosÅ¥ len pre Älenov"}. {"Make room moderated","NastaviÅ¥ miestnosÅ¥ ako moderovanú"}. {"Make room password protected","ChrániÅ¥ miestnosÅ¥ heslom"}. {"Make room persistent","NastaviÅ¥ miestnosÅ¥ ako trvalú"}. {"Make room public searchable","NastaviÅ¥ miestnosÅ¥ ako verejne prehľadávateľnú"}. {"March","Marec"}. {"Maximum Number of Occupants","PoÄet úÄastníkov"}. {"Max # of items to persist","Maximálny poÄet položiek, ktoré je možné natrvalo uložiÅ¥"}. {"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"}. {"Modules","Moduly"}. {"Monday","Pondelok"}. {"Name:","Meno:"}. {"Name","Meno"}. {"Never","Nikdy"}. {"New Password:","Nové heslo:"}. {"Nickname","Prezývka"}. {"Nickname Registration at ","Registrácia prezývky na "}. {"Nickname ~s does not exist in the room","Prezývka ~s v miestnosti neexistuje"}. {"nobody","nikto"}. {"No body provided for announce message","Správa neobsahuje text"}. {"No Data","Žiadne dáta"}. {"Node ID","ID uzlu"}. {"Node not found","Uzol nenájdený"}. {"Nodes","Uzly"}. {"No limit","Bez limitu"}. {"None","NiÄ"}. {"No resource provided","Nebol poskytnutý žiadny zdroj"}. {"Not Found","Nebol nájdený"}. {"Notify subscribers when items are removed from the node","UpozorniÅ¥ prihlásených používateľov na odstránenie položiek z uzlu"}. {"Notify subscribers when the node configuration changes","UpozorniÅ¥ prihlásených používateľov na zmenu nastavenia uzlu"}. {"Notify subscribers when the node is deleted","UpozorniÅ¥ prihlásených používateľov na zmazanie uzlu"}. {"November","November"}. {"Number of occupants","PoÄet zúÄastnených"}. {"Number of online users","PoÄet online užívateľov"}. {"Number of registered users","PoÄet registrovaných užívateľov"}. {"October","Október"}. {"Offline Messages:","Offline správy"}. {"Offline Messages","Offline správy"}. {"OK","OK"}. {"Old Password:","Staré heslo:"}. {"Online","Online"}. {"Online Users:","Online používatelia:"}. {"Online Users","Online užívatelia"}. {"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"}. {"Owner privileges required","Sú vyžadované práva vlastníka"}. {"Packet","Paket"}. {"Password ~b","Heslo ~b"}. {"Password:","Heslo:"}. {"Password","Heslo"}. {"Password Verification:","Overenie hesla"}. {"Password Verification","Overenie hesla"}. {"Path to Dir","Cesta k adresáru"}. {"Path to File","Cesta k súboru"}. {"Pending","ÄŒakajúce"}. {"Period: ","ÄŒas:"}. {"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"}. {"Present real Jabber IDs to","ZobrazovaÅ¥ skutoÄné Jabber ID"}. {"private, ","súkromná, "}. {"Protocol","Protokol"}. {"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"}. {"Register","Zoznam kontaktov"}. {"Registration in mod_irc for ","Registrácia do mod_irc na"}. {"Remote copy","Vzdialená kópia"}. {"Remove All Offline Messages","OdstrániÅ¥ vÅ¡etky offline správy"}. {"Remove","OdstrániÅ¥"}. {"Remove User","OdstrániÅ¥ užívateľa"}. {"Replaced by new connection","Nahradené novým spojením"}. {"Resources","Zdroje"}. {"Restart","ReÅ¡tart"}. {"Restart Service","ReÅ¡tartovaÅ¥ službu"}. {"Restore Backup from File at ","ObnoviÅ¥ zálohu zo súboru na "}. {"Restore binary backup after next ejabberd restart (requires less memory):","ObnoviÅ¥ binárnu zálohu pri nasledujúcom reÅ¡tarte ejabberd (vyžaduje menej pamäte)"}. {"Restore binary backup immediately:","Okamžite obnoviÅ¥ binárnu zálohu:"}. {"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"}. {"Roster groups allowed to subscribe","Skupiny kontaktov, ktoré môžu odoberaÅ¥"}. {"Roster of ","Zoznam kontaktov "}. {"Roster size","PoÄet kontaktov v zozname"}. {"Roster","Zoznam kontaktov"}. {"RPC Call Error","Chyba RPC volania"}. {"Running Nodes","Bežiace uzly"}. {"~s access rule configuration","~s konfigurácia prístupového pravidla"}. {"Saturday","Sobota"}. {"Script check","Kontrola skriptu"}. {"Search Results for ","HľadaÅ¥ výsledky pre "}. {"Search users in ","HľadaÅ¥ užívateľov v "}. {"Send announcement to all online users","OdoslaÅ¥ zoznam vÅ¡etkým online používateľom"}. {"Send announcement to all online users on all hosts","OdoslaÅ¥ oznam vÅ¡etkým online používateľom na vÅ¡etkých serveroch"}. {"Send announcement to all users","OdoslaÅ¥ oznam vÅ¡etkým používateľom"}. {"Send announcement to all users on all hosts","PoslaÅ¥ oznámenie vÅ¡etkým užívateľom na vÅ¡etkých serveroch"}. {"September","September"}. {"Server ~b","Server ~b"}. {"Set message of the day and send to online users","NastaviÅ¥ správu dňa a odoslaÅ¥ ju online používateľom"}. {"Set message of the day on all hosts and send to online users","NastaviÅ¥ správu dňa na vÅ¡etkých serveroch a poslaÅ¥ ju online užívateľom"}. {"Shared Roster Groups","Skupiny pre zdieľaný zoznam kontaktov"}. {"Show Integral Table","ZobraziÅ¥ kompletnú tabuľku"}. {"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 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"}. {"~s's Offline Messages Queue","~s Offline správy"}. {"Start Modules at ","SpustiÅ¥ moduly na "}. {"Start Modules","SpustiÅ¥ moduly"}. {"Start","Å tart"}. {"Statistics of ~p","Å tatistiky ~p"}. {"Statistics","Å tatistiky"}. {"Stop Modules at ","ZastaviÅ¥ moduly na "}. {"Stop Modules","ZastaviÅ¥ moduly"}. {"Stopped Nodes","Zastavené uzly"}. {"Stop","ZastaviÅ¥"}. {"Storage Type","Typ úložiska"}. {"Store binary backup:","UložiÅ¥ binárnu zálohu:"}. {"Store plain text backup:","UložiÅ¥ zálohu do textového súboru:"}. {"Subject","Predmet"}. {"Submit","OdoslaÅ¥"}. {"Submitted","Odoslané"}. {"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: "}. {"There was an error deleting the account: ","Pri ruÅ¡ení úÄtu nastala chyba:"}. {"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."}. {"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"}. {"Update","AktualizovaÅ¥"}. {"Update message of the day (don't send)","AktualizovaÅ¥ správu dňa (neodosielaÅ¥)"}. {"Update message of the day on all hosts (don't send)","UpraviÅ¥ správu dňa na vÅ¡etkých serveroch"}. {"Update plan","AktualizovaÅ¥ plán"}. {"Update script","Aktualizované skripty"}. {"Uptime:","Uptime:"}. {"Use of STARTTLS required","Je vyžadované použitie STARTTLS "}. {"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"}. ejabberd-16.01/priv/msgs/no.msg0000644000232200023220000006251112645157216016720 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Tilgangskonfigurasjon"}. {"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"}. {"Add Jabber ID","Legg til Jabber ID"}. {"Add New","Legg til ny"}. {"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 "}. {"Allow users to change the subject","Tillat brukere Ã¥ endre emne"}. {"Allow users to query other users","Tillat brukere Ã¥ sende forespørsel til andre brukere"}. {"Allow users to send invites","Tillat brukere Ã¥ sende invitasjoner"}. {"Allow users to send private messages","Tillat brukere Ã¥ sende private meldinger"}. {"Allow visitors to change nickname","Tillat besøkende Ã¥ endre kallenavn"}. {"Allow visitors to send private messages to","Tillat brukere Ã¥ sende private meldinger til"}. {"Allow visitors to send status text in presence updates","Tillat besøkende Ã¥ sende status tekst i "}. {"Allow visitors to send voice requests","Tillat brukere Ã¥ sende lyd forespørsler"}. {"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"}. {"Backup","Sikkerhetskopier"}. {"Backup to File at ","Sikkerhetskopiere til Fil pÃ¥ "}. {"Bad format","Feil format"}. {"Birthday","Fødselsdag"}. {"CAPTCHA web page","CAPTCHA web side"}. {"Change Password","Endre Passord"}. {"Change User Password","Endre Brukers Passord"}. {"Characters not allowed:","Ikke godtatte tegn:"}. {"Chatroom configuration modified","Samtalerommets konfigurasjon er endret"}. {"Chatroom is created","Samtalerom er opprettet"}. {"Chatroom is destroyed","Samtalerom er fjernet"}. {"Chatroom is started","Samtalerom er startet"}. {"Chatroom is stopped","Samtalerom er stoppet"}. {"Chatrooms","Samtalerom"}. {"Choose a username and password to register with this server","Velg et brukernavn og passord for Ã¥ registrere pÃ¥ "}. {"Choose modules to stop","Velg hvilke moduler som skal stoppes"}. {"Choose storage type of tables","Velg lagringstype for tabeller"}. {"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:"}. {"Connections parameters","Tilkoblings parametere"}. {"Country","Land"}. {"CPU Time:","CPU Tid:"}. {"Database","Database"}. {"Database Tables Configuration at ","Database Tabell Konfigurasjon pÃ¥ "}. {"December","desember"}. {"Default users as participants","Standard brukere som deltakere"}. {"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 User","Slett Bruker"}. {"Deliver event notifications","Lever begivenhets kunngjøringer"}. {"Deliver payloads with event notifications","Send innhold sammen med kunngjøringer"}. {"Description:","Beskrivelse:"}. {"Disc only copy","Kun diskkopi"}. {"Displayed Groups:","Viste grupper:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Ikke fortell passordet til noen, ikke en gang til administratoren av Jabber serveren."}. {"Dump Backup to Text File at ","Dump Sikkerhetskopi til Tekstfil pÃ¥ "}. {"Dump to Text File","Dump til Tekstfil"}. {"Edit Properties","Redigere Egenskaper"}. {"Either approve or decline the voice request.","Enten godkjenn eller forby lyd forespørselen"}. {"ejabberd IRC module","ejabberd IRC modul"}. {"ejabberd MUC module","ejabberd MUC modul"}. {"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","ejabberd Web Admin"}. {"Elements","Elementer"}. {"Email","Epost"}. {"Enable logging","SlÃ¥ pÃ¥ logging"}. {"Encoding for server ~b","Tekstkoding for server ~b"}. {"End User Session","Avslutt Bruker Sesjon"}. {"Enter list of {Module, [Options]}","Skriv inn en liste av {Module, [Options]}"}. {"Enter nickname you want to register","Skriv inn kallenavnet du ønsker Ã¥ registrere"}. {"Enter path to backup file","Skriv inn sti til sikkerhetskopi filen"}. {"Enter path to jabberd14 spool dir","Skriv inn sti til jabberd14 spoolkatalog"}. {"Enter path to jabberd14 spool file","Skriv inn sti til jabberd14 spoolfil"}. {"Enter path to text file","Skriv inn sti til tekstfil"}. {"Enter the text you see","Skriv inn teksten du ser"}. {"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.","Angi brukernavn og kodinger du ønsker Ã¥ bruke for Ã¥ koble til IRC servere. Trykk 'Neste' for Ã¥ fÃ¥ flere felt for Ã¥ fylle i. Trykk 'Fullfør' for Ã¥ lagre innstillingene."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Skriv brukernavn, tekstkoding, porter og passord du ønsker Ã¥ bruke for tilkobling til IRC servere"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"Error","Feil"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Eksempel: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Fyll inn skjemaet for Ã¥ søke etter Jabber bruker (Legg til * pÃ¥ slutten av feltet for Ã¥ treffe alle som starter slik)"}. {"Friday","fredag"}. {"From","Fra"}. {"From ~s","Fra ~s"}. {"Full Name","Fullstendig Navn"}. {"Get Number of Online Users","Vis Antall Tilkoblede Brukere"}. {"Get Number of Registered Users","Vis Antall Registrerte Brukere"}. {"Get User Last Login Time","Vis Brukers Siste PÃ¥loggings Tidspunkt"}. {"Get User Password","Hent Brukers Passord"}. {"Get User Statistics","Vis Bruker Statistikk"}. {"Grant voice to this person?","Gi lyd til denne personen?"}. {"Group ","Gruppe "}. {"Groups","Grupper"}. {"has been banned","har blitt bannlyst"}. {"has been kicked because of an affiliation change","har blitt kastet ut pÃ¥ grunn av en tilknytnings endring"}. {"has been kicked because of a system shutdown","har blitt kastet ut pÃ¥ grunn av at systemet avslutter"}. {"has been kicked because the room has been changed to members-only","har blitt kastet ut pÃ¥ grunn av at rommet er endret til kun-for-medlemmer"}. {"has been kicked","har blitt kastet ut"}. {" has set the subject to: "," har satt emnet til: "}. {"Host","Maskin"}. {"If you don't see the CAPTCHA image here, visit the web page.","Dersom du ikke ser CAPTCHA bilde her, besøk web siden. "}. {"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.","Om du ønsker Ã¥ spesifisere tekstkoding for IRC tjenere, fyller du ut en liste med verdier i formatet '{\"irc server\", \"encoding\", port, \"password\"}'. Denne tjenesten bruker \"~s\" som standard, port ~p, empty password."}. {"Import Directory","Importer Katalog"}. {"Import File","Importer File"}. {"Import user data from jabberd14 spool file:","Importer bruker data fra jabberd14 spoolfiler:"}. {"Import User from File at ","Importer Bruker fra Fil pÃ¥ "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importer brukeres data fra en PIEFXIS fil (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","IRC kanal (ikke skriv den første #)"}. {"IRC server","IRC server"}. {"IRC settings","IRC instillinger"}. {"IRC Transport","IRC Transport"}. {"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"}. {"January","januar"}. {"Join IRC channel","Bli med i IRC kanal"}. {"joins the room","kommer inn i rommet"}. {"Join the IRC channel here.","Bli med i IRC kanalen her. "}. {"Join the IRC channel in this Jabber ID: ~s","Bli med i IRC kanalen med denne Jabber ID: ~s"}. {"July","juli"}. {"June","juni"}. {"Last Activity","Siste Aktivitet"}. {"Last login","Siste pÃ¥logging"}. {"Last month","Siste mÃ¥ned"}. {"Last year","Siste Ã¥ret"}. {"leaves the room","forlater rommet"}. {"Listened Ports at ","Lyttende Porter pÃ¥ "}. {"Listened Ports","Lyttende Porter"}. {"List of modules to start","Liste over moduler som skal startes"}. {"Low level update script","LavnivÃ¥ oppdaterings skript"}. {"Make participants list public","Gjør deltakerlisten offentlig"}. {"Make room CAPTCHA protected","Gjør rommet CAPTCHA beskyttet"}. {"Make room members-only","Gjør rommet tilgjengelig kun for medlemmer"}. {"Make room moderated","Gjør rommet redaktørstyrt"}. {"Make room password protected","Passordbeskytt rommet"}. {"Make room persistent","Gjør rommet permanent"}. {"Make room public searchable","Gjør rommet offentlig søkbart"}. {"March","mars"}. {"Maximum Number of Occupants","Maksimum Antall Deltakere"}. {"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"}. {"Modules","Moduler"}. {"Monday","mandag"}. {"Name:","Navn:"}. {"Name","Navn"}. {"Never","Aldri"}. {"New Password:","Nytt Passord:"}. {"Nickname","Kallenavn"}. {"Nickname Registration at ","Registrer Kallenavn pÃ¥ "}. {"Nickname ~s does not exist in the room","Kallenavn ~s eksisterer ikke i dette rommet"}. {"nobody","ingen"}. {"No body provided for announce message","Ingen meldingskropp gitt for kunngjørings melding"}. {"No Data","Ingen Data"}. {"Node ID","Node ID"}. {"Node not found","Noden finnes ikke"}. {"Nodes","Noder"}. {"No limit","Ingen grense"}. {"None","Ingen"}. {"No resource provided","Ingen ressurs angitt"}. {"Not Found","Finnes Ikke"}. {"Notify subscribers when items are removed from the node","Informer abonnenter nÃ¥r elementer fjernes fra noden"}. {"Notify subscribers when the node configuration changes","Informer abonnenter nÃ¥r node konfigurasjonen endres"}. {"Notify subscribers when the node is deleted","Informer abonnenter nÃ¥r noden slettes"}. {"November","november"}. {"Number of occupants","Antall deltakere"}. {"Number of online users","Antall tilkoblede brukere"}. {"Number of registered users","Antall registrerte brukere"}. {"October","oktober"}. {"Offline Messages:","Frakoblede Meldinger:"}. {"Offline Messages","Frakoblede Meldinger"}. {"OK","OK"}. {"Old Password:","Gammelt Passord:"}. {"Online","Tilkoblet"}. {"Online Users:","Tilkoblede Brukere:"}. {"Online Users","Tilkoblede Brukere"}. {"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"}. {"Owner privileges required","Eierprivilegier kreves"}. {"Packet","Pakke"}. {"Password ~b","Passord ~b"}. {"Password:","Passord:"}. {"Password","Passord"}. {"Password Verification:","Passord Bekreftelse:"}. {"Password Verification","Passord Bekreftelse"}. {"Path to Dir","Sti til Katalog"}. {"Path to File","Sti til Fil"}. {"Pending","Ventende"}. {"Period: ","Periode: "}. {"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"}. {"Present real Jabber IDs to","Presenter ekte Jabber IDer til"}. {"private, ","privat, "}. {"Protocol","Protokoll"}. {"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"}. {"Register","Registrer"}. {"Registration in mod_irc for ","Registrering i mod_irc for "}. {"Remote copy","Lagres ikke lokalt"}. {"Remove All Offline Messages","Fjern Alle Frakoblede Meldinger"}. {"Remove","Fjern"}. {"Remove User","Fjern Bruker"}. {"Replaced by new connection","Erstattet av en ny tilkobling"}. {"Resources","Ressurser"}. {"Restart Service","Start Tjeneste pÃ¥ Nytt"}. {"Restart","Starte pÃ¥ nytt"}. {"Restore Backup from File at ","Gjenopprett fra Sikkerhetsopifil pÃ¥ "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Gjenopprette binær backup etter neste ejabberd omstart (krever mindre minne):"}. {"Restore binary backup immediately:","Gjenopprette binær backup umiddelbart:"}. {"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"}. {"Roster groups allowed to subscribe","Kontaktliste grupper som tillates Ã¥ abonnere"}. {"Roster","Kontaktliste"}. {"Roster of ","Kontaktliste for "}. {"Roster size","Kontaktliste størrelse"}. {"RPC Call Error","RPC Kall Feil"}. {"Running Nodes","Kjørende Noder"}. {"~s access rule configuration","tilgangsregel konfigurasjon for ~s"}. {"Saturday","lørdag"}. {"Script check","Skript sjekk"}. {"Search Results for ","Søke Resultater for "}. {"Search users in ","Søk etter brukere i "}. {"Send announcement to all online users on all hosts","Send kunngjøring til alle tilkoblede brukere pÃ¥ alle "}. {"Send announcement to all online users","Send kunngjøring alle tilkoblede brukere"}. {"Send announcement to all users on all hosts","Send kunngjøring til alle brukere pÃ¥ alle maskiner"}. {"Send announcement to all users","Send kunngjøring til alle brukere"}. {"September","september"}. {"Server ~b","Server ~b"}. {"Server:","Server:"}. {"Set message of the day and send to online users","Angi melding for dagen og send til tilkoblede brukere"}. {"Set message of the day on all hosts and send to online users","Angi melding for dagen pÃ¥ alle maskiner og send til "}. {"Shared Roster Groups","Delte Kontaktgrupper"}. {"Show Integral Table","Vis Integral Tabell"}. {"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 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"}. {"~s's Offline Messages Queue","~ss kø for Frakoblede Meldinger"}. {"Start Modules at ","Start Moduler pÃ¥ "}. {"Start Modules","Start Moduler"}. {"Start","Start"}. {"Statistics of ~p","Statistikk for ~p"}. {"Statistics","Statistikk"}. {"Stop Modules at ","Stopp Moduler pÃ¥ "}. {"Stop Modules","Stop Moduler"}. {"Stopped Nodes","Stoppede Noder"}. {"Stop","Stoppe"}. {"Storage Type","Lagringstype"}. {"Store binary backup:","Lagre binær sikkerhetskopi:"}. {"Store plain text backup:","Lagre rentekst sikkerhetskopi:"}. {"Subject","Tittel"}. {"Submit","Send"}. {"Submitted","Innsendt"}. {"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:"}. {"There was an error deleting the account: ","En feil skjedde under sletting av kontoen: "}. {"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."}. {"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"}. {"Update message of the day (don't send)","Oppdater melding for dagen (ikke send)"}. {"Update message of the day on all hosts (don't send)","Oppdater melding for dagen pÃ¥ alle maskiner (ikke send)"}. {"Update","Oppdatere"}. {"Update plan","Oppdaterings plan"}. {"Update script","Oppdaterings skript"}. {"Uptime:","Oppetid:"}. {"Use of STARTTLS required","Bruk av STARTTLS kreves"}. {"User","Bruker"}. {"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"}. ejabberd-16.01/priv/msgs/he.msg0000644000232200023220000007544512645157216016712 0ustar debalancedebalance%% -*- 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","הוסף מזהה 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?","להתיר למזהה 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 voice requests","התר ×œ×ž×‘×§×¨×™× ×œ×©×œ×•×— בקשות ביטוי"}. {"All Users","כל המשתמשי×"}. {"Announcements","בשורות"}. {"anyone","לכל ×חד"}. {"A password is required to enter this room","נדרשת סיסמה כדי להיכנס ×ל חדר ×–×”"}. {"April","×פריל"}. {"August","×וגוסט"}. {"Backup Management","ניהול גיבוי"}. {"Backup of ~p","גיבוי של ~p"}. {"Backup to File at ","גבה לקובץ ×צל "}. {"Backup","גיבוי"}. {"Bad format","פורמט רע"}. {"Birthday","×™×•× ×”×•×œ×“×ª"}. {"CAPTCHA web page","עמוד רשת CAPTCHA"}. {"Change Password","שנה סיסמה"}. {"Change User Password","שנה סיסמת משתמש"}. {"Characters not allowed:","×ª×•×•×™× ×œ× ×ž×•×¨×©×™×:"}. {"Chatroom configuration modified","תצורת חדר שיחה שונתה"}. {"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","בחר ×ž×•×“×•×œ×™× ×œ×”×¤×¡×§×”"}. {"Choose storage type of tables","בחר טיפוס ×חסון של טבל×ות"}. {"Choose whether to approve this entity's subscription.","בחר ×”×× ×œ×שר ×ת ההרשמה של ישות זו."}. {"City","עיר"}. {"Commands","פקודות"}. {"Conference room does not exist","חדר ועידה ×œ× ×§×™×™×"}. {"Configuration of room ~s","תצורת חדר ~s"}. {"Configuration","תצורה"}. {"Connected Resources:","מש××‘×™× ×ž×—×•×‘×¨×™×:"}. {"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 Selected","מחק נבחרות"}. {"Delete User","מחק משתמש"}. {"Deliver 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","השלך לקובץ טקסט"}. {"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"}. {"ejabberd Web Admin","מנהל רשת ejabberd"}. {"Elements","×למנטי×"}. {"Email","דו×״ל"}. {"Enable logging","×פשר ×¨×™×©×•× ×¤×¢×™×œ×•×ª"}. {"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","הזן נתיב למדור סליל (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"}. {"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):"}. {"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 מבוקש (ב×פשרותך להוסיף * בסוף שדה כדי להת××™× ×œ×ž×—×¨×•×–×ª-משנה)"}. {"Friday","×™×•× ×©×™×©×™"}. {"From ~s","מ×ת ~s"}. {"From","מ×ת"}. {"Full Name","×©× ×ž×œ×"}. {"Get Number of Online Users","השג מספר של ×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×"}. {"Get Number of Registered Users","השג מספר של ×ž×©×ª×ž×©×™× ×¨×©×•×ž×™×"}. {"Get User Last Login Time","השג זמן כניסה ×חרון של משתמש"}. {"Get User Password","השג סיסמת משתמש"}. {"Get User Statistics","השג סטטיסטיקת משתמש"}. {"Grant voice to this person?","להעניק ביטוי ל×ישיות זו?"}. {"Groups","קבוצות"}. {"Group ","קבוצה "}. {"has been banned","× ×סר/×”"}. {"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 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, סיסמה ריקה."}. {"Import Directory","×™×™×‘×•× ×ž×“×•×¨"}. {"Import File","×™×™×‘×•× ×§×•×‘×¥"}. {"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 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"}. {"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","ידועה כעת בכינוי"}. {"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"}. {"January","ינו×ר"}. {"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"}. {"July","יולי"}. {"June","יוני"}. {"Last Activity","פעילות ×חרונה"}. {"Last login","כניסה ×חרונה"}. {"Last month","חודש ×חרון"}. {"Last year","שנה ×חרונה"}. {"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","הפוך חדר לחדר עבור חברי×-בלבד"}. {"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"}. {"Modules","מודולי×"}. {"Module","מודול"}. {"Monday","×™×•× ×©× ×™"}. {"Multicast","שידור מרובב"}. {"Multi-User Chat","שיחה מרובת משתמשי×"}. {"Name:","ש×:"}. {"Name","ש×"}. {"Never","××£ פע×"}. {"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","מזהה צומת (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","הודע ×ž× ×•×™×™× ×›×שר הצומת נמחק"}. {"November","נובמבר"}. {"Number of occupants","מספר של נוכחי×"}. {"Number of online users","מספר של ×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×"}. {"Number of registered users","מספר של ×ž×©×ª×ž×©×™× ×¨×©×•×ž×™×"}. {"October","×וקטובר"}. {"Offline Messages:","הודעות ×œ× ×ž×§×•×•× ×•×ª:"}. {"Offline Messages","הודעות ×œ× ×ž×§×•×•× ×•×ª"}. {"OK","×ישור"}. {"Old Password:","סיסמה ישנה:"}. {"Online Users:","×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×:"}. {"Online Users","×ž×©×ª×ž×©×™× ×ž×§×•×•× ×™×"}. {"Online","מקוון"}. {"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 יוצ××™×"}. {"Owner privileges required","נדרשות הרש×ות בעלי×"}. {"Packet","חבילת מידע"}. {"Password ~b","סיסמה ~b"}. {"Password Verification:","×ימות סיסמה:"}. {"Password Verification","×ימות סיסמה"}. {"Password:","סיסמה:"}. {"Password","סיסמה"}. {"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, wait for a while before sending new voice request","×× ×, המתן לזמן מה לפני שליחת בקשת ביטוי חדשה"}. {"Pong","פונג"}. {"Port ~b","פורט ~b"}. {"Port","פורט"}. {"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","טהר ×ת כל ×”×¤×¨×™×˜×™× ×›×שר ×”×ž×¤×¨×¡× ×”×¨×œ×•×•× ×˜×™ הופך לבלתי מקוון"}. {"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:","×ž×©×ª×ž×©×™× ×¨×©×•×ž×™×:"}. {"Registered Users","×ž×©×ª×ž×©×™× ×¨×©×•×ž×™×"}. {"Register","הרש×"}. {"Registration in mod_irc for ","×¨×™×©×•× ×‘×ª×•×š mod_irc עבור "}. {"Remote copy","העתק מרוחק"}. {"Remove All Offline Messages","הסר ×ת כל ההודעות ×”×œ× ×ž×§×•×•× ×•×ª"}. {"Remove User","הסר משתמש"}. {"Remove","הסר"}. {"Replaced by new connection","הוחלף בחיבור חדש"}. {"Resources","מש×בי×"}. {"Restart Service","×תחל שירות"}. {"Restart","×תחל"}. {"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:","שחזר גיבוי טקסט גלוי (plain text) ל×לתר:"}. {"Restore","שחזר"}. {"Room Configuration","תצורת חדר"}. {"Room creation is denied by service policy","יצירת חדר נדחתה על ידי פוליסת שירות"}. {"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 ","תוצ×ות חיפוש עבור "}. {"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:","שרת:"}. {"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"}. {"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","התחל מודולי×"}. {"Start","התחל"}. {"Statistics of ~p","סטטיסטיקות של ~p"}. {"Statistics","סטטיסטיקה"}. {"Stop Modules at ","הפסק ×ž×•×“×•×œ×™× ×צל "}. {"Stop Modules","הפסק מודולי×"}. {"Stopped Nodes","×¦×ž×ª×™× ×©× ×¤×¡×§×•"}. {"Stop","הפסק"}. {"Storage Type","טיפוס ×חסון"}. {"Store binary backup:","×חסן גיבוי בינ×רי:"}. {"Store plain text backup:","×חסן גיבוי טקסט גלוי (plain text):"}. {"Subject","נוש×"}. {"Submitted","נשלח"}. {"Submit","שלח"}. {"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: ","×ירעה שגי××” בשינוי הסיסמה: "}. {"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 ×–×”."}. {"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","בטל רישו×"}. {"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 Management","ניהול משתמשי×"}. {"Username:","×©× ×ž×©×ª×ž×©:"}. {"Users are not allowed to register accounts so quickly","×ž×©×ª×ž×©×™× ××™× × ×ž×•×¨×©×™× ×œ×¨×©×•× ×—×©×‘×•× ×•×ª כל כך במהירות"}. {"Users Last Activity","פעילות ×ž×©×ª×ž×©×™× ×חרונה"}. {"User ~s","משתמש ~s"}. {"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.","רשימת הפרטיות הפעילה שלך ×סרה ×ת הניתוב של סטנזה זו."}. {"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"}. ejabberd-16.01/priv/msgs/no.po0000644000232200023220000014267612645157216016563 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: Stian B. Barmen \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Norwegian (bokmÃ¥l)\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Bruk av STARTTLS kreves" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Ingen ressurs angitt" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Erstattet av en ny tilkobling" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Skriv inn teksten du ser" #: 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: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:227 msgid "CAPTCHA web page" msgstr "CAPTCHA web side" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Captchaen er ikke gyldig" #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "Uautorisert" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administrasjon" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "RÃ¥" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Tilgangsregler" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "tilgangsregel konfigurasjon for ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuella Maskiner" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Brukere" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Tilkoblede Brukere" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Brukers Siste Aktivitet" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periode: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Siste mÃ¥ned" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Siste Ã¥ret" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "All aktivitet" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Vis Ordinær Tabell" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Vis Integral Tabell" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistikk" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Finnes Ikke" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Noden finnes ikke" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Legg til ny" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Maskin" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrerte Brukere" #: 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:1459 msgid "Offline Messages" msgstr "Frakoblede Meldinger" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Siste Aktivitet" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Aldri" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Tilkoblet" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrerte Brukere:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "UtgÃ¥ende s2s Koblinger" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "UtgÃ¥ende s2s Koblinger" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Bruker " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Tilkoblede Ressurser:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Passord:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Fjern Bruker" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Ingen Data" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Noder" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Kjørende Noder" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Stoppede Noder" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Node " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sikkerhetskopier" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Lyttende Porter" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Oppdatere" #: 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:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stoppe" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduler" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC Kall Feil" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Database Tabeller pÃ¥ " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Navn" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Lagringstype" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementer" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Minne" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Feil" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Sikkerhetskopi av " #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Lagre binær sikkerhetskopi:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Gjenopprette binær backup umiddelbart:" #: 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:1999 msgid "Store plain text backup:" msgstr "Lagre rentekst sikkerhetskopi:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Gjenopprette rentekst sikkerhetskopi umiddelbart:" #: 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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importer bruker data fra jabberd14 spoolfiler:" #: 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:2115 msgid "Listened Ports at " msgstr "Lyttende Porter pÃ¥ " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduler pÃ¥ " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistikk for ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Oppetid:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU Tid:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Sendte Transaksjoner:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Avbrutte Transasksjoner:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Omstartede Transasksjoner:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Loggede Transasksjoner:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Oppdater " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Oppdaterings plan" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Endrede moduler" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Oppdaterings skript" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "LavnivÃ¥ oppdaterings skript" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Skript sjekk" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokoll" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Alternativer" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Start" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Kommandoer" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Virkelig slette melding for dagen?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Tittel" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Meldingskropp" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Ingen meldingskropp gitt for kunngjørings melding" #: mod_announce.erl:662 msgid "Announcements" msgstr "Kunngjøringer" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Send kunngjøring til alle brukere" #: 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:668 msgid "Send announcement to all online users" msgstr "Send kunngjøring alle tilkoblede brukere" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Oppdater melding for dagen (ikke send)" #: 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:680 msgid "Delete message of the day" msgstr "Slett melding for dagen" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Slett melding for dagen pÃ¥ alle maskiner" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Konfigurasjon" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Start Moduler" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Stop Moduler" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Gjenopprett" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Dump til Tekstfil" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importer File" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importer Katalog" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Start Tjeneste pÃ¥ Nytt" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Avslutt Tjeneste" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Slett Bruker" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Avslutt Bruker Sesjon" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Endre Brukers Passord" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Vis Bruker Statistikk" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Vis Antall Registrerte Brukere" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Vis Antall Tilkoblede Brukere" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Bruker Behandling" #: mod_configure.erl:525 msgid "All Users" msgstr "Alle Brukere" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "UtgÃ¥ende s2s Koblinger" #: mod_configure.erl:615 msgid "Backup Management" msgstr "HÃ¥ndtere Sikkerehetskopiering" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importer Brukere Fra jabberd14 Spoolfiler" #: mod_configure.erl:762 msgid "To ~s" msgstr "Til ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Fra ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Database Tabell Konfigurasjon pÃ¥ " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Velg lagringstype for tabeller" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Kun diskkopi" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM og diskkopi" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM kopi" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Lagres ikke lokalt" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Stopp Moduler pÃ¥ " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Velg hvilke moduler som skal stoppes" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Start Moduler pÃ¥ " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Skriv inn en liste av {Module, [Options]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Liste over moduler som skal startes" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Sikkerhetskopiere til Fil pÃ¥ " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Skriv inn sti til sikkerhetskopi filen" #: 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:1115 msgid "Restore Backup from File at " msgstr "Gjenopprett fra Sikkerhetsopifil pÃ¥ " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Dump Sikkerhetskopi til Tekstfil pÃ¥ " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Skriv inn sti til tekstfil" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importer Bruker fra Fil pÃ¥ " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Skriv inn sti til jabberd14 spoolfil" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importer Brukere fra Katalog pÃ¥ " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Skriv inn sti til jabberd14 spoolkatalog" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Sti til Katalog" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Tids forsinkelse" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfigurasjon for Tilgangskontroll lister" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Tilgangskontroll lister" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Tilgangskonfigurasjon" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Passord Bekreftelse" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Antall registrerte brukere" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Antall tilkoblede brukere" #: mod_configure.erl:1936 msgid "Last login" msgstr "Siste pÃ¥logging" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Kontaktliste størrelse" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresser" #: mod_configure.erl:1967 msgid "Resources" msgstr "Ressurser" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administrasjon av " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Handling pÃ¥ bruker" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Redigere Egenskaper" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modul" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registrering i mod_irc for " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "Skriv brukernavn, tekstkoding, porter og passord du ønsker Ã¥ bruke for " "tilkobling til IRC servere" #: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC Brukernavn" #: 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." msgstr "" "Om du ønsker Ã¥ spesifisere tekstkoding for IRC tjenere, fyller du ut en " "liste med verdier i formatet '{\"irc server\", \"encoding\", port, \"password" "\"}'. Denne tjenesten bruker \"~s\" som standard, port ~p, empty password." #: 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 "" "Eksempel: [{\"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 "Tilkoblings parametere" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Bli med i IRC kanal" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanal (ikke skriv den første #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC server" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Bli med i IRC kanalen her. " #: 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:1046 msgid "IRC settings" msgstr "IRC instillinger" #: 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 "" "Angi brukernavn og kodinger du ønsker Ã¥ bruke for Ã¥ koble til IRC servere. " "Trykk 'Neste' for Ã¥ fÃ¥ flere felt for Ã¥ fylle i. Trykk 'Fullfør' for Ã¥ lagre " "innstillingene." #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC brukernavn" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Passord ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Tekstkoding for server ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registrer Kallenavn pÃ¥ " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Kallenavn" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Samtalerom" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "forlater rommet" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Registrerte Brukere" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Samtalerommets konfigurasjon er endret" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "kommer inn i rommet" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "forlater rommet" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "har blitt bannlyst" #: 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: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: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:450 msgid "is now known as" msgstr "er nÃ¥ kjent som" #: 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:493 msgid "Chatroom is created" msgstr "Samtalerom er opprettet" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Samtalerom er fjernet" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Samtalerom er startet" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Samtalerom er stoppet" #: mod_muc_log.erl:503 msgid "Monday" msgstr "mandag" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "tirsdag" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "onsdag" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "torsdag" #: mod_muc_log.erl:507 msgid "Friday" msgstr "fredag" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "lørdag" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "søndag" #: mod_muc_log.erl:513 msgid "January" msgstr "januar" #: mod_muc_log.erl:514 msgid "February" msgstr "februar" #: mod_muc_log.erl:515 msgid "March" msgstr "mars" #: mod_muc_log.erl:516 msgid "April" msgstr "april" #: mod_muc_log.erl:517 msgid "May" msgstr "mai" #: mod_muc_log.erl:518 msgid "June" msgstr "juni" #: mod_muc_log.erl:519 msgid "July" msgstr "juli" #: mod_muc_log.erl:520 msgid "August" msgstr "august" #: mod_muc_log.erl:521 msgid "September" msgstr "september" #: mod_muc_log.erl:522 msgid "October" msgstr "oktober" #: mod_muc_log.erl:523 msgid "November" msgstr "november" #: mod_muc_log.erl:524 msgid "December" msgstr "desember" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Rom Konfigurasjon" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Samtalerom Deltakere" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Kallenavn ~s eksisterer ikke i dette rommet" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Ugyldig rang: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ugyldig rolle: ~s" #: 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:3359 msgid "Room title" msgstr "Romtittel" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Rom beskrivelse" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Gjør rommet permanent" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Gjør rommet offentlig søkbart" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Gjør deltakerlisten offentlig" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Passordbeskytt rommet" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maksimum Antall Deltakere" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Ingen grense" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Presenter ekte Jabber IDer til" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "kun for redaktører" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "hvem som helst" #: 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:3516 msgid "Make room moderated" msgstr "Gjør rommet redaktørstyrt" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Standard brukere som deltakere" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Tillat brukere Ã¥ endre emne" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Tillat brukere Ã¥ sende private meldinger" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Tillat brukere Ã¥ sende private meldinger til" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "ingen" #: 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:3579 msgid "Allow users to send invites" msgstr "Tillat brukere Ã¥ sende invitasjoner" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Tillat besøkende Ã¥ endre kallenavn" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Tillat brukere Ã¥ sende lyd forespørsler" #: 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:3599 msgid "Make room CAPTCHA protected" msgstr "Gjør rommet CAPTCHA beskyttet" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Ekskluder Jabber IDer fra CAPTCHA utfordring" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "SlÃ¥ pÃ¥ logging" #: 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:4190 msgid "Number of occupants" msgstr "Antall deltakere" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privat, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Lyd forespørsel" #: 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:4349 msgid "User JID" msgstr "Bruker JID" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Gi lyd til denne personen?" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s inviterer deg til rommet ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "passordet er" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "Tid" #: mod_offline.erl:812 msgid "From" msgstr "Fra" #: mod_offline.erl:813 msgid "To" msgstr "Til" #: mod_offline.erl:814 msgid "Packet" msgstr "Pakke" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Frakoblede Meldinger:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Fjern Alle Frakoblede Meldinger" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub abonements forespørsel" #: 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:1559 msgid "Node ID" msgstr "Node ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Abonnements Adresse" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Send innhold sammen med kunngjøringer" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Lever begivenhets kunngjøringer" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Informer abonnenter nÃ¥r node konfigurasjonen endres" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Informer abonnenter nÃ¥r noden slettes" #: 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:3755 msgid "Persist items to storage" msgstr "Vedvarende elementer til lagring" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Et vennlig navn for noden" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Høyeste # elementer som skal lagres" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Om man skal tillate abonnenter" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Spesifiser aksess modellen" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Kontaktliste grupper som tillates Ã¥ abonnere" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Angi publiserings modell" #: 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:3771 msgid "Specify the event message type" msgstr "Spesifiser hendelsesbeskjed type" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Største innholdsstørrelse i byte" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "NÃ¥r skal siste publiserte artikkel sendes" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Send kunngjøringer bare til tilgjengelige brukere" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Samlingene som en node er assosiert med" #: 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: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" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "En feil skjedde under oppretting av kontoen:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Dni Jabber konto er blitt sltettet." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "En feil skjedde under sletting av kontoen: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Passordet for din Jabber konto ble endret." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "En feil skjedde under endring av passordet:" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Jabber Konto Registrering" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Registrer en Jabber konto" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Brukernavn:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Denne er ufølsom for smÃ¥ og store bokstaver: macbeth er det samme som " "MacBeth og Macbeth. " #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Ikke godtatte tegn:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Ikke fortell passordet til noen, ikke en gang til administratoren av Jabber " "serveren." #: 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: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 "" "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: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 "" "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. " #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Passord Bekreftelse:" #: mod_register_web.erl:269 msgid "Register" msgstr "Registrer" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Gammelt Passord:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nytt Passord:" #: 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:480 msgid "Unregister" msgstr "Avregistrer" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Abonnement" #: mod_roster.erl:1437 msgid "Pending" msgstr "Ventende" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grupper" #: mod_roster.erl:1476 msgid "Validate" msgstr "Bekrefte gyldighet" #: mod_roster.erl:1485 msgid "Remove" msgstr "Fjern" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontaktliste for " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Legg til Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Kontaktliste" #: 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:1232 msgid "Name:" msgstr "Navn:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Beskrivelse:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Medlemmer:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Viste grupper:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Gruppe " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Fødselsdag" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "By" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Land" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Epost" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Etternavn" #: 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 "" "Fyll inn skjemaet for Ã¥ søke etter Jabber bruker (Legg til * pÃ¥ slutten av " "feltet for Ã¥ treffe alle som starter slik)" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Fullstendig Navn" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Mellomnavn" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organisasjonsnavn" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Organisasjonsenhet" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Søk etter brukere i " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard Bruker Søk" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard modul" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Søke Resultater for " #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Denne deltakeren er kastet ut av rommet fordi han sendte en feilmelding " #~ "til en annen deltaker" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Captchaen er ikke gyldig" ejabberd-16.01/priv/msgs/tr.po0000644000232200023220000014636712645157216016575 0ustar debalancedebalance# translation of tr.po to Turkish # Doruk Fisek , 2009, 2012. msgid "" msgstr "" "Project-Id-Version: tr\n" "PO-Revision-Date: 2012-04-17 11:18+0300\n" "Last-Translator: Doruk Fisek \n" "Language-Team: Turkish \n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Turkish (türkçe)\n" "X-Generator: KBabel 1.11.4\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "STARTTLS kullanımı gereklidir" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Hiç kaynak saÄŸlanmadı" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Eski baÄŸlantı yenisi ile deÄŸiÅŸtirildi" #: 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: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: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: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: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:227 msgid "CAPTCHA web page" msgstr "CAPTCHA web sayfası" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "İnsan doÄŸrulaması (captcha) geçerli." #: 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ı" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Sunucu:" #: 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" #: 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 "Yetkisiz" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Yöneticisi" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Yönetim" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Ham" #: 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: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:913 msgid "~s access rule configuration" msgstr "~s eriÅŸim kuralları ayarları" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Sanal Sunucuları" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Kullanıcılar" #: 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:971 msgid "Users Last Activity" msgstr "Kullanıcıların Son Aktiviteleri" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periyot:" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Geçen ay" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Geçen yıl" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Tüm aktivite" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Sıradan Tabloyu Göster" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Önemli Tabloyu Göster" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "İstatistikler" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Bulunamadı" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Düğüm bulunamadı" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Yeni Ekle" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Sunucu" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Kayıtlı Kullanıcılar" #: 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:1459 msgid "Offline Messages" msgstr "Çevirim-dışı Mesajlar" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Son Aktivite" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Asla" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "BaÄŸlı" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Kayıtlı Kullanıcılar:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Giden s2s BaÄŸlantıları:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Giden s2s BaÄŸlantıları:" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Kullanıcı " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "BaÄŸlı Kaynaklar:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Parola:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Kullanıcıyı Kaldır" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Veri Yok" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Düğümler" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Çalışan Düğümler" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "DurdurulmuÅŸ Düğümler" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Düğüm " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Veritabanı" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Yedekle" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Dinlenen Kapılar (Portlar)" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "GÜncelle" #: 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:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Durdur" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modüller" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC ÇaÄŸrı Hatası" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Veritabanı Tabloları : " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "İsim" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Depolama Tipi" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementler" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Bellek" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Hata" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Yedek : " #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "İkili yedeÄŸi sakla:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Hemen ikili yedekten geri al:" #: 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:1999 msgid "Store plain text backup:" msgstr "Düz metin yedeÄŸi sakla:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Hemen düz metin yedekten geri al" #: 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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Jabberd 1.4 Spool Dizininden Kullanıcıları İçe Aktar:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Dinlenen Kapılar (Portlar) : " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Modüller : " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "~p istatistikleri" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Hizmet Süresi:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "İşlemci Zamanı:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Tamamlanan Hareketler (Transactions Committed):" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "İptal Edilen Hareketler (Transactions):" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Tekrar BaÅŸlatılan Hareketler (Transactions):" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Kaydı Tutulan Hareketler (Transactions):" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Güncelle " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Planı güncelle" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "DeÄŸiÅŸen modüller" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "BetiÄŸi Güncelle" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Düşük seviye güncelleme betiÄŸi" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Betik kontrolü" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Kapı (Port)" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokol" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modül" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Seçenekler" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "BaÅŸlat" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Komutlar" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: 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:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Konu" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Mesajın gövdesi" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Duyuru mesajının gövdesi yok" #: mod_announce.erl:662 msgid "Announcements" msgstr "Duyurular" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Duyuruyu tüm kullanıcılara yolla" #: 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:668 msgid "Send announcement to all online users" msgstr "Duyuruyu tüm baÄŸlı kullanıcılara yolla" #: 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:672 msgid "Set message of the day and send to online users" msgstr "Günün mesajını belirle" #: 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:676 msgid "Update message of the day (don't send)" msgstr "Günün mesajını güncelle (gönderme)" #: 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:680 msgid "Delete message of the day" msgstr "Günün mesajını sil" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Ayarlar" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Modülleri BaÅŸlat" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Modülleri Durdur" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Yedekten Geri Al" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Metin Dosyasına Döküm Al" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Dosyayı İçe Aktar" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Dizini İçe Aktar" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Servisi Tekrar BaÅŸlat" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Servisi Kapat" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Kullanıcıyı Sil" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Kullanıcı Oturumunu Kapat" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Kullanıcı Parolasını DeÄŸiÅŸtir" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Kullanıcı İstatistiklerini Al" #: 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:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "BaÄŸlı Kullanıcı Sayısını Al" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Kullanıcı Yönetimi" #: mod_configure.erl:525 msgid "All Users" msgstr "Tüm Kullanıcılar" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Giden s2s BaÄŸlantıları" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Yedek Yönetimi" #: 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:762 msgid "To ~s" msgstr "Kime ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Kimden ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Veritabanı Tablo Ayarları : " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Tabloların veri depolama tipini seçiniz" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Sadece disk kopyala" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM ve disk kopyala" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM kopyala" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Uzak kopyala" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Modülleri Durdur : " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Durdurulacak modülleri seçiniz" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Modülleri BaÅŸlat : " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "{Module, [Options]} listesi giriniz" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "BaÅŸlatılacak modüllerin listesi" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Dosyaya Yedekle : " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Yedek dosyasının yolunu giriniz" #: 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:1115 msgid "Restore Backup from File at " msgstr "Dosyadaki Yedekten Geri Al : " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Metin Dosyasına Döküm Alarak Yedekle : " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Metin dosyasının yolunu giriniz" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Dosyadan Kullanıcıları İçe Aktar : " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "jabberd14 spool dosyası için yol giriniz" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Dizinden Kullanıcıları İçe Aktar : " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "jabberd14 spool dosyası için yol giriniz" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Dizinin Yolu" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Zaman gecikmesi" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "EriÅŸim Kontrol Listelerinin Ayarlanması (ACL)" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "EriÅŸim kontrol listeleri (ACL)" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "EriÅŸim Ayarları" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Parola DoÄŸrulaması" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Kayıtlı kullanıcı sayısı" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "BaÄŸlı kullanıcı sayısı" #: mod_configure.erl:1936 msgid "Last login" msgstr "Son giriÅŸ" #: mod_configure.erl:1963 msgid "Roster size" msgstr "İsim listesi boyutu" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresleri" #: mod_configure.erl:1967 msgid "Resources" msgstr "Kaynaklar" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Yönetim : " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Kullanıcıya uygulanacak eylem" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Özellikleri Düzenle" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modülü" #: 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:653 msgid "Registration in mod_irc for " msgstr "mod_irc'ye kayıt : " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "IRC sunuculara baÄŸlanmak için kullanmak istediÄŸiniz kullanıcı ismi, " "kodlamalar, kapılar (portlar) ve parolaları giriniz" #: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC Kullanıcı İsmi" #: 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." msgstr "" "IRC sunucuları için farklı kapılar (portlar), parolalar, kodlamalar " "belirtmek istiyorsanız, '{\"irc sunucusu\", \"kodlama\",\"kapı\",\"parola" "\"}' 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:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." msgstr "" "Örnek: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"gizli\"}, {\"vendetta.fef.net" "\", \"iso8859-1\", 7000}], {\"irc.sometestserver.net\", \"utf-8\"}]" #: mod_irc.erl:713 msgid "Connections parameters" msgstr "BaÄŸlantı parametreleri" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "IRC kanalına katıl" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanalı (ilk # iÅŸaretini koymayın)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC sunucusu" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Buradaki IRC kanalına katıl." #: 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:1046 msgid "IRC settings" msgstr "IRC ayarları" #: 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 "" "IRC sunuculara baÄŸlanmak için kullanmak istediÄŸiniz kullanıcı isimleri ve " "kodlamaları giriniz. 'İleri' tuÅŸuna basınca karşınıza dolduracak daha fazla " "alan çıkacak. 'Tamamla' tuÅŸuna basarak ayarları kaydedin." #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC kullanıcı ismi" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Parola ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Kapı (Port) ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Sunucu için kodlama ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Sunucu ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Takma İsim Kaydı : " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Takma isim" #: 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ü" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Sohbet Odaları" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "odadan ayrıldı" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Kayıtlı Kullanıcılar" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: 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:410 msgid "joins the room" msgstr "odaya katıldı" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "odadan ayrıldı" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "odaya girmesi yasaklandı" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "sistem kapandığından dolayı atıldı" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "isim deÄŸiÅŸtirdi :" #: 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:493 msgid "Chatroom is created" msgstr "Sohbet odası oluÅŸturuldu" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Sohbet odası kaldırıldı" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Sohbet odası baÅŸlatıldı" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Sohbet odası durduruldu" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Pazartesi" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Salı" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "ÇarÅŸamba" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "PerÅŸembe" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Cuma" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Cumartesi" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Pazar" #: mod_muc_log.erl:513 msgid "January" msgstr "Ocak" #: mod_muc_log.erl:514 msgid "February" msgstr "Åžubat" #: mod_muc_log.erl:515 msgid "March" msgstr "Mart" #: mod_muc_log.erl:516 msgid "April" msgstr "Nisan" #: mod_muc_log.erl:517 msgid "May" msgstr "Mayıs" #: mod_muc_log.erl:518 msgid "June" msgstr "Haziran" #: mod_muc_log.erl:519 msgid "July" msgstr "Temmuz" #: mod_muc_log.erl:520 msgid "August" msgstr "AÄŸustos" #: mod_muc_log.erl:521 msgid "September" msgstr "Eylül" #: mod_muc_log.erl:522 msgid "October" msgstr "Ekim" #: mod_muc_log.erl:523 msgid "November" msgstr "Kasım" #: mod_muc_log.erl:524 msgid "December" msgstr "Aralık" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Oda Ayarları" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Oda Sakini Sayısı" #: 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" msgstr "" "Sadece moderatörlerin ve katılımcıların bu odanın konusunu deÄŸiÅŸtirmesine " "izin veriliyor" #: 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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "~s takma ismi odada yok" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Geçersiz iliÅŸki: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Geçersiz rol: ~s" #: 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:3359 msgid "Room title" msgstr "Oda baÅŸlığı" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Oda tanımı" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Odayı kalıcı hale getir" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Odayı herkes tarafından aranabilir hale getir" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Katılımcı listesini herkese açık hale getir" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Odayı parola korumalı hale getir" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Odada En Fazla Bulunabilecek KiÅŸi Sayısı" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Sınırsız" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Gerçek Jabber ID'lerini göster :" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "sadece moderatörler" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "herkes" #: 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:3516 msgid "Make room moderated" msgstr "Odayı moderasyonlu hale getir" #: 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:3522 msgid "Allow users to change the subject" msgstr "Kullanıcıların konu deÄŸiÅŸtirmesine izin ver" #: 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:3533 msgid "Allow visitors to send private messages to" msgstr "Ziyaretçilerin özel mesaj göndermelerine izin ver" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "hiç kimse" #: 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:3579 msgid "Allow users to send invites" msgstr "Kullanıcıların davetiye göndermelerine izin ver" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Ziyaretçilerin takma isim deÄŸiÅŸtirmelerine izin ver" #: 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: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:3599 msgid "Make room CAPTCHA protected" msgstr "Odayı insan doÄŸrulaması (captcha) korumalı hale getir" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: 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:3621 msgid "Enable logging" msgstr "Kayıt tutma özelliÄŸini aç" #: 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:4190 msgid "Number of occupants" msgstr "Oda sakini sayısı" #: mod_muc_room.erl:4260 msgid "private, " msgstr "özel" #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Ses isteÄŸi" #: 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:4349 msgid "User JID" msgstr "Kullanıcı JID" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Bu kiÅŸiye ses verelim mi?" #: 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:4507 msgid "the password is" msgstr "parola :" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "Zaman" #: mod_offline.erl:812 msgid "From" msgstr "Kimden" #: mod_offline.erl:813 msgid "To" msgstr "Kime" #: mod_offline.erl:814 msgid "Packet" msgstr "Paket" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Çevirim-dışı Mesajlar:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Tüm Çevirim-dışı Mesajları Kaldır" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modülü" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Yayınla-Üye Ol" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modülü" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub üye isteÄŸi" #: 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:1559 msgid "Node ID" msgstr "Düğüm ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Üye Olanın Adresi" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Yükleri (payload) olay uyarıları ile beraber gönder" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Olay uyarıları gönderilsin" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Bir düğüm silindiÄŸinde üyeleri uyar" #: 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:3755 msgid "Persist items to storage" msgstr "Öğeleri depoda kalıcı hale getir" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Düğüm için dostane bir isim" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Kalıcı hale getirilecek en fazla öğe sayısı" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Üyeliklere izin verilsin mi" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "EriÅŸim modelini belirtiniz" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Üye olunmasına izin verilen kontak listesi grupları" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Yayıncı modelini belirtiniz" #: 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:3771 msgid "Specify the event message type" msgstr "Olay mesaj tipini belirtiniz" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "En fazla yük (payload) boyutu (bayt olarak)" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Son yayınlanan öğe ne zaman gönderilsin" #: 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:3779 msgid "The collections with which a node is affiliated" msgstr "Bir düğüm ile baÄŸlantılı koleksiyonlar" #: 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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Hesap oluÅŸturulurken bir hata oluÅŸtu:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Jabber hesabınız baÅŸarıyla silindi." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Hesabın silinmesi sırasında bir hata oluÅŸtu:" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Jabber hesabınızın parolası baÅŸarıyla deÄŸiÅŸtirildi." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Parolanın deÄŸiÅŸtirilmesi sırasında bir hata oluÅŸtu:" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Jabber Hesap Kaydı" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Bir Jabber hesabı kaydet" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Kullanıcı adı:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Burada büyük küçük harfi yapılmaz: macbeth ile MacBeth ve Macbeth aynıdır." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "İzin verilmeyen karakterler:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Sunucu:" #: 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: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: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 "" "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: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 "" "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." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Parola DoÄŸrulaması:" #: mod_register_web.erl:269 msgid "Register" msgstr "Kayıt Ol" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Eski Parola:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Yeni Parola:" #: 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:480 msgid "Unregister" msgstr "Kaydı Sil" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Üyelik" #: mod_roster.erl:1437 msgid "Pending" msgstr "Sıra Bekleyen" #: mod_roster.erl:1438 msgid "Groups" msgstr "Gruplar" #: mod_roster.erl:1476 msgid "Validate" msgstr "Geçerli" #: mod_roster.erl:1485 msgid "Remove" msgstr "Kaldır" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontak Listesi : " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Jabber ID'si Ekle" #: mod_roster.erl:1622 msgid "Roster" msgstr "Kontak Listesi" #: 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:1232 msgid "Name:" msgstr "İsim:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Tanım:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Üyeler:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Gösterilen Gruplar:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Group " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Sunucusu" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "DoÄŸumgünü" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "İl" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Ülke" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-posta" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Soyisim" #: 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 "" "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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Tam İsim" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Ortanca İsim" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Kurum İsmi" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Kurumun İlgili Birimi" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Kullanıcılarda arama yap : " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard Kullanıcı Araması" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard modülü" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Arama sonuçları : " #: 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 "Outgoing s2s Servers:" #~ msgstr "Giden s2s Sunucuları" #~ msgid "Delete" #~ msgstr "Sil" #~ msgid "This room is not anonymous" #~ msgstr "Bu oda anonim deÄŸil" #~ 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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Bu katılımcı baÅŸka bir katılımcıya bir hata mesajı gönderdiÄŸi için odadan " #~ "atıldı" #~ 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ı" ejabberd-16.01/priv/msgs/zh.po0000644000232200023220000013752512645157216016565 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "Last-Translator: Shelley Shyan - shelleyshyan AT gmail DOT com\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Chinese (中文)\n" "X-Additional-Translator: Zhan Caibao - zhancaibao AT gmail DOT com\n" "X-Additional-Translator: Mike Wang\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "è¦æ±‚使用 STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "æ— èµ„æºæä¾›" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "被新的连接替æ¢" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "请输入您所看到的文本" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "您å‘é€ç»™ ~s 的消æ¯å·²è¢«é˜»æ­¢. è¦è§£é™¤é˜»æ­¢, 请访问 ~s" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "如果您在这里没有看到验è¯ç å›¾ç‰‡, 请访问网页." #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "验è¯ç ç½‘页" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "验è¯ç æœ‰æ•ˆ." #: 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 "用户" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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 "ejabberd 网页管ç†" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "管ç†" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "原始格å¼" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "访问规则" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s 访问规则é…ç½®" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "虚拟主机" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "用户" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "在线用户" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "用户上次活动" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "æŒç»­æ—¶é—´: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "上个月" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "上一年" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "所有活动" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "显示普通列表" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "显示完整列表" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "统计" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "没有找到" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "没有找到节点" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "添加新用户" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "主机" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "注册用户" #: 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:1459 msgid "Offline Messages" msgstr "离线消æ¯" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "上次活动" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "从未" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "在线" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "注册用户:" #: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 #: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "在线用户:" #: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "出站 s2s 连接:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" 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 msgid "None" msgstr "æ— " #: 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:1673 #, fuzzy msgid "User ~s" msgstr "用户 " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "已连接资æº:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "密ç :" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "删除用户" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "没有数æ®" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "节点" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "è¿è¡Œä¸­çš„节点" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "å·²ç»åœæ­¢çš„节点" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "节点 " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "æ•°æ®åº“" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "备份" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "被监å¬çš„端å£" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "æ›´æ–°" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "é‡å¯" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "åœæ­¢" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "模å—" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC 调用错误" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "æ•°æ®åº“列表ä½äºŽ " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "å§“å" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "存储类型" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "元素" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "内存" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "错误" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "å¤‡ä»½æ¥æº " #: 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 "" "注æ„:这些选项仅将备份内置的 Mnesia æ•°æ®åº“. 如果您正在使用 ODBC 模å—, 您还需" "è¦åˆ†åˆ«å¤‡ä»½æ‚¨çš„æ•°æ®åº“." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "存储为二进制备份:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "ç«‹å³æ¢å¤äºŒè¿›åˆ¶å¤‡ä»½:" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "在下次 ejabberd é‡å¯åŽæ¢å¤äºŒè¿›åˆ¶å¤‡ä»½(需è¦çš„内存更少):" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "存储为普通文本备份:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "ç«‹å³æ¢å¤æ™®é€šæ–‡æœ¬å¤‡ä»½:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "从 PIEFXIS 文件 (XEP-0227) 导入用户数æ®:" #: 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:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "å°†æŸä¸»æœºçš„用户数æ®å¯¼å‡ºåˆ° PIEFXIS 文件 (XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "从 jabberd14 Spool 文件导入用户数æ®:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "从 jabberd14 Spool 目录导入用户数æ®:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "监å¬çš„端å£ä½äºŽ " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "模å—ä½äºŽ " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "~p 的统计" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "正常è¿è¡Œæ—¶é—´:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU 时间:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "æäº¤çš„事务:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "å–æ¶ˆçš„事务:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "é‡å¯çš„事务:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "记入日志的事务:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "æ›´æ–° " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "更新计划" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "被修改模å—" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "更新脚本" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "低级别更新脚本" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "脚本检查" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "端å£" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "åè®®" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "模å—" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "选项" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "开始" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "命令" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "确实è¦åˆ é™¤æ¯æ—¥æ¶ˆæ¯å—?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "标题" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "消æ¯ä¸»ä½“" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "é€šçŸ¥æ¶ˆæ¯æ— æ­£æ–‡å†…容" #: mod_announce.erl:662 msgid "Announcements" msgstr "通知" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "å‘é€é€šçŸ¥ç»™æ‰€æœ‰ç”¨æˆ·" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "å‘é€é€šçŸ¥ç»™æ‰€æœ‰ä¸»æœºä¸Šçš„æ‰€æœ‰ç”¨æˆ·" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "å‘é€é€šçŸ¥ç»™æ‰€æœ‰åœ¨çº¿ç”¨æˆ·" #: 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:672 msgid "Set message of the day and send to online users" msgstr "è®¾å®šæ¯æ—¥æ¶ˆæ¯å¹¶å‘é€ç»™æ‰€æœ‰åœ¨çº¿ç”¨æˆ·" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "è®¾ç½®æ‰€æœ‰ä¸»æœºä¸Šçš„æ¯æ—¥æ¶ˆæ¯å¹¶å‘é€ç»™åœ¨çº¿ç”¨æˆ·" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "æ›´æ–°æ¯æ—¥æ¶ˆæ¯(ä¸å‘é€)" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "æ›´æ–°æ‰€æœ‰ä¸»æœºä¸Šçš„æ¯æ—¥æ¶ˆæ¯(ä¸å‘é€)" #: mod_announce.erl:680 msgid "Delete message of the day" msgstr "åˆ é™¤æ¯æ—¥æ¶ˆæ¯" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "åˆ é™¤æ‰€æœ‰ä¸»æœºä¸Šçš„æ¯æ—¥æ¶ˆæ¯" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "é…ç½®" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "å¯åŠ¨æ¨¡å—" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "åœæ­¢æ¨¡å—" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "æ¢å¤" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "转储到文本文件" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "导入文件" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "导入目录" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "é‡å¯æœåŠ¡" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "关闭æœåŠ¡" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "删除用户" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "结æŸç”¨æˆ·ä¼šè¯" #: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 #: mod_configure.erl:1473 msgid "Get User Password" msgstr "获å–用户密ç " #: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "更改用户密ç " #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "获å–用户上次登陆时间" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "获å–用户统计" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "èŽ·å–æ³¨å†Œç”¨æˆ·æ•°" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "获å–在线用户数" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "用户管ç†" #: mod_configure.erl:525 msgid "All Users" msgstr "所有用户" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "出站 s2s 连接" #: mod_configure.erl:615 msgid "Backup Management" msgstr "备份管ç†" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "从 jabberd14 Spool 文件导入用户" #: mod_configure.erl:762 msgid "To ~s" msgstr "å‘é€ç»™~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "æ¥è‡ª~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "æ•°æ®åº“表格é…ç½®ä½äºŽ" #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "请选择表格的存储类型" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "ä»…ç£ç›˜å¤åˆ¶" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "内存与ç£ç›˜å¤åˆ¶" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "内存(RAM)å¤åˆ¶" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "远程å¤åˆ¶" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "è¦åœæ­¢çš„æ¨¡å—ä½äºŽ " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "请选择è¦åœæ­¢çš„æ¨¡å—" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "è¦å¯åŠ¨çš„æ¨¡å—ä½äºŽ " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "请输入{模å—, [选项]}列表" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "è¦å¯åŠ¨çš„æ¨¡å—列表" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "备份文件ä½äºŽ" #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "请输入备份文件的路径" #: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "文件路径" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "è¦æ¢å¤çš„备份文件ä½äºŽ" #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "转储备份到文本文件于" #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "请输入文本文件的路径" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "导入用户的文件ä½äºŽ " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "请输入 jabberd14 spool 文件的路径" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "导入用户的目录ä½äºŽ " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "请输入 jabberd14 spool 目录的路径" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "目录的路径" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "时间延迟" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "访问控制列表(ACL)é…ç½®" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "访问控制列表(ACL)" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "访问é…ç½®" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "确认密ç " #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "注册用户数" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "在线用户数" #: mod_configure.erl:1936 msgid "Last login" msgstr "上次登陆" #: mod_configure.erl:1963 msgid "Roster size" msgstr "花å册大å°" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP 地å€" #: mod_configure.erl:1967 msgid "Resources" msgstr "资æº" #: mod_configure.erl:2095 msgid "Administration of " msgstr "管ç†" #: mod_configure.erl:2100 msgid "Action on user" msgstr "对用户的动作" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "编辑属性" #: 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_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:220 mod_muc.erl:467 msgid "Access denied by service policy" msgstr "访问被æœåŠ¡ç­–ç•¥æ‹’ç»" #: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC 传输" #: mod_irc.erl:476 msgid "ejabberd IRC module" 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 设置" #: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "mod_irc 中的注册是为 " #: 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:667 msgid "IRC Username" msgstr "IRC 用户å" #: 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." msgstr "" "如果您想为 IRC æœåŠ¡å™¨æŒ‡å®šä¸åŒçš„端å£, 密ç , ç¼–ç , 请用 '{\"irc æœåС噍\", \"ç¼–" "ç \", 端å£, \"密ç \"}' æ ¼å¼çš„值填充此表å•. 默认情况下此æœåŠ¡ä½¿ç”¨\"~s\"ç¼–ç , " "~p 端å£, 密ç ä¸ºç©º." #: 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 "" "例如: [{\"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 "è¿žæŽ¥å‚æ•°" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "加入 IRC 频é“" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC é¢‘é“ (ä¸è¦è¾“入第一个#å·)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC æœåС噍" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "在这里加入 IRC 频é“." #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "用此 Jabber ID: ~s 加入 IRC 频é“" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC 设置" #: 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 "" "请输入您想使用的用æ¥è¿žæŽ¥åˆ° IRC æœåŠ¡å™¨çš„ç”¨æˆ·å和编ç . 按 '下一步' èŽ·å–æ›´å¤šå¾…å¡«" "字段. 按 '完æˆ' ä¿å­˜è®¾ç½®." #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC 用户å" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "~b 的密ç " #: mod_irc.erl:1137 msgid "Port ~b" msgstr "~b 的端å£" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "æœåС噍 ~b 的编ç " #: mod_irc.erl:1171 msgid "Server ~b" msgstr "æœåС噍 ~b" #: 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 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:941 msgid "Nickname Registration at " msgstr "昵称注册于 " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "昵称" #: 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 模å—" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "èŠå¤©å®¤" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "离开房间" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "注册用户" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "èŠå¤©å®¤é…置已修改" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "加入房间" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "离开房间" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "å·²è¢«ç¦æ­¢" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "å› è”属关系改å˜è€Œè¢«è¸¢å‡º" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "因该房间改为åªå¯¹ä¼šå‘˜å¼€æ”¾è€Œè¢«è¸¢å‡º" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "因系统关机而被踢出" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "现在称呼为" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr "已将标题设置为: " #: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "èŠå¤©å®¤å·²è¢«åˆ›å»º" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "èŠå¤©å®¤å·²è¢«é”€æ¯" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "èŠå¤©å®¤å·²è¢«å¯åЍ" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "èŠå¤©å®¤å·²è¢«åœç”¨" #: mod_muc_log.erl:503 msgid "Monday" msgstr "星期一" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "星期二" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "星期三" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "星期四" #: mod_muc_log.erl:507 msgid "Friday" msgstr "星期五" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "星期六" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "星期天" #: mod_muc_log.erl:513 msgid "January" msgstr "一月" #: mod_muc_log.erl:514 msgid "February" msgstr "二月" #: mod_muc_log.erl:515 msgid "March" msgstr "三月" #: mod_muc_log.erl:516 msgid "April" msgstr "四月" #: mod_muc_log.erl:517 msgid "May" msgstr "五月" #: mod_muc_log.erl:518 msgid "June" msgstr "六月" #: mod_muc_log.erl:519 msgid "July" msgstr "七月" #: mod_muc_log.erl:520 msgid "August" msgstr "八月" #: mod_muc_log.erl:521 msgid "September" msgstr "乿œˆ" #: mod_muc_log.erl:522 msgid "October" msgstr "åæœˆ" #: mod_muc_log.erl:523 msgid "November" msgstr "å一月" #: mod_muc_log.erl:524 msgid "December" msgstr "å二月" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "房间é…ç½®" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "房间人数" #: 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:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "åªæœ‰ä¸»æŒäººå¯ä»¥åœ¨æ­¤æˆ¿é—´é‡Œæ›´æ”¹ä¸»é¢˜" #: 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:2772 msgid "Nickname ~s does not exist in the room" msgstr "昵称 ~s ä¸åœ¨è¯¥æˆ¿é—´" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "无效加入: ~s" #: 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:3348 msgid "Configuration of room ~s" msgstr "房间 ~s çš„é…ç½® " #: mod_muc_room.erl:3359 msgid "Room title" msgstr "房间标题" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "房间æè¿°" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "永久ä¿å­˜è¯¥æˆ¿é—´" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "使房间å¯è¢«å…¬å¼€æœç´¢" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "公开å‚与人列表" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "进入此房间需è¦å¯†ç " #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "å…许的与会人最大数" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "ä¸é™" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "将真实 Jabber ID 显示给" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "仅主æŒäºº" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "任何人" #: 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:3516 msgid "Make room moderated" msgstr "è®¾ç½®æˆ¿é—´åªæŽ¥æ”¶ä¸»æŒäºº" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "用户默认被视为å‚与人" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "å…许用户更改主题" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "å…许用户å‘é€ç§èŠæ¶ˆæ¯" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "å…许访客å‘é€ç§èŠæ¶ˆæ¯è‡³" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "没有人" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "å…许用户查询其它用户" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "å…许用户å‘é€é‚€è¯·" #: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "æ›´æ–°åœ¨çº¿çŠ¶æ€æ—¶å…许用户å‘é€çŠ¶æ€æ–‡æœ¬" #: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "å…许用户更改昵称" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "å…许访客å‘é€å£°éŸ³è¯·æ±‚" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "声音请求的最å°é—´éš”(以秒为å•ä½)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "ä¿æŠ¤æˆ¿é—´éªŒè¯ç " #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "从验è¯ç æŒ‘战中排除 Jabber ID" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "å¯ç”¨æœåŠ¡å™¨ç«¯èŠå¤©è®°å½•" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "您需è¦ä¸€ä¸ªå…¼å®¹ x:data 的客户端æ¥é…置房间" #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "驻留人数" #: mod_muc_room.erl:4260 msgid "private, " msgstr "ä¿å¯†, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "声音请求" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "æŽ¥å—æˆ–æ‹’ç»å£°éŸ³è¯·æ±‚" #: mod_muc_room.erl:4349 msgid "User JID" msgstr "用户 JID" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "为此人授æƒå£°éŸ³?" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s 邀请你到 ~s 房间" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "å¯†ç æ˜¯" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "æ—¶é—´" #: mod_offline.erl:812 msgid "From" msgstr "从" #: mod_offline.erl:813 msgid "To" msgstr "到" #: mod_offline.erl:814 msgid "Packet" msgstr "æ•°æ®åŒ…" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "离线消æ¯:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "移除所有离线消æ¯" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 å­—èŠ‚æµæ¨¡å—" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "å‘行-订阅" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd å‘行-订阅模å—" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub 订阅人请求" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "选择是å¦å…许该实体的订阅" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "节点 ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "订阅人地å€" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "å…许该 Jabber ID 订阅该 pubsub 节点?" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "用事件通告传输有效负载" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "传递事件通知" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "å½“èŠ‚ç‚¹è®¾ç½®æ”¹å˜æ—¶é€šçŸ¥è®¢é˜…人" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "当节点被删除时通知订阅人" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "当从节点删除内容æ¡ç›®æ—¶é€šçŸ¥è®¢é˜…人" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "æŒä¹…化内容æ¡ç›®" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "该节点的å‹å¥½åç§°" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "å…许æŒä¹…化的最大内容æ¡ç›®æ•°" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "是å¦å…许订阅" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "指定访问范例" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "å…许订阅的花å册组" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "指定å‘布人范例" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "相关å‘å¸ƒäººç¦»çº¿åŽæ¸…除所有选项" #: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "指定事件消æ¯ç±»åž‹" # bytes was translated as 'bits'. It's corrected now. #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "最大有效负载字节数" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "何时å‘逿œ€æ–°å‘布的内容æ¡ç›®" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "仅将通知å‘é€ç»™å¯å‘é€çš„用户" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "加入结点的集åˆ" #: 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: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 叿ˆ·å·²æˆåŠŸåˆ›å»º." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "叿ˆ·åˆ›å»ºå‡ºé”™: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "ä½ çš„ Jabber 叿ˆ·å·²æˆåŠŸåˆ é™¤." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "叿ˆ·åˆ é™¤å¤±è´¥: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "ä½ çš„ Jabber 叿ˆ·å¯†ç å·²æˆåŠŸæ›´æ–°." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "修改密ç å‡ºé”™: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Jabber 叿ˆ·æ³¨å†Œ" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "注册 Jabber 叿ˆ·" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "注销 Jabber 叿ˆ·" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "本页é¢å…许在此æœåŠ¡å™¨ä¸Šåˆ›å»º Jabber 叿ˆ·. ä½ çš„ JID (Jabber ID) 的形å¼å¦‚下: 用户" "å@æœåС噍. 请仔细阅读说明并正确填写相应字段." #: 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 是一样的." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "ç¦ç”¨å­—符:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "æœåС噍:" #: 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:249 msgid "You can later change your password using a Jabber client." msgstr "ä½ å¯ä»¥ç¨åŽç”¨ 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 "" "æŸäº› Jabber 客户端å¯ä»¥åœ¨ä½ çš„计算机里存储密ç . 请仅在你确认你的计算机安全的情" "况下使用该功能." #: 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 "" "è®°ä½ä½ çš„密ç , 或将其记到纸上并放于安全ä½ç½®. 如果你忘记了密ç , Jabber 也没有自" "动æ¢å¤å¯†ç çš„æ–¹å¼." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "密ç ç¡®è®¤:" #: mod_register_web.erl:269 msgid "Register" msgstr "注册" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "旧密ç : " #: mod_register_web.erl:370 msgid "New Password:" msgstr "新密ç : " #: 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:480 msgid "Unregister" msgstr "å–æ¶ˆæ³¨å†Œ" #: mod_roster.erl:1436 msgid "Subscription" msgstr "订阅" #: mod_roster.erl:1437 msgid "Pending" msgstr "挂起" #: mod_roster.erl:1438 msgid "Groups" msgstr "组" #: mod_roster.erl:1476 msgid "Validate" msgstr "确认" #: mod_roster.erl:1485 msgid "Remove" msgstr "移除" #: mod_roster.erl:1490 msgid "Roster of " msgstr "花å册属于 " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "添加 Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "花å册" #: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 #: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "共享的花å册组群" #: mod_shared_roster.erl:1232 msgid "Name:" msgstr "å§“å:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "æè¿°:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "会员:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "已显示的组:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "组" #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber æœåС噍" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "出生日期" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "城市" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "国家" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "电å­é‚®ä»¶" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "å§“æ°" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "å…¨å" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "中间å" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "组织åç§°" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "组织å•ä½" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "æœç´¢ç”¨æˆ·äºŽ " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard 用户æœç´¢" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard 模å—" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "æœç´¢ç»“æžœå±žäºŽå…³é”®è¯ " #: mod_vcard_ldap.erl:502 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 "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "该å‚与人由于å‘é€äº†é”™è¯¯æ¶ˆæ¯è€Œè¢«è¸¢å‡ºäº†èŠå¤©å®¤" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "该å‚与人由于给其他人å‘é€äº†å‡ºé”™æ¶ˆæ¯è€Œè¢«è¸¢å‡ºäº†èŠå¤©å®¤" #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "该用户由于å‘é€äº†é”™è¯¯çжæ€è€Œè¢«è¸¢å‡ºäº†èŠå¤©å®¤" #~ msgid "Captcha test failed" #~ msgstr "验è¯ç æ£€æµ‹å¤±è´¥." #~ msgid "Encodings" #~ msgstr "ç¼–ç " #~ msgid "(Raw)" #~ msgstr "(原始格å¼)" #~ msgid "Specified nickname is already registered" #~ msgstr "指定的昵称已被注册" #~ msgid "Size" #~ msgstr "大å°" ejabberd-16.01/priv/msgs/pl.msg0000644000232200023220000006652512645157216016730 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Konfiguracja dostÄ™pu"}. {"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"}. {"Add Jabber ID","Dodaj Jabber ID"}. {"Add New","Dodaj nowe"}. {"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"}. {"Allow users to change the subject","Pozwól użytkownikom zmieniać temat"}. {"Allow users to query other users","Pozwól użytkownikom pobierać informacje o innych użytkownikach"}. {"Allow users to send invites","Pozwól użytkownikom wysyÅ‚ać zaproszenia"}. {"Allow users to send private messages","Pozwól użytkownikom wysyÅ‚ać prywatne wiadomoÅ›ci"}. {"Allow visitors to change nickname","Pozwól uczestnikom na zmianÄ™ nicka"}. {"Allow visitors to send private messages to","Pozwól użytkownikom wysyÅ‚ać prywatne wiadomoÅ›ci"}. {"Allow visitors to send status text in presence updates","Pozwól uczestnikom na wysyÅ‚anie statusów opisowych"}. {"Allow visitors to send voice requests","Pozwól użytkownikom wysyÅ‚ać zaproszenia"}. {"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"}. {"Backup of ~p","Kopia zapasowa ~p"}. {"Backup to File at ","Zapisz kopiÄ™ w pliku na "}. {"Backup","Wykonaj kopie"}. {"Bad format","Błędny format"}. {"Birthday","Data urodzenia"}. {"CAPTCHA web page","Strona internetowa CAPTCHA"}. {"Change Password","ZmieÅ„ hasÅ‚o"}. {"Change User Password","ZmieÅ„ hasÅ‚o użytkownika"}. {"Characters not allowed:","Te znaki sÄ… niedozwolone:"}. {"Chatroom configuration modified","Konfiguracja pokoju zmodyfikowana"}. {"Chatroom is created","Pokój zostaÅ‚ stworzony"}. {"Chatroom is destroyed","Pokój zostaÅ‚ usuniÄ™ty"}. {"Chatroom is started","Pokój zostaÅ‚ uruchomiony"}. {"Chatroom is stopped","Pokój zostaÅ‚ zatrzymany"}. {"Chatrooms","Pokoje rozmów"}. {"Choose a username and password to register with this server","Wybierz nazwÄ™ użytkownika i hasÅ‚o aby zarejestrować siÄ™ na tym serwerze"}. {"Choose modules to stop","Wybierz moduÅ‚y do zatrzymania"}. {"Choose storage type of tables","Wybierz typ bazy dla tablel"}. {"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:"}. {"Connections parameters","Parametry połączeÅ„"}. {"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"}. {"Delete message of the day on all hosts","UsuÅ„ wiadomość dnia ze wszystkich hostów"}. {"Delete message of the day","UsuÅ„ wiadomość dnia"}. {"Delete Selected","UsuÅ„ zaznaczone"}. {"Delete User","UsuÅ„ użytkownika"}. {"Deliver event notifications","Dostarczaj powiadomienia o zdarzeniach"}. {"Deliver payloads with event notifications","Dostarczaj zawartość publikacji wraz z powiadomieniami o zdarzeniach"}. {"Description:","Opis:"}. {"Disc only copy","Kopia tylko na dysku"}. {"Displayed Groups:","WyÅ›wietlane grupy:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Nie podawaj swojego hasÅ‚a nikomu, nawet administratorowi serwera Jabber."}. {"Dump Backup to Text File at ","Zapisz kopiÄ™ zapasowÄ… w pliku tekstowym na "}. {"Dump to Text File","Wykonaj kopie do pliku tekstowego"}. {"Edit Properties","Edytuj wÅ‚aÅ›ciwoÅ›ci"}. {"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"}. {"ejabberd Web Admin","ejabberd: Panel Administracyjny"}. {"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]}"}. {"Enter nickname you want to register","Wprowadz nazwÄ™ użytkownika którego chcesz zarejestrować"}. {"Enter path to backup file","Wprowadź scieżkÄ™ do pliku kopii zapasowej"}. {"Enter path to jabberd14 spool dir","Wprowadź Å›cieżkÄ™ do roboczego katalogu serwera jabberd14"}. {"Enter path to jabberd14 spool file","Wprowadź Å›cieżkÄ™ do roboczego pliku serwera jabberd14"}. {"Enter path to text file","Wprowadź scieżkÄ™ do pliku tekstowego"}. {"Enter the text you see","Przepisz tekst z obrazka"}. {"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.","Wprowadź nazwÄ™ użytkownika i kodowania których chcesz używać do łączenia z serwerami IRC. WciÅ›nij \"Dalej\" aby ustawić wiÄ™cej parametrów połączenia. WciÅ›nij \"ZakoÅ„cz\" aby zapisać ustawienia."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Wprowadź nazwÄ™ użytkownika, port i kodowanie, których chcesz używać do łączenia z serwerami IRC"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"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):"}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","WypeÅ‚nij formularz aby wyszukać użytkowników Jabbera (dodaj * na koniec zapytania aby wyszukać po fragmencie)"}. {"Friday","PiÄ…tek"}. {"From","Od"}. {"From ~s","Od ~s"}. {"Full Name","PeÅ‚na nazwa"}. {"Get Number of Online Users","Pokaż liczbÄ™ zalogowanych użytkowników"}. {"Get Number of Registered Users","Pokaż liczbÄ™ zarejestrowanych użytkowników"}. {"Get User Last Login Time","Pokaż czas ostatniego zalogowania uzytkownika"}. {"Get User Password","Pobierz hasÅ‚o użytkownika"}. {"Get User Statistics","Pobierz statystyki użytkownika"}. {"Grant voice to this person?","Udzielić gÅ‚osu tej osobie?"}. {"Group ","Grupa "}. {"Groups","Grupy"}. {"has been banned","zostaÅ‚ wykluczony"}. {"has been kicked because of an affiliation change","zostaÅ‚ wyrzucony z powodu zmiany przynależnoÅ›ci"}. {"has been kicked because of a system shutdown","zostaÅ‚ wyrzucony z powodu wyłączenia systemu"}. {"has been kicked because the room has been changed to members-only","zostaÅ‚ wyrzucony z powodu zmiany pokoju na \"Tylko dla CzÅ‚onków\""}. {"has been kicked","zostaÅ‚ wyrzucony"}. {" has set the subject to: "," zmieniÅ‚ temat na: "}. {"Host","Host"}. {"If you don't see the CAPTCHA image here, visit the web page.","JeÅ›li nie widzisz obrazka CAPTCHA, odwiedź stronÄ™ internetowÄ…."}. {"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.","JeÅ›li chcesz ustawić inne hasÅ‚a, porty lub kodowania dla poszczególnych serwerów IRC, wypeÅ‚nij tÄ… listÄ™ wartoÅ›ciami w formacie '{\"irc server\",\"encoding\", port, \"password\"}'. DomyÅ›lne ta usÅ‚uga używa kodowania \"~s\", portu ~p, bez hasÅ‚a."}. {"Import Directory","Importuj katalog"}. {"Import File","Importuj plik"}. {"Import user data from jabberd14 spool file:","Importuj dane użytkownika z pliku roboczego serwera jabberd14:"}. {"Import User from File at ","Importuj użytkownika z pliku na "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importuj dane użytkowników z pliku w formacie PIEFXIS (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","KanaÅ‚ IRC (nie używaj #)"}. {"IRC server","Serwer IRC"}. {"IRC settings","Ustawienia IRC"}. {"IRC Transport","Transport IRC"}. {"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"}. {"January","StyczeÅ„"}. {"Join IRC channel","Dołącz do kanaÅ‚u IRC"}. {"joins the room","dołącza do pokoju"}. {"Join the IRC channel here.","Dołącz do kanaÅ‚u IRC."}. {"Join the IRC channel in this Jabber ID: ~s","Dołącz do kanaÅ‚u IRC pod tym Jabber ID: ~s"}. {"July","Lipiec"}. {"June","Czerwiec"}. {"Last Activity","Ostatnia aktywność"}. {"Last login","Ostatnie logowanie"}. {"Last month","Miniony miesiÄ…c"}. {"Last year","Miniony rok"}. {"leaves the room","opuszcza pokój"}. {"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Ä…"}. {"Make room members-only","Pokój tylko dla czÅ‚onków"}. {"Make room moderated","Pokój moderowany"}. {"Make room password protected","Pokój zabezpieczony hasÅ‚em"}. {"Make room persistent","Utwórz pokój na staÅ‚e"}. {"Make room public searchable","Pozwól wyszukiwać pokój"}. {"March","Marzec"}. {"Maximum Number of Occupants","Maksymalna liczba uczestników"}. {"Max # of items to persist","Maksymalna liczba przechowywanych przedmiotów"}. {"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Å‚"}. {"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"}. {"New Password:","Nowe hasÅ‚o:"}. {"Nickname","Nazwa użytkownika"}. {"Nickname Registration at ","Rejestracja nazwy użytkownika na "}. {"Nickname ~s does not exist in the room","Nie ma nicka ~s w tym pokoju"}. {"nobody","nikt"}. {"No body provided for announce message","Brak treÅ›ci powiadomienia"}. {"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"}. {"No resource provided","Nie podano zasobu"}. {"Not Found","Nie znaleziono"}. {"Notify subscribers when items are removed from the node","Informuj subskrybentów o usuniÄ™ciu elementów wÄ™zÅ‚a"}. {"Notify subscribers when the node configuration changes","Informuj subskrybentów o zmianach konfiguracji wÄ™zÅ‚a"}. {"Notify subscribers when the node is deleted","Informuj subskrybentów o usuniÄ™ciu wÄ™zÅ‚a"}. {"November","Listopad"}. {"Number of occupants","Liczba uczestników"}. {"Number of online users","Liczba zalogowanych użytkowników"}. {"Number of registered users","Liczba zarejestrowanych użytkowników"}. {"October","Październik"}. {"Offline Messages:","WiadomoÅ›ci offline:"}. {"Offline Messages","WiadomoÅ›ci offline"}. {"OK","OK"}. {"Old Password:","Stare hasÅ‚o:"}. {"Online","DostÄ™pny"}. {"Online Users:","Użytkownicy zalogowani:"}. {"Online Users","Użytkownicy zalogowani"}. {"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"}. {"Owner privileges required","Wymagane uprawnienia wÅ‚aÅ›ciciela"}. {"Packet","Pakiet"}. {"Password ~b","HasÅ‚o ~b"}. {"Password:","HasÅ‚o:"}. {"Password","HasÅ‚o"}. {"Password Verification:","Weryfikacja hasÅ‚a:"}. {"Password Verification","Weryfikacja hasÅ‚a"}. {"Path to Dir","Åšcieżka do katalogu"}. {"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."}. {"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"}. {"Present real Jabber IDs to","Prawdziwe Jabber ID widoczne dla"}. {"private, ","prywatny, "}. {"Protocol","Protokół"}. {"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:"}. {"Registered Users","Użytkownicy zarejestrowani"}. {"Register","Zarejestruj"}. {"Registration in mod_irc for ","Rejestracja w mod_irc dla "}. {"Remote copy","Kopia zdalna"}. {"Remove All Offline Messages","UsuÅ„ wszystkie wiadomoÅ›ci typu 'Offline'"}. {"Remove User","UsuÅ„ użytkownika"}. {"Remove","UsuÅ„"}. {"Replaced by new connection","Połączenie zostaÅ‚o zastÄ…pione"}. {"Resources","Zasoby"}. {"Restart Service","Restart usÅ‚ugi"}. {"Restart","Uruchom ponownie"}. {"Restore Backup from File at ","Odtwórz bazÄ™ danych z kopii zapasowej na "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Odtwórz kopiÄ™ binarnÄ… podczas nastÄ™pnego uruchomienia ejabberd (wymaga mniej zasobów):"}. {"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"}. {"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"}. {"Roster groups allowed to subscribe","Grupy kontaktów uprawnione do subskrypcji"}. {"Roster","Lista kontaktów"}. {"Roster of ","Lista kontaktów "}. {"Roster size","Rozmiar listy kontaktów"}. {"RPC Call Error","Błąd żądania RPC"}. {"Running Nodes","Uruchomione wÄ™zÅ‚y"}. {"~s access rule configuration","~s konfiguracja zasad dostÄ™pu"}. {"Saturday","Sobota"}. {"Script check","Sprawdź skrypt"}. {"Search Results for ","Wyniki wyszukiwania dla "}. {"Search users in ","Wyszukaj użytkowników w "}. {"Send announcement to all online users on all hosts","WyÅ›lij powiadomienie do wszystkich zalogowanych użytkowników na wszystkich hostach"}. {"Send announcement to all online users","WyÅ›lij powiadomienie do wszystkich zalogowanych użytkowników"}. {"Send announcement to all users on all hosts","WyÅ›lij powiadomienie do wszystkich użytkowników na wszystkich hostach"}. {"Send announcement to all users","WyÅ›lij powiadomienie do wszystkich użytkowników"}. {"September","WrzesieÅ„"}. {"Server ~b","Serwer ~b"}. {"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"}. {"Show Integral Table","Pokaż tabelÄ™ caÅ‚kowitÄ…"}. {"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 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"}. {"~s's Offline Messages Queue","Kolejka wiadomoÅ›ci offline użytkownika ~s"}. {"Start Modules at ","Uruchom moduÅ‚y na "}. {"Start Modules","Uruchom moduÅ‚y"}. {"Start","Uruchom"}. {"Statistics of ~p","Statystyki ~p"}. {"Statistics","Statystyki"}. {"Stop Modules at ","Zatrzymaj moduÅ‚y na "}. {"Stop Modules","Zatrzymaj moduÅ‚y"}. {"Stopped Nodes","Zatrzymane wÄ™zÅ‚y"}. {"Stop","Zatrzymaj"}. {"Storage Type","Typ bazy"}. {"Store binary backup:","Zachowaj kopiÄ™ binarnÄ…:"}. {"Store plain text backup:","Zachowaj kopiÄ™ w postaci tekstowej:"}. {"Subject","Temat"}. {"Submitted","Wprowadzone"}. {"Submit","WyÅ›lij"}. {"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:"}. {"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."}. {"Thursday","Czwartek"}. {"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"}. {"Update","Aktualizuj"}. {"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"}. {"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"}. {"User","Użytkownik"}. {"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"}. ejabberd-16.01/priv/msgs/eo.po0000644000232200023220000014367212645157216016547 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: Andreas van Cranenburgh \n" "Language-Team: \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:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Uzo de STARTTLS bezonata" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Neniu risurco donita" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "AnstataÅ­igita je nova konekto" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Enmetu montrita teksto" #: 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: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:227 msgid "CAPTCHA web page" msgstr "CAPTCHA teksaĵ-paÄo" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "La CAPTCHA Äustas" #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Servilo:" #: 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" #: 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 "Nepermesita" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Teksaĵa Administro" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administro" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Kruda" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Atingo-reguloj" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Agordo de atingo-reguloj de ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtual-gastigoj" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Uzantoj" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Konektataj Uzantoj" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Lasta aktiveco de uzanto" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periodo: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Lasta monato" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Lasta jaro" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Ĉiu aktiveco" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Montru ordinaran tabelon" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Montru integran tabelon" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistikoj" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Ne trovita" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo ne trovita" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Aldonu novan" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Gastigo" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registritaj uzantoj" #: 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:1459 msgid "Offline Messages" msgstr "Liverontaj mesaÄoj" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Lasta aktiveco" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Neniam" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Konektata" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registritaj uzantoj:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Elirantaj s-al-s-konektoj:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Elirantaj s-al-s-konektoj:" #: 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: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:1673 msgid "User ~s" msgstr "Uzanto ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Konektataj risurcoj:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Pasvorto:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Forigu uzanton" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Neniu datumo" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodoj" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Funkciantaj Nodoj" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Neaktivaj Nodoj" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Nodo ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Datumbazo" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Faru Sekurkopion" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Atentataj pordoj" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Äœisdatigu" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Restartu" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Haltigu" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduloj" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Eraro de RPC-alvoko" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Datumbaz-tabeloj je ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nomo" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Konserv-tipo" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Eroj" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memoro" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Eraro" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Sekurkopio de ~p" #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Konservu duuman sekurkopion:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "RestaÅ­rigu duuman sekurkopion tuj:" #: 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:1999 msgid "Store plain text backup:" msgstr "Skribu sekurkopion en plata tekstdosiero" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "RestaÅ­rigu sekurkopion el plata tekstdosiero tuj" #: 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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Eksportu ĉiuj tabeloj kiel SQL-informmendo al dosierujo:" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importu uzantojn de jabberd14-uzantdosieroj" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importu uzantojn de jabberd14-uzantdosieroj" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Atentataj pordoj je " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Moduloj je ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistikoj de ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "DaÅ­ro de funkciado" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU-tempo" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transakcioj enmetitaj" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transakcioj nuligitaj" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transakcioj restartitaj" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transakcioj protokolitaj" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Äœisdatigu ~p-n" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Äœisdatigo-plano" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Äœisdatigitaj moduloj" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Äœisdatigo-skripto" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Bazanivela Äisdatigo-skripto" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Skript-kontrolo" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Pordo" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokolo" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modulo" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Elektebloj" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Startu" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Ordonoj" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Sondaĵo" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Resondaĵo" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Ĉu vere forigi mesaÄon de la tago?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Temo" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Teksto de mesaÄo" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Neniu teksto donita por anonc-mesaÄo" #: mod_announce.erl:662 msgid "Announcements" msgstr "Anoncoj" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Sendu anoncon al ĉiu uzanto" #: 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:668 msgid "Send announcement to all online users" msgstr "Sendu anoncon al ĉiu konektata uzanto" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "ÅœanÄu mesaÄon de la tago (ne sendu)" #: 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:680 msgid "Delete message of the day" msgstr "Forigu mesaÄo de la tago" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Agordo" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Startu Modulojn" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Haltigu Modulojn" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "RestaÅ­ru" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Skribu en plata tekst-dosiero" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importu dosieron" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importu dosierujo" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Restartu Servon" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Haltigu Servon" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Forigu Uzanton" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Haltigu Uzant-seancon" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "ÅœanÄu pasvorton de uzanto" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Montru statistikojn de uzanto" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Montru nombron de registritaj uzantoj" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Montru nombron de konektataj uzantoj" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Uzanto-administrado" #: mod_configure.erl:525 msgid "All Users" msgstr "Ĉiuj Uzantoj" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Elirantaj s-al-s-konektoj" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Mastrumado de sekurkopioj" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importu uzantojn de jabberd14-uzantdosieroj" #: mod_configure.erl:762 msgid "To ~s" msgstr "Al ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Agordo de datumbaz-tabeloj je " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Elektu konserv-tipon de tabeloj" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Nur disk-kopio" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM- kaj disk-kopio" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM-kopio" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Fora kopio" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Haltigu modulojn je " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Elektu modulojn por fini" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Startu modulojn je " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Enmetu liston de {Modulo, [Elektebloj]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Listo de moduloj por starti" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Faru sekurkopion je " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Enmetu vojon por sekurkopio" #: 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:1115 msgid "Restore Backup from File at " msgstr "RestaÅ­rigu de dosiero el " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Skribu sekurkopion en plata teksto al " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Enmetu vojon al plata teksto" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importu uzanton de dosiero el " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Enmetu vojon al jabberd14-uzantdosiero" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importu uzantojn de dosierujo ĉe " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Enmetu vojon al jabberd14-uzantdosierujo" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Vojo al dosierujo" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Prokrasto" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Agordo de atingokontrolo" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Atingokontrol-listoj" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Agordo de atingo" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Pasvortkontrolo" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Nombro de registritaj uzantoj" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Nombro de konektataj uzantoj" #: mod_configure.erl:1936 msgid "Last login" msgstr "Lasta ensaluto" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Kontaktlist-grando" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP-adresoj" #: mod_configure.erl:1967 msgid "Resources" msgstr "Risurcoj" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Mastrumado de " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Ago je uzanto" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Redaktu atributojn" #: mod_fail2ban.erl:95 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC-modulo" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registraĵo en mod_irc de " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "Enmetu uzantnomon,j enkodigojn, pordojn kaj pasvortojn kiujn vi volas uzi " "por konektoj al IRC-serviloj" #: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC-kaÅnomo" #: 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." msgstr "" "Se vi volas specifi diversajn pordojn, pasvortojn, enkodigojn por IRC-" "serviloj, kompletigu la jenan liston kun la formo '{\"irc-servilo\", " "\"enkodigo\", porto, \"pasvorto\"}'. Se ne specifita, ĉi tiu servilo uzas la " "enkodigo \"~s\", porto ~p, malplena pasvorto." #: 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 "" "Ekzemplo: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"sekreto\"}, {\"vendetta." "fef.net\", \"iso8859-1\", 7000}, {\"irc.iutestservilo.net\", \"utf-8\"}]." #: mod_irc.erl:713 msgid "Connections parameters" msgstr "Konekto-parametroj" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Eniras IRC-babilejon" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC-babilejo (ne aldonu #-prefikson)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC-servilo" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Eniru IRC-babilejon jen" #: 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:1046 msgid "IRC settings" msgstr "IRC agordoj" #: 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 "" "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:1060 msgid "IRC username" msgstr "IRC-uzantnomo" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Pasvorto ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Pordo ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Enkodigo por servilo ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servilo ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "KaÅnomo-registrado je " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "KaÅnomo" #: 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" #: 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:249 msgid "Total rooms" msgstr "Babilejoj" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Permanentaj babilejoj" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Registritaj uzantnomoj" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Listo de babilejoj" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Agordo de babilejo ÅanÄita" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "eniras la babilejo" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "eliras la babilejo" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "estas forbarita" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "estas forpelita pro sistem-haltigo" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "nun nomiÄas" #: 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:493 msgid "Chatroom is created" msgstr "Babilejo kreita" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Babilejo neniigita" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Babilejo lanĉita" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Babilejo haltita" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Lundo" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Mardo" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Merkredo" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Ä´aÅ­do" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Vendredo" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sabato" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Dimanĉo" #: mod_muc_log.erl:513 msgid "January" msgstr "Januaro" #: mod_muc_log.erl:514 msgid "February" msgstr "Februaro" #: mod_muc_log.erl:515 msgid "March" msgstr "Marĉo" #: mod_muc_log.erl:516 msgid "April" msgstr "Aprilo" #: mod_muc_log.erl:517 msgid "May" msgstr "Majo" #: mod_muc_log.erl:518 msgid "June" msgstr "Junio" #: mod_muc_log.erl:519 msgid "July" msgstr "Julio" #: mod_muc_log.erl:520 msgid "August" msgstr "AÅ­gusto" #: mod_muc_log.erl:521 msgid "September" msgstr "Septembro" #: mod_muc_log.erl:522 msgid "October" msgstr "Oktobro" #: mod_muc_log.erl:523 msgid "November" msgstr "Novembro" #: mod_muc_log.erl:524 msgid "December" msgstr "Decembro" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Babilejo-agordo" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Nombro de ĉeestantoj" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "KaÅnomo ~s ne ekzistas en la babilejo" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Nevalida aparteneco: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Nevalida rolo: ~s" #: 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:3359 msgid "Room title" msgstr "Babilejo-nomo" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Babilejo-priskribo" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Farigu babilejon daÅ­ra" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Farigu babilejon publike trovebla" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Farigu partoprento-liston publika" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Farigu babilejon protektata per pasvorto" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Limigo de nombro de partoprenantoj" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Neniu limigo" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Montru verajn Jabber ID-ojn al" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderantoj sole" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "iu ajn" #: 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:3516 msgid "Make room moderated" msgstr "Farigu babilejon moderigata" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Kutime farigu uzantojn kiel partpoprenantoj" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permesu uzantojn ÅanÄi la temon" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permesu uzantojn sendi privatajn mesaÄojn" #: 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:3551 msgid "nobody" msgstr "neniu" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Permesu uzantojn informpeti aliajn uzantojn" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Permesu uzantojn sendi invitojn" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Permesu al vizitantoj ÅanÄi siajn kaÅnomojn" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Permesu uzantojn sendi voĉ-petojn" #: 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:3599 msgid "Make room CAPTCHA protected" msgstr "Farigu babilejon protektata per CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Åœaltu mesaÄo-arkivo" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Esceptu Ä´abber-identigilojn je CAPTCHA-defio" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Åœaltu protokoladon" #: 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:4190 msgid "Number of occupants" msgstr "Nombro de ĉeestantoj" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privata, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Voĉ-peto" #: 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:4349 msgid "User JID" msgstr "Uzant-JID" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Koncedu voĉon al ĉi-persono?" #: 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:4507 msgid "the password is" msgstr "la pasvorto estas" #: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast-servo" #: 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:811 msgid "Time" msgstr "Tempo" #: mod_offline.erl:812 msgid "From" msgstr "De" #: mod_offline.erl:813 msgid "To" msgstr "Äœis" #: mod_offline.erl:814 msgid "Packet" msgstr "Pakaĵo" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Liverontaj mesaÄoj" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Forigu ĉiujn liverontajn mesaÄojn" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bajtfluo modulo" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Public-Abonado" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Public-Abonada modulo" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubAbo abonpeto" #: 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:1559 msgid "Node ID" msgstr "Nodo ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Abonanta adreso" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Liveru aĵojn de event-sciigoj" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Liveru event-sciigojn" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Sciigu abonantoj kiam la nodo estas forigita" #: 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:3755 msgid "Persist items to storage" msgstr "Savu erojn en konservado" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Kromnomo por ĉi tiu nodo" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maksimuma kiomo de eroj en konservado" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Ĉu permesi aboni" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Specifu atingo-modelon" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Kontaktlist-grupoj kiuj rajtas aboni" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Enmetu publikadan modelon" #: 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:3771 msgid "Specify the event message type" msgstr "Specifu tipo de event-mesaÄo" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maksimuma aĵo-grando je bajtoj" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Kiam sendi la laste publicitan eron" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Nur liveru sciigojn al konektataj uzantoj" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Aro kun kiu nodo estas filigita" #: 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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Estis eraro dum kreado de la konto:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Via Ä´abber-konto estas sukcese forigita." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Estis eraro dum forigado de la konto:" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "La pasvorto de via Ä´abber-konto estas sukcese ÅanÄata." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Estis eraro dum ÅanÄi de la pasvortro:" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Ä´abber-konto registrado" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Registru Ä´abber-konton" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Malregistru Ä´abber-konton" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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. " #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Uzantnomo" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "Uskleco ne signifas: macbeth estas la sama ol MacBeth kaj Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Karaktroj ne permesata:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Servilo:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Ne donu vian pasvorton al iun ajn, eĉ ne al la administrantoj de la Ä´abber-" "servilo." #: 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: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 "" "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: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 "" "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." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Pasvortkontrolo:" #: mod_register_web.erl:269 msgid "Register" msgstr "Registru" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Malnova Pasvorto:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nova Pasvorto:" #: 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:480 msgid "Unregister" msgstr "Malregistru" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Abono" #: mod_roster.erl:1437 msgid "Pending" msgstr "Atendanta" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grupoj" #: mod_roster.erl:1476 msgid "Validate" msgstr "Validigu" #: mod_roster.erl:1485 msgid "Remove" msgstr "Forigu" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontaktlisto de " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Aldonu Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Kontaktlisto" #: 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:1232 msgid "Name:" msgstr "Nomo:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Priskribo:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membroj:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Montrataj grupoj:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupo " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang-a Jabber-Servilo" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "NaskiÄtago" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Urbo" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Lando" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "RetpoÅto" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Lasta Nomo" #: 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 "" "Kompletigu la formon por serĉi rekonata Jabber-uzanto (Aldonu * je la fino " "de la kampo por rekoni subĉenon" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Plena Nomo" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Meza Nomo" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organiz-nomo" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Organiz-parto" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Serĉu uzantojn en " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Serĉado de vizitkartoj" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard-modulo" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Serĉ-rezultoj de " #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Ĉi tiu partoprenanto estas forpelata de la babilejo pro sendo de erar-" #~ "mesaÄo al alia partoprenanto" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "La aÅ­tomata Turingtesto estas Äusta" #~ msgid "Encodings" #~ msgstr "Enkodigoj" #~ msgid "(Raw)" #~ msgstr "(Kruda)" #~ msgid "Specified nickname is already registered" #~ msgstr "Donita kaÅnomo jam estas registrita" #~ msgid "Size" #~ msgstr "Grando" #~ msgid "You must fill in field \"nick\" in the form" #~ msgstr "Vi devas enmeti kampon \"kaÅnomo\"" ejabberd-16.01/priv/msgs/de.po0000644000232200023220000014742712645157216016536 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: Nikolaus Polak \n" "Language-Team: \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: German (deutsch)\n" "X-Additional-Translator: Florian Zumbiehl\n" "X-Additional-Translator: Cord Beermann\n" "X-Additional-Translator: Marvin Preuss\n" "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:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Verwendung von STARTTLS erforderlich" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Keine Ressource angegeben" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Durch neue Verbindung ersetzt" #: 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: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: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: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: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:227 msgid "CAPTCHA web page" msgstr "CAPTCHA Webseite" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Die Verifizierung ist gültig." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "Nicht berechtigt" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web-Admin" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Verwaltung" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Unformatiert" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Zugangsregeln" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s Zugangsregel-Konfiguration" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuelle Hosts" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Benutzer" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Angemeldete Benutzer" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Letzte Benutzeraktivität" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Zeitraum: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Letzter Monat" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Letztes Jahr" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Alle Aktivitäten" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Gewöhnliche Tabelle anzeigen" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Integrale Tabelle anzeigen" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiken" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nicht gefunden" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Knoten nicht gefunden" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Neue(n) hinzufügen" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrierte Benutzer" #: 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:1459 msgid "Offline Messages" msgstr "Offline-Nachrichten" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Letzte Aktivität" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nie" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Angemeldet" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrierte Benutzer:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Ausgehende s2s-Verbindungen:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Ausgehende 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 msgid "None" msgstr "Keine" #: 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:1673 msgid "User ~s" msgstr "Benutzer ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Verbundene Ressourcen:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Passwort:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Benutzer löschen" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Keine Daten" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Knoten" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Aktive Knoten" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Angehaltene Knoten" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Knoten ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Datenbank" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Datensicherung" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Aktive Ports" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aktualisieren" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Neustart" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stoppen" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Module" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Fehler bei RPC-Aufruf" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Datenbanktabellen auf ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Vorname" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Speichertyp" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elemente" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Speicher" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Fehler" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Sicherung von ~p" #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Speichere binäre Sicherung:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Stelle binäre Sicherung sofort wieder her:" #: 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:1999 msgid "Store plain text backup:" msgstr "Speichere Klartext-Sicherung:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Stelle Klartext-Sicherung sofort wieder her:" #: 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: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: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: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:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importiere Benutzer von jabberd14 Spool Datei:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importiere Benutzer von jabberd14 Spool Verzeichnis:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Aktive Ports bei" #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Module bei ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistiken von ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Betriebszeit:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU-Zeit:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Durchgeführte Transaktionen:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Abgebrochene Transaktionen:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Neu gestartete Transaktionen:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Protokollierte Transaktionen:" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Aktualisierung ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Aktualisierungsplan" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Geänderte Module" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Aktualisierungsscript" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Low level Aktualisierungsscript" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Script-Überprüfung" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokoll" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Optionen" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Starten" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Befehle" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Die Nachricht des Tages wirklich löschen?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Betreff" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Nachrichtentext" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Kein Text für die Ankündigungsnachricht angegeben" #: mod_announce.erl:662 msgid "Announcements" msgstr "Ankündigungen" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Sende Ankündigung an alle Benutzer" #: 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:668 msgid "Send announcement to all online users" msgstr "Sende Ankündigung an alle angemeldeten Benutzer" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Aktualisiere Nachricht des Tages (nicht senden)" #: 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:680 msgid "Delete message of the day" msgstr "Lösche Nachricht des Tages" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Konfiguration" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Module starten" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Module stoppen" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Wiederherstellung" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Ausgabe in Textdatei" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Datei importieren" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Verzeichnis importieren" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Dienst neustarten" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Dienst herunterfahren" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Benutzer löschen" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Benutzer-Sitzung beenden" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Benutzer-Passwort ändern" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Benutzer-Statistiken abrufen" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Anzahl der registrierten Benutzer abrufen" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Anzahl der angemeldeten Benutzer abrufen" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Benutzerverwaltung" #: mod_configure.erl:525 msgid "All Users" msgstr "Alle Benutzer" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Ausgehende s2s-Verbindungen" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Datensicherungsverwaltung" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importiere Benutzer aus jabberd14-Spool-Dateien" #: mod_configure.erl:762 msgid "To ~s" msgstr "An ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Von ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Datenbanktabellen-Konfiguration auf " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Wähle Speichertyp der Tabellen" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Nur auf Festplatte" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM und Festplatte" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Nur RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Fernkopie" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Stoppe Module auf " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Wähle zu stoppende Module" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Starte Module auf " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Geben sie eine Liste bestehend aus {Modul, [Optionen]} ein" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Liste der zu startenden Module" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Datensicherung in die Datei " #: 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:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Pfad zur Datei" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Datenwiederherstellung aus der Datei " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Ausgabe der Sicherung in diese Textdatei " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Geben sie den Pfad zur Textdatei ein" #: mod_configure.erl:1156 msgid "Import User from File at " 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" #: mod_configure.erl:1177 msgid "Import Users from Dir at " 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" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Pfad zum Verzeichnis" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Zeitverzögerung" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfiguration der Zugangskontrolllisten" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Zugangskontroll-Listen (ACL)" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Zugangskonfiguration" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Passwort bestätigen" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Anzahl der registrierten Benutzer" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Anzahl der angemeldeten Benutzer" #: mod_configure.erl:1936 msgid "Last login" msgstr "Letzte Anmeldung" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Kontaktlistengröße" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP Adressen" #: mod_configure.erl:1967 msgid "Resources" msgstr "Ressourcen" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administration von " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Aktion auf Benutzer" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Einstellungen ändern" #: mod_fail2ban.erl:95 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC-Modul" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registrierung in mod_irc für " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" 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:667 msgid "IRC Username" msgstr "IRC-Benutzername" #: 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." msgstr "" "Wenn sie verschiedene Ports, Passwörter und Kodierungen für IRC Server " "angeben wollen, erstellen sie die Liste mit folgendem Format '{\"IRC Server" "\", \"Kodierung\", Port, \"Passwort\"}'. Standardmäßig benutzt dieser " "Dienst die \"~s\" Kodierung, den Port ~p und kein Passwort." #: 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 "" "Beispiel: [{\"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 "Verbindungsparameter" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "IRC Channel beitreten" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC Channel (ohne dem ersten #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC Server" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Hier den IRC Channel beitreten." #: 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:1046 msgid "IRC settings" msgstr "IRC Einstellungen" #: 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 "" "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." #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC Benutzername" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Passwort ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Kodierung für Server ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registrieren des Benutzernames auf" #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Benutzername" #: 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" #: 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:249 msgid "Total rooms" msgstr "Alle Chaträume" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "permanente Chaträume" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Registrierte Benutzernamen" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Liste von Chaträumen" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Chatraum-Konfiguration geändert" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "betretet den Raum" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "verlässt den Raum" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "wurde gebannt" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "wurde wegen einer Systemabschaltung entfernt" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "ist nun bekannt als" #: 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:493 msgid "Chatroom is created" msgstr "Chatraum wurde erstellt" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Chatraum wurde entfernt" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Chatraum wurde gestartet" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Chatraum wurde beendet" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Montag" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Dienstag" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Mittwoch" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Donnerstag" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Freitag" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Samstag" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Sonntag" #: mod_muc_log.erl:513 msgid "January" msgstr "Januar" #: mod_muc_log.erl:514 msgid "February" msgstr "Februar" #: mod_muc_log.erl:515 msgid "March" msgstr "März" #: mod_muc_log.erl:516 msgid "April" msgstr "April" #: mod_muc_log.erl:517 msgid "May" msgstr "Mai" #: mod_muc_log.erl:518 msgid "June" msgstr "Juni" #: mod_muc_log.erl:519 msgid "July" msgstr "Juli" #: mod_muc_log.erl:520 msgid "August" msgstr "August" #: mod_muc_log.erl:521 msgid "September" msgstr "September" #: mod_muc_log.erl:522 msgid "October" msgstr "Oktober" #: mod_muc_log.erl:523 msgid "November" msgstr "November" #: mod_muc_log.erl:524 msgid "December" msgstr "Dezember" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Raum-Konfiguration" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Teilnehmer in diesem Raum" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Der Benutzername ~s existiert im Raum nicht" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Ungültige Mitgliedschaft: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ungültige Rolle: ~s" #: 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:3359 msgid "Room title" msgstr "Raumname" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Raum Beschreibung" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Raum persistent machen" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Raum öffentlich suchbar machen" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Teilnehmerliste öffentlich machen" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Raum mit Passwort schützen" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maximale Anzahl von Teilnehmern" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Keine Begrenzung" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Echte Jabber-IDs anzeigen für" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "ausschliesslich Moderatoren" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "jeden" #: 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:3516 msgid "Make room moderated" msgstr "Raum moderiert machen" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Benutzer werden standardmäßig vollwertige Teilnehmer" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Erlaube Benutzern das Thema zu ändern" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Erlaube Benutzern private Nachrichten zu senden" #: 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:3551 msgid "nobody" msgstr "niemanden" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Erlaube Benutzern Informationen über andere Benutzer abzufragen" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Erlaube Benutzern Einladungen zu senden" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Erlaube Besuchern ihren Benutzernamen zu ändern" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Anfragen von Sprachrechten für Benutzer erlauben" #: 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:3599 msgid "Make room CAPTCHA protected" msgstr "Raum mit Verifizierung (Captcha) versehen" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Nachrichtenarchivierung aktivieren" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Von CAPTCHA Überprüfung ausgeschlossene Jabber IDs" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Protokollierung aktivieren" #: 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:4190 msgid "Number of occupants" msgstr "Anzahl der Teilnehmer" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privat, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Anfrage für Sprachrechte" #: 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:4349 msgid "User JID" msgstr "Benutzer JID" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Sprachrechte dieser Person erteilen?" #: 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:4507 msgid "the password is" msgstr "das Passwort lautet" #: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast Dienst" #: 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:811 msgid "Time" msgstr "Zeit" #: mod_offline.erl:812 msgid "From" msgstr "Von" #: mod_offline.erl:813 msgid "To" msgstr "An" #: mod_offline.erl:814 msgid "Packet" msgstr "Paket" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline-Nachrichten:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Alle Offline Nachrichten löschen" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5-Bytestreams-Modul" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe-Modul" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub-Abonnenten-Anfrage" #: 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:1559 msgid "Node ID" msgstr "Knoten-ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Abonnenten-Adresse" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Nachrichten mit Ereignis-Benachrichtigungen zustellen" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Ereignisbenachrichtigung zustellen" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Abonnenten benachrichtigen, wenn sich die Knotenkonfiguration ändert" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Abonnenten benachrichtigen, wenn der Knoten gelöscht wird" #: 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:3755 msgid "Persist items to storage" msgstr "Einträge dauerhaft speichern" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Ein merkbarer Name für den Knoten" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maximale Anzahl dauerhaft zu speichernder Einträge" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Ob Abonnements erlaubt sind" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Geben sie das Zugangsmodell an" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Kontaktlisten-Gruppen die abonnieren dürfen" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Geben sie das Publikationsmodell an" #: 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:3771 msgid "Specify the event message type" msgstr "Geben sie den Ereignis-Nachrichtentyp an" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maximale Nutzlastgrösse in Bytes" #: 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:3777 msgid "Only deliver notifications to available users" msgstr "Benachrichtigungen nur an verfügbare Benutzer schicken" #: 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: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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Es trat ein Fehler beim Erstellen des Kontos auf: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." 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: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." 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: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Jabber Konto Anmeldung" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Jabber Konto registrieren" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Jabber Konto entfernen" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Benutzername:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Groß/Klein-Schreibung spielt hierbei keine Rolle: macbeth ist gleich MacBeth " "und Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Nicht erlaubte Zeichen:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Geben sie niemandem ihr Passwort, auch nicht den Administratoren des Jabber " "Servers." #: 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: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 "" "Einige Jabber Client Programme speichern ihr Passwort auf ihrem Computer. " "Verwenden sie diese Möglichkeit nur auf Computern, die sie als sicher " "einstufen." #: 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 "" "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." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Passwort bestätigen:" #: mod_register_web.erl:269 msgid "Register" msgstr "Anmelden" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Aktuelles Passwort:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Neues Passwort:" #: 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:480 msgid "Unregister" msgstr "Abmelden" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Abonnement" #: mod_roster.erl:1437 msgid "Pending" msgstr "Schwebend" #: mod_roster.erl:1438 msgid "Groups" msgstr "Gruppen" #: mod_roster.erl:1476 msgid "Validate" msgstr "Validieren" #: mod_roster.erl:1485 msgid "Remove" msgstr "Entfernen" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontaktliste von " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Jabber-ID hinzufügen" #: mod_roster.erl:1622 msgid "Roster" msgstr "Kontaktliste" #: 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:1232 msgid "Name:" msgstr "Name:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Beschreibung:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Mitglieder:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Angezeigte Gruppen:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Gruppe " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Geburtsdatum" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Stadt" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Land" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-Mail" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Nachname" #: 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 "" "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 msgid "Full Name" msgstr "Vollständiger Name" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Zweiter Vorname" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Name der Organisation" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Abteilung" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Benutzer suchen in " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard-Benutzer-Suche" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard-Modul" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " 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 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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Dieser Teilnehmer wurde aus dem Raum geworfen, da er eine fehlerhafte " #~ "Nachricht an einen anderen Teilnehmer gesendet hat" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Die Verifizierung ist gültig." ejabberd-16.01/priv/msgs/sv.msg0000644000232200023220000004740212645157216016736 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Ã…tkomstkonfiguration"}. {"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"}. {"Add Jabber ID","Lägg till Jabber ID"}. {"Add New","Lägg till ny"}. {"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"}. {"Allow users to change the subject","TillÃ¥t användare att byta ämne"}. {"Allow users to query other users","TillÃ¥t användare att söka efter andra användare"}. {"Allow users to send invites","TillÃ¥t användare att skicka inbjudningar"}. {"Allow users to send private messages","TillÃ¥t användare att skicka privata meddelanden"}. {"Allow visitors to change nickname","TillÃ¥t gäster att kunna ändra smeknamn"}. {"Allow visitors to send status text in presence updates","TillÃ¥t gäster att skicka statustext som uppdatering"}. {"All Users","Alla användare"}. {"Announcements","Meddelanden"}. {"anyone","Vemsomhelst"}. {"April","April"}. {"August","Augusti"}. {"Backup Management","Hantera säkerhetskopior"}. {"Backup","Säkerhetskopiera"}. {"Backup to File at ","Säkerhetskopiera till fil pÃ¥ "}. {"Bad format","DÃ¥ligt format"}. {"Birthday","Födelsedag"}. {"Change Password","Ändra lösenord"}. {"Change User Password","Andra användarlösenord"}. {"Chatroom configuration modified","Chattrum konfiguration modifierad"}. {"Chatrooms","Chattrum"}. {"Choose a username and password to register with this server","Välj ett användarnamn och lösenord för att registrera mot denna server"}. {"Choose modules to stop","Välj vilka moduler som skall stoppas"}. {"Choose storage type of tables","Välj lagringstyp för tabeller"}. {"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:"}. {"Connections parameters","Uppkopplingsparametrar"}. {"Country","Land"}. {"CPU Time:","CPU tid"}. {"Database","Databas"}. {"Database Tables Configuration at ","Databastabellers konfiguration"}. {"December","December"}. {"Default users as participants","Gör om användare till deltagare"}. {"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 User","Ta bort användare"}. {"Deliver event notifications","Skicka eventnotifikation"}. {"Deliver payloads with event notifications","Skicka innehÃ¥ll tillsammans med notifikationer"}. {"Description:","Beskrivning:"}. {"Disc only copy","Endast diskkopia"}. {"Displayed Groups:","Visade grupper:"}. {"Dump Backup to Text File at ","Dumpa säkerhetskopia till textfil pÃ¥ "}. {"Dump to Text File","Dumpa till textfil"}. {"Edit Properties","Redigera egenskaper"}. {"ejabberd IRC module","ejabberd IRC-modul"}. {"ejabberd MUC module","ejabberd MUC modul"}. {"ejabberd Publish-Subscribe module","ejabberd publikprenumerations modul"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestrem modul"}. {"ejabberd vCard module","ejabberd vCard-modul"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Elements"}. {"Email","Email"}. {"Enable logging","Möjliggör login"}. {"Encoding for server ~b","Encoding för server ~b"}. {"End User Session","Avsluta användarsession"}. {"Enter list of {Module, [Options]}","Skriv in en lista av {Module, [Options]}"}. {"Enter nickname you want to register","Skriv in smeknamnet du vill registrera"}. {"Enter path to backup file","Skriv in sökväg till fil för säkerhetskopia"}. {"Enter path to jabberd14 spool dir","Skriv in sökväg till spoolkatalog frÃ¥n jabberd14"}. {"Enter path to jabberd14 spool file","Skriv in sökväg till spoolfil frÃ¥n jabberd14"}. {"Enter path to text file","Skriv in sökväg till textfil"}. {"Enter the text you see","Skriv in sökväg till textfil"}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Skriv in användarnamn och textkodning du vill använda för att ansluta till IRC-servrar"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"Error","Fel"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Exempel: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportera data av alla användare i servern till en PIEFXIS fil (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportera data av användare i en host till PIEFXIS fil (XEP-0227):"}. {"Family Name","Efternamn"}. {"February","Februari"}. {"Fill in fields to search for any matching Jabber User","Fyll i fält för att söka efter jabberanvändare"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","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Ã¥)"}. {"Friday","Fredag"}. {"From","FrÃ¥n"}. {"From ~s","FrÃ¥n ~s"}. {"Full Name","Fullständigt namn"}. {"Get Number of Online Users","Hämta antal inloggade användare"}. {"Get Number of Registered Users","Hämta antal registrerade användare"}. {"Get User Last Login Time","Hämta användarens senast inloggade tid"}. {"Get User Password","Hämta användarlösenord"}. {"Get User Statistics","Hämta användarstatistik"}. {"Group ","Grupp "}. {"Groups","Grupper"}. {"has been banned","har blivit bannad"}. {"has been kicked because of an affiliation change","har blivit kickad p.g.a en ändring av tillhörighet"}. {"has been kicked because of a system shutdown","har blivit kickad p.g.a en systemnerstängning"}. {"has been kicked because the room has been changed to members-only","har blivit kickad p.g.a att rummet har ändrats till endast användare"}. {"has been kicked","har blivit kickad"}. {" has set the subject to: "," har satt ämnet till: "}. {"Host","Server"}. {"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.","Om du vill specifiera textkodning för IRC-servrar, fyll i listan med värden i formatet '{\"irc server\", \"encoding\", port, \"password\"}'. Som standard används \"~s\", port ~p, no password."}. {"Import Directory","Importera katalog"}. {"Import File","Importera fil"}. {"Import user data from jabberd14 spool file:","Importera användare frÃ¥n jabberd14 Spool filer"}. {"Import User from File at ","Importera användare frÃ¥n fil pÃ¥ "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importera användardata frÃ¥n en PIEFXIS fil (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","IRC kanal (skriv inte första #)"}. {"IRC server","IRC-användarnamn"}. {"IRC settings","IRC Inställningar"}. {"IRC Transport","IRC transport"}. {"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"}. {"Join IRC channel","Lägg till IRC kanal"}. {"joins the room","joinar rummet"}. {"Join the IRC channel here.","Lägg till IRC kanal här."}. {"Join the IRC channel in this Jabber ID: ~s","Lägg till IRC kanal till detta Jabber ID: ~s"}. {"July","Juli"}. {"June","Juni"}. {"Last Activity","Senast aktivitet"}. {"Last login","Senaste login"}. {"Last month","Senaste mÃ¥naden"}. {"Last year","Senaste Ã¥ret"}. {"leaves the room","lämnar rummet"}. {"Listened Ports at ","Lyssnande portar pÃ¥ "}. {"Listened Ports","Lyssnarport"}. {"List of modules to start","Lista av moduler som skall startas"}. {"Low level update script","Uppdaterade laglevel skript"}. {"Make participants list public","Gör deltagarlistan publik"}. {"Make room members-only","Gör om rummet till endast medlemmar"}. {"Make room moderated","Gör rummet modererat"}. {"Make room password protected","Gör losenorden i rummet publika"}. {"Make room persistent","Gör rummet permanent"}. {"Make room public searchable","Gör rummet publikt sökbart"}. {"March","Mars"}. {"Maximum Number of Occupants","Maximalt antal av användare"}. {"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"}. {"Modules","Moduler"}. {"Monday","MÃ¥ndag"}. {"Name:","Namn:"}. {"Name","Namn"}. {"Never","Aldrig"}. {"Nickname Registration at ","Registrera smeknamn pÃ¥ "}. {"Nickname ~s does not exist in the room","Smeknamnet ~s existerar inte i det här rummet"}. {"Nickname","Smeknamn"}. {"No body provided for announce message","Ingen kropp behövs för dessa meddelanden"}. {"No Data","Ingen data"}. {"Node ID","Node ID"}. {"Node not found","Noden finns inte"}. {"Nodes","Noder"}. {"No limit","Ingen gräns"}. {"None","Inga"}. {"No resource provided","Ingen resurs angiven"}. {"Not Found","Noden finns inte"}. {"Notify subscribers when items are removed from the node","Meddela prenumeranter när dataposter tas bort frÃ¥n noden"}. {"Notify subscribers when the node configuration changes","Meddela prenumeranter när nodens konfiguration ändras"}. {"Notify subscribers when the node is deleted","Meddela prenumeranter när noden tas bort"}. {"November","November"}. {"Number of occupants","Antal besökare"}. {"Number of online users","Antal inloggade användare"}. {"Number of registered users","Antal registrerade användare"}. {"October","Oktober"}. {"Offline Messages:","Offline meddelanden:"}. {"Offline Messages","Offline meddelanden"}. {"OK","OK"}. {"Online","Ansluten"}. {"Online Users","Anslutna användare"}. {"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"}. {"Owner privileges required","Ägarprivilegier krävs"}. {"Packet","Paket"}. {"Password ~b","Lösenord ~b"}. {"Password:","Lösenord:"}. {"Password","Lösenord"}. {"Password Verification","Lösenordsverifikation"}. {"Path to Dir","Sökväg till katalog"}. {"Path to File","Sökväg till fil"}. {"Pending","Ännu inte godkända"}. {"Period: ","Period: "}. {"Persist items to storage","Spara dataposter permanent"}. {"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.","Kom ihÃ¥g att dessa inställningar endast tar backup pa builtin Mnesias databas. Om du använder ODBC modul sÃ¥ mÃ¥ste du ta backup pÃ¥ SQLs databas enskilt"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. {"Present real Jabber IDs to","Nuvarande äkta Jabber IDs till"}. {"private, ","privat, "}. {"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 "}. {"Remote copy","Sparas inte lokalt"}. {"Remove","Ta bort"}. {"Remove User","Ta bort användare"}. {"Replaced by new connection","Ersatt av ny anslutning"}. {"Resources","Resurser"}. {"Restart","Omstart"}. {"Restart Service","Starta om servicen"}. {"Restore","Ã…terställ"}. {"Restore Backup from File at ","Ã…terställ säkerhetskopia frÃ¥n fil pÃ¥ "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Ã¥terställ den binära backupen efter nästa ejabberd omstart"}. {"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"}. {"Roster","Kontaktlista"}. {"Roster of ","Kontaktlista för "}. {"Roster size","Roster storlek"}. {"RPC Call Error","RPC Uppringningserror"}. {"Running Nodes","Körande noder"}. {"~s access rule configuration","Ã…tkomstregelkonfiguration för ~s"}. {"Saturday","Lördag"}. {"Script check","Skript kollat"}. {"Search Results for ","Sökresultat för"}. {"Search users in ","Sök efter användare pÃ¥ "}. {"Send announcement to all online users on all hosts","Sänd meddelanden till alla inloggade användare pÃ¥ alla värdar"}. {"Send announcement to all online users","Sänd meddelanden till alla inloggade användare"}. {"Send announcement to all users on all hosts","Sänd meddelanden till alla användare pÃ¥ alla värdar"}. {"Send announcement to all users","Sänd meddelanden till alla användare"}. {"September","September"}. {"Server ~b","Server ~b"}. {"Set message of the day and send to online users","Sätt dagens status meddelande och skicka till alla användare"}. {"Set message of the day on all hosts and send to online users","Sätt dagens status meddelande pa alla värdar och skicka till alla användare"}. {"Shared Roster Groups","Delade Rostergrupper"}. {"Show Integral Table","Visa kumulativ tabell"}. {"Show Ordinary Table","Visa normal tabell"}. {"Shut Down Service","Stäng ner servicen"}. {"~s invites you to the room ~s","~s bjöd in dig till rummet ~s"}. {"Specify the access model","Specificera accessmodellen"}. {"Specify the publisher model","Ange publiceringsmodell"}. {"~s's Offline Messages Queue","~s's offline meddelandekö"}. {"Start Modules at ","Starta moduler pÃ¥ "}. {"Start Modules","Starta moduler"}. {"Start","Starta"}. {"Statistics of ~p","Statistik pÃ¥ ~p"}. {"Statistics","Statistik"}. {"Stop Modules at ","Stoppa moduler pÃ¥ "}. {"Stop Modules","Stanna moduler"}. {"Stopped Nodes","Stannade noder"}. {"Stop","Stoppa"}. {"Storage Type","Lagringstyp"}. {"Store binary backup:","Lagra den binära backupen"}. {"Store plain text backup:","Lagra textbackup"}. {"Subject","Ämne"}. {"Submit","Skicka"}. {"Submitted","Skicka in"}. {"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"}. {"Time delay","Tidsförsening"}. {"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 "}. {"Transactions Restarted:","Transaktioner omstartade"}. {"Tuesday","Tisdag"}. {"Unauthorized","Ej auktoriserad"}. {"Update message of the day (don't send)","Uppdatera dagens status meddelande (skicka inte)"}. {"Update message of the day on all hosts (don't send)","Uppdatera dagens status meddelande pÃ¥ alla värdar (skicka inte)"}. {"Update plan","Uppdateringsplan"}. {"Update script","Uppdatera skript"}. {"Update","Uppdatera"}. {"Uptime:","Tid upp"}. {"Use of STARTTLS required","Du mÃ¥ste använda STARTTLS"}. {"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"}. ejabberd-16.01/priv/msgs/eo.msg0000644000232200023220000006423512645157216016714 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Agordo de atingo"}. {"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"}. {"Add Jabber ID","Aldonu Jabber ID"}. {"Add New","Aldonu novan"}. {"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"}. {"Allow users to change the subject","Permesu uzantojn ÅanÄi la temon"}. {"Allow users to query other users","Permesu uzantojn informpeti aliajn uzantojn"}. {"Allow users to send invites","Permesu uzantojn sendi invitojn"}. {"Allow users to send private messages","Permesu uzantojn sendi privatajn mesaÄojn"}. {"Allow visitors to change nickname","Permesu al vizitantoj ÅanÄi siajn kaÅnomojn"}. {"Allow visitors to send private messages to","Permesu uzantojn sendi privatajn mesaÄojn al"}. {"Allow visitors to send status text in presence updates","Permesu al vizitantoj sendi statmesaÄon en ĉeest-sciigoj"}. {"Allow visitors to send voice requests","Permesu uzantojn sendi voĉ-petojn"}. {"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"}. {"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"}. {"CAPTCHA web page","CAPTCHA teksaĵ-paÄo"}. {"Change Password","ÅœanÄu pasvorton"}. {"Change User Password","ÅœanÄu pasvorton de uzanto"}. {"Characters not allowed:","Karaktroj ne permesata:"}. {"Chatroom configuration modified","Agordo de babilejo ÅanÄita"}. {"Chatroom is created","Babilejo kreita"}. {"Chatroom is destroyed","Babilejo neniigita"}. {"Chatroom is started","Babilejo lanĉita"}. {"Chatroom is stopped","Babilejo haltita"}. {"Chatrooms","Babilejoj"}. {"Choose a username and password to register with this server","Elektu uzantnomon kaj pasvorton por registri je ĉi tiu servilo"}. {"Choose modules to stop","Elektu modulojn por fini"}. {"Choose storage type of tables","Elektu konserv-tipon de tabeloj"}. {"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:"}. {"Connections parameters","Konekto-parametroj"}. {"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 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"}. {"Delete User","Forigu Uzanton"}. {"Deliver event notifications","Liveru event-sciigojn"}. {"Deliver payloads with event notifications","Liveru aĵojn de event-sciigoj"}. {"Description:","Priskribo:"}. {"Disc only copy","Nur disk-kopio"}. {"Displayed Groups:","Montrataj grupoj:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Ne donu vian pasvorton al iun ajn, eĉ ne al la administrantoj de la Ä´abber-servilo."}. {"Dump Backup to Text File at ","Skribu sekurkopion en plata teksto al "}. {"Dump to Text File","Skribu en plata tekst-dosiero"}. {"Edit Properties","Redaktu atributojn"}. {"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"}. {"ejabberd Web Admin","ejabberd Teksaĵa Administro"}. {"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]}"}. {"Enter nickname you want to register","Enmetu kaÅnomon kiun vi volas registri"}. {"Enter path to backup file","Enmetu vojon por sekurkopio"}. {"Enter path to jabberd14 spool dir","Enmetu vojon al jabberd14-uzantdosierujo"}. {"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):"}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Kompletigu la formon por serĉi rekonata Jabber-uzanto (Aldonu * je la fino de la kampo por rekoni subĉenon"}. {"Friday","Vendredo"}. {"From","De"}. {"From ~s","De ~s"}. {"Full Name","Plena Nomo"}. {"Get Number of Online Users","Montru nombron de konektataj uzantoj"}. {"Get Number of Registered Users","Montru nombron de registritaj uzantoj"}. {"Get User Last Login Time","Montru tempon de lasta ensaluto"}. {"Get User Password","Montru pasvorton de uzanto"}. {"Get User Statistics","Montru statistikojn de uzanto"}. {"Grant voice to this person?","Koncedu voĉon al ĉi-persono?"}. {"Group ","Grupo "}. {"Groups","Grupoj"}. {"has been banned","estas forbarita"}. {"has been kicked because of an affiliation change","estas forpelita pro aparteneca ÅanÄo"}. {"has been kicked because of a system shutdown","estas forpelita pro sistem-haltigo"}. {"has been kicked because the room has been changed to members-only","estas forpelita ĉar la babilejo fariÄis sole por membroj"}. {"has been kicked","estas forpelita"}. {" has set the subject to: "," ÅanÄis la temon al: "}. {"Host","Gastigo"}. {"If you don't see the CAPTCHA image here, visit the web page.","Se vi ne vidas la CAPTCHA-imagon jene, vizitu la teksaĵ-paÄon."}. {"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 vi volas specifi diversajn pordojn, pasvortojn, enkodigojn por IRC-serviloj, kompletigu la jenan liston kun la formo '{\"irc-servilo\", \"enkodigo\", porto, \"pasvorto\"}'. Se ne specifita, ĉi tiu servilo uzas la enkodigo \"~s\", porto ~p, malplena pasvorto."}. {"Import Directory","Importu dosierujo"}. {"Import File","Importu dosieron"}. {"Import user data from jabberd14 spool file:","Importu uzantojn de jabberd14-uzantdosieroj"}. {"Import User from File at ","Importu uzanton de dosiero el "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importu uzanto-datumojn de PIEFXIS dosiero (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","IRC-babilejo (ne aldonu #-prefikson)"}. {"IRC server","IRC-servilo"}. {"IRC settings","IRC agordoj"}. {"IRC Transport","IRC-transportilo"}. {"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"}. {"January","Januaro"}. {"Join IRC channel","Eniras IRC-babilejon"}. {"joins the room","eniras la babilejo"}. {"Join the IRC channel here.","Eniru IRC-babilejon jen"}. {"Join the IRC channel in this Jabber ID: ~s","Eniru IRC-babilejon en ĉi Jabber-ID: ~s"}. {"July","Julio"}. {"June","Junio"}. {"Last Activity","Lasta aktiveco"}. {"Last login","Lasta ensaluto"}. {"Last month","Lasta monato"}. {"Last year","Lasta jaro"}. {"leaves the room","eliras la babilejo"}. {"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"}. {"Make room members-only","Farigu babilejon sole por membroj"}. {"Make room moderated","Farigu babilejon moderigata"}. {"Make room password protected","Farigu babilejon protektata per pasvorto"}. {"Make room persistent","Farigu babilejon daÅ­ra"}. {"Make room public searchable","Farigu babilejon publike trovebla"}. {"March","Marĉo"}. {"Maximum Number of Occupants","Limigo de nombro de partoprenantoj"}. {"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"}. {"Modules at ~p","Moduloj je ~p"}. {"Modules","Moduloj"}. {"Monday","Lundo"}. {"Multicast","Multicast"}. {"Multi-User Chat","Grupbabilado"}. {"Name:","Nomo:"}. {"Name","Nomo"}. {"Never","Neniam"}. {"New Password:","Nova Pasvorto:"}. {"Nickname","KaÅnomo"}. {"Nickname Registration at ","KaÅnomo-registrado je "}. {"Nickname ~s does not exist in the room","KaÅnomo ~s ne ekzistas en la babilejo"}. {"nobody","neniu"}. {"No body provided for announce message","Neniu teksto donita por anonc-mesaÄo"}. {"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"}. {"No resource provided","Neniu risurco donita"}. {"Not Found","Ne trovita"}. {"Notify subscribers when items are removed from the node","Sciigu abonantoj kiam eroj estas forigita de la nodo"}. {"Notify subscribers when the node configuration changes","Sciigu abonantoj kiam la agordo de la nodo ÅanÄas"}. {"Notify subscribers when the node is deleted","Sciigu abonantoj kiam la nodo estas forigita"}. {"November","Novembro"}. {"Number of occupants","Nombro de ĉeestantoj"}. {"Number of online users","Nombro de konektataj uzantoj"}. {"Number of registered users","Nombro de registritaj uzantoj"}. {"October","Oktobro"}. {"Offline Messages:","Liverontaj mesaÄoj"}. {"Offline Messages","Liverontaj mesaÄoj"}. {"OK","Bone"}. {"Old Password:","Malnova Pasvorto:"}. {"Online","Konektata"}. {"Online Users:","Konektataj uzantoj:"}. {"Online Users","Konektataj Uzantoj"}. {"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"}. {"Owner privileges required","Mastraj rajtoj bezonata"}. {"Packet","Pakaĵo"}. {"Password ~b","Pasvorto ~b"}. {"Password:","Pasvorto:"}. {"Password","Pasvorto"}. {"Password Verification:","Pasvortkontrolo:"}. {"Password Verification","Pasvortkontrolo"}. {"Path to Dir","Vojo al dosierujo"}. {"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."}. {"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"}. {"Present real Jabber IDs to","Montru verajn Jabber ID-ojn al"}. {"private, ","privata, "}. {"Protocol","Protokolo"}. {"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:"}. {"Registered Users","Registritaj uzantoj"}. {"Register","Registru"}. {"Registration in mod_irc for ","Registraĵo en mod_irc de "}. {"Remote copy","Fora kopio"}. {"Remove All Offline Messages","Forigu ĉiujn liverontajn mesaÄojn"}. {"Remove","Forigu"}. {"Remove User","Forigu uzanton"}. {"Replaced by new connection","AnstataÅ­igita je nova konekto"}. {"Resources","Risurcoj"}. {"Restart","Restartu"}. {"Restart Service","Restartu Servon"}. {"Restore Backup from File at ","RestaÅ­rigu de dosiero el "}. {"Restore binary backup after next ejabberd restart (requires less memory):","RestaÅ­rigu duuman sekurkopion post sekvonta ejabberd-restarto"}. {"Restore binary backup immediately:","RestaÅ­rigu duuman sekurkopion tuj:"}. {"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"}. {"Roster groups allowed to subscribe","Kontaktlist-grupoj kiuj rajtas aboni"}. {"Roster","Kontaktlisto"}. {"Roster of ","Kontaktlisto de "}. {"Roster size","Kontaktlist-grando"}. {"RPC Call Error","Eraro de RPC-alvoko"}. {"Running Nodes","Funkciantaj Nodoj"}. {"~s access rule configuration","Agordo de atingo-reguloj de ~s"}. {"Saturday","Sabato"}. {"Script check","Skript-kontrolo"}. {"Search Results for ","Serĉ-rezultoj de "}. {"Search users in ","Serĉu uzantojn en "}. {"Send announcement to all online users on all hosts","Sendu anoncon al ĉiu konektata uzanto de ĉiu gastigo"}. {"Send announcement to all online users","Sendu anoncon al ĉiu konektata uzanto"}. {"Send announcement to all users on all hosts","Sendu anoncon al ĉiu uzanto de ĉiu gastigo"}. {"Send announcement to all users","Sendu anoncon al ĉiu uzanto"}. {"September","Septembro"}. {"Server ~b","Servilo ~b"}. {"Server:","Servilo:"}. {"Set message of the day and send to online users","Enmetu mesaÄon de la tago kaj sendu al konektataj uzantoj"}. {"Set message of the day on all hosts and send to online users","Enmetu mesaÄon de la tago je ĉiu gastigo kaj sendu al konektataj uzantoj"}. {"Shared Roster Groups","Komuna Kontaktlist-grupo"}. {"Show Integral Table","Montru integran tabelon"}. {"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 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"}. {"~s's Offline Messages Queue","MesaÄo-atendovico de ~s"}. {"Start Modules at ","Startu modulojn je "}. {"Start Modules","Startu Modulojn"}. {"Start","Startu"}. {"Statistics of ~p","Statistikoj de ~p"}. {"Statistics","Statistikoj"}. {"Stop","Haltigu"}. {"Stop Modules at ","Haltigu modulojn je "}. {"Stop Modules","Haltigu Modulojn"}. {"Stopped Nodes","Neaktivaj Nodoj"}. {"Storage Type","Konserv-tipo"}. {"Store binary backup:","Konservu duuman sekurkopion:"}. {"Store plain text backup:","Skribu sekurkopion en plata tekstdosiero"}. {"Subject","Temo"}. {"Submit","Sendu"}. {"Submitted","Sendita"}. {"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:"}. {"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."}. {"Thursday","Ä´aÅ­do"}. {"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"}. {"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"}. {"Use of STARTTLS required","Uzo de STARTTLS bezonata"}. {"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"}. {"User","Uzanto"}. {"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"}. ejabberd-16.01/priv/msgs/cs.po0000644000232200023220000014453312645157216016546 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "Last-Translator: Lukáš Polívka [spike411] xmpp:spike411@jabber.cz\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Czech (ÄeÅ¡tina)\n" "X-Additional-Translator: Milos Svasek [DuxforD] from openheads.net\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Je vyžadováno STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nebyl poskytnut žádný zdroj" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Nahrazeno novým spojením" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Zadejte text, který vidíte" #: 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: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:227 msgid "CAPTCHA web page" msgstr "Webová stránka CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "CAPTCHA souhlasí." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "Nemáte oprávnÄ›ní" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Webová administrace ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administrace" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Zdroj" #: 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: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:913 msgid "~s access rule configuration" msgstr "~s konfigurace pravidla přístupu" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuální hostitelé" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Uživatelé" #: 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:971 msgid "Users Last Activity" msgstr "Poslední aktivita uživatele" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "ÄŒas: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Poslední mÄ›síc" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Poslední rok" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "VÅ¡echny aktivity" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Zobrazit běžnou tabulku" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Zobrazit kompletní tabulku" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiky" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nenalezeno" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Uzel nenalezen" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "PÅ™idat nový" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Hostitel" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrovaní uživatelé" #: 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:1459 msgid "Offline Messages" msgstr "Offline zprávy" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Poslední aktivita" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nikdy" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Online" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrovaní živatelé:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Odchozí s2s spojení:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Odchozí 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 msgid "None" msgstr "Nic" #: 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:1673 #, fuzzy msgid "User ~s" msgstr "Uživatel " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "PÅ™ipojené zdroje:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Heslo:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Odstranit uživatele" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Žádná data" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Uzly" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Běžící uzly" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zastavené uzly" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Uzel " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databáze" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Zálohovat" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "OtevÅ™ené porty" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aktualizovat" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Restart" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stop" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduly" #: ejabberd_web_admin.erl:1866 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 " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Jméno" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Typ úložiÅ¡tÄ›" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Položek" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Paměť" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Chyba" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Záloha na " #: 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 "" "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Ä›." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Uložit binární zálohu:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "OkamžitÄ› obnovit binární zálohu:" #: 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:1999 msgid "Store plain text backup:" msgstr "Uložit zálohu do textového souboru:" #: 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: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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importovat uživatele z jabberd14 spool souborů:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "OtevÅ™ené porty na " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduly na " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistiky ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "ÄŒas bÄ›hu:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "ÄŒas procesoru" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transakce potvrzena" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transakce zruÅ¡ena" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transakce restartována" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transakce zaznamenána" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Aktualizovat " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Aktualizovat plán" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Aktualizované moduly" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Aktualizované skripty" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Nízkoúrovňový aktualizaÄní skript" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Kontrola skriptu" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokol" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Nastavení" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Start" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Příkazy" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "SkuteÄnÄ› smazat zprávu dne?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "PÅ™edmÄ›t" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "TÄ›lo zprávy" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Zpráva neobsahuje text" #: mod_announce.erl:662 msgid "Announcements" msgstr "Oznámení" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Odeslat oznámení vÅ¡em uživatelům" #: 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:668 msgid "Send announcement to all online users" msgstr "Odeslat oznámení vÅ¡em online uživatelům" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Aktualizovat zprávu dne (neodesílat)" #: 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:680 msgid "Delete message of the day" msgstr "Smazat zprávu dne" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Konfigurace" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Spustit moduly" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Zastavit moduly" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Obnovit" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Uložit do textového souboru" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Import souboru" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Import adresáře" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Restartovat službu" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Vypnout službu" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Smazat uživatele" #: 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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "ZmÄ›nit heslo uživatele" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Získat statistiky uživatele" #: 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:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Získat poÄet online uživatelů" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Správa uživatelů" #: mod_configure.erl:525 msgid "All Users" msgstr "VÅ¡ichni uživatelé" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Odchozí s2s spojení" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Správa zálohování" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importovat uživatele z jabberd14 spool souborů" #: mod_configure.erl:762 msgid "To ~s" msgstr "Pro ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Od ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Konfigurace databázových tabulek " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Vyberte typ úložiÅ¡tÄ› pro tabulky" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Jen kopie disku" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Kopie RAM a disku" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Kopie RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Vzdálená kopie" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Zastavit moduly na " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Vyberte moduly, které mají být zastaveny" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Spustit moduly na " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Vložte seznam modulů {Modul, [Parametry]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Seznam modulů, které mají být spuÅ¡tÄ›né" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Záloha do souboru na " #: 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:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Cesta k souboru" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Obnovit zálohu ze souboru na " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Uložit zálohu do textového souboru na " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Zadajte cestu k textovému souboru" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importovat uživatele ze souboru na " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Zadejte cestu k spool souboru jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importovat uživatele z adresáře na " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Zadejte cestu k jabberd14 spool adresáři" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Cesta k adresáři" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "ÄŒasový posun" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfigurace seznamu přístupových práv (ACL)" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Seznamy přístupových práv (ACL)" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Konfigurace přístupů" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Ověření hesla" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "PoÄet registrovaných uživatelů" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "PoÄet online uživatelů" #: mod_configure.erl:1936 msgid "Last login" msgstr "Poslední pÅ™ihlášení" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Velikost seznamu kontaktů" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresy" #: mod_configure.erl:1967 msgid "Resources" msgstr "Zdroje" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administrace " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Akce aplikovaná na uživatele" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Upravit vlastnosti" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modul" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registrace do mod_irc na " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" 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:667 msgid "IRC Username" msgstr "IRC pÅ™ezdívka" #: 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." msgstr "" "Pokud chcete zadat jiné kódování pro IRC servery, vyplňte seznam s hodnotami " "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:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." 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:713 msgid "Connections parameters" msgstr "Parametry spojení" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Vstoupit do IRC kanálu" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanál (bez poÄáteÄního #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC pÅ™ezdívka" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Vstoupit do tohoto IRC kanálu." #: 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:1046 msgid "IRC settings" msgstr "Nastavení IRC" #: 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 "" "Zadejte pÅ™ezdívku a kódování, které chcete používat pro pÅ™ipojení k serverům " "IRC. StisknÄ›te 'Další' pro více políÄek k vyplnÄ›ní. StisknÄ›te 'DokonÄit' pro " "uložení nastavení." #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC pÅ™ezdívka" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Heslo ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Kódování pro server ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registrace pÅ™ezdívky na " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "PÅ™ezdívka" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Konference" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "opustil(a) místnost" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Registrovaní uživatelé" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: 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:410 msgid "joins the room" msgstr "vstoupil(a) do místnosti" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "opustil(a) místnost" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "byl(a) zablokován(a)" #: 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: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: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:450 msgid "is now known as" msgstr "se pÅ™ejmenoval(a) na" #: 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:493 msgid "Chatroom is created" msgstr "Konference vytvoÅ™ena" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Konference zruÅ¡ena" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Konference spuÅ¡tÄ›na" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Konference zastavena" #: mod_muc_log.erl:503 msgid "Monday" msgstr "PondÄ›lí" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Úterý" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "StÅ™eda" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "ÄŒtvrtek" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Pátek" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sobota" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "NedÄ›le" #: mod_muc_log.erl:513 msgid "January" msgstr ". ledna" #: mod_muc_log.erl:514 msgid "February" msgstr ". února" #: mod_muc_log.erl:515 msgid "March" msgstr ". bÅ™ezna" #: mod_muc_log.erl:516 msgid "April" msgstr ". dubna" #: mod_muc_log.erl:517 msgid "May" msgstr ". kvÄ›tna" #: mod_muc_log.erl:518 msgid "June" msgstr ". Äervna" #: mod_muc_log.erl:519 msgid "July" msgstr ". Äervence" #: mod_muc_log.erl:520 msgid "August" msgstr ". srpna" #: mod_muc_log.erl:521 msgid "September" msgstr ". září" #: mod_muc_log.erl:522 msgid "October" msgstr ". října" #: mod_muc_log.erl:523 msgid "November" msgstr ". listopadu" #: mod_muc_log.erl:524 msgid "December" msgstr ". prosince" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Nastavení místnosti" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "PoÄet úÄastníků" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "PÅ™ezdívka ~s v místnosti neexistuje" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Neplatné pÅ™iÅ™azení: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Neplatná role: ~s" #: 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:3359 msgid "Room title" msgstr "Název místnosti" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Popis místnosti" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Nastavit místnost jako stálou" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Nastavit místnost jako veÅ™ejnou" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Nastavit seznam úÄastníků jako veÅ™ejný" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Chránit místnost heslem" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "PoÄet úÄastníků" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Bez limitu" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Odhalovat skuteÄná Jabber ID" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderátorům" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "každému" #: 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:3516 msgid "Make room moderated" msgstr "Nastavit místnost jako moderovanou" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Uživatelé jsou implicitnÄ› Äleny" #: 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:3525 msgid "Allow users to send private messages" msgstr "Povolit uživatelům odesílat soukromé zprávy" #: 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:3551 msgid "nobody" msgstr "nikdo" #: 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:3579 msgid "Allow users to send invites" msgstr "Povolit uživatelům posílání pozvánek" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Povolit návÅ¡tÄ›vníkům mÄ›nit pÅ™ezdívku" #: 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: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:3599 msgid "Make room CAPTCHA protected" msgstr "Chránit místnost pomocí CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: 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:3621 msgid "Enable logging" msgstr "Zaznamenávat konverzace" #: 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:4190 msgid "Number of occupants" msgstr "PoÄet úÄastníků" #: mod_muc_room.erl:4260 msgid "private, " msgstr "soukromá, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Žádost o voice práva" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Povolit nebo odmítnout voice žádost." #: mod_muc_room.erl:4349 msgid "User JID" msgstr "Jabber ID uživatele" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "UdÄ›lit voice práva této osobÄ›?" #: 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:4507 msgid "the password is" msgstr "heslo je" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "ÄŒas" #: mod_offline.erl:812 msgid "From" msgstr "Od" #: mod_offline.erl:813 msgid "To" msgstr "Pro" #: mod_offline.erl:814 msgid "Packet" msgstr "Paket" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline zprávy:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Odstranit vÅ¡echny offline zprávy" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Žádost odbÄ›ratele PubSub" #: 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:1559 msgid "Node ID" msgstr "ID uzlu" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adresa odbÄ›ratele" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "DoruÄovat náklad s upozornÄ›ním na událost" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "DoruÄovat upozornÄ›ní na události" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Upozornit odbÄ›ratele na zmÄ›nu nastavení uzlu" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Upozornit odbÄ›ratele na smazání uzlu" #: 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:3755 msgid "Persist items to storage" msgstr "Uložit položky natrvalo do úložiÅ¡tÄ›" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "PřívÄ›tivé jméno pro uzel" #: 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:3761 msgid "Whether to allow subscriptions" msgstr "Povolit odebírání" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "UveÄte přístupový model" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Skupiny kontaktů, které mohou odebírat" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Specifikovat model pro publikování" #: 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:3771 msgid "Specify the event message type" msgstr "Zvolte typ zpráv pro události" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maximální náklad v bajtech" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Kdy odeslat poslední publikovanou položku" #: 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:3779 msgid "The collections with which a node is affiliated" msgstr "Kolekce, se kterými je uzel spříznÄ›n" #: 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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "PÅ™i vytváření úÄtu doÅ¡lo k chybÄ›." #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Váš úÄet Jabberu byl úspěšnÄ› smazán." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "PÅ™i mazání úÄtu doÅ¡lo k chybÄ›: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Heslo vaÅ¡eho úÄtu Jabberu bylo úspěšnÄ› zmÄ›nÄ›no." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "PÅ™i zmÄ›nÄ› hesla doÅ¡lo k chybÄ›: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Registrace úÄtu Jabberu" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Zaregistrujte si úÄet Jabberu" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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ů." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Uživatelské jméno:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Zde nezáleží na velikosti písmen: macbeth je stejný jako MacBeth a Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Nepřípustné znaky:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" #: 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: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: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 "" "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: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 "" "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:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Ověření hesla:" #: mod_register_web.erl:269 msgid "Register" msgstr "Zaregistrovat se" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "SouÄasné heslo:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nové heslo:" #: 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:480 msgid "Unregister" msgstr "ZruÅ¡it registraci" #: mod_roster.erl:1436 msgid "Subscription" msgstr "PÅ™ihlášení" #: mod_roster.erl:1437 msgid "Pending" msgstr "ÄŒekající" #: mod_roster.erl:1438 msgid "Groups" msgstr "Skupiny" #: mod_roster.erl:1476 msgid "Validate" msgstr "Ověřit" #: mod_roster.erl:1485 msgid "Remove" msgstr "Odstranit" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Seznam kontaktů " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "PÅ™idat Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Seznam kontaktů" #: 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:1232 msgid "Name:" msgstr "Jméno:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Popis:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "ÄŒlenové:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Zobrazené skupiny:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Skupina " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Datum narození" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "MÄ›sto" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "ZemÄ›" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-mail" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Příjmení" #: 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 "" "Pro vyhledání uživatele Jabberu vyplňte formulář (na konec pÅ™idejte znak * " "pro vyhledání podÅ™etÄ›zce)" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Celé jméno" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Druhé jméno" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Název firmy" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "OddÄ›lení" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Hledat uživatele v " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Hledání uživatelů podle vizitek" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard modul" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Výsledky hledání pro " #: 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 "Outgoing s2s Servers:" #~ msgstr "Odchozí s2s servery:" #~ msgid "Delete" #~ msgstr "Smazat" #~ msgid "This room is not anonymous" #~ msgstr "Tato místnost není anonymní" #~ 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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Tento úÄastník byl vyhozen, protože odeslal chybovou zprávu jinému " #~ "úÄastníkovi" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "ZkouÅ¡ka CAPTCHA neproÅ¡la." ejabberd-16.01/priv/msgs/pl.po0000644000232200023220000014574312645157216016560 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: PaweÅ‚ Chmielowski \n" "Language-Team: \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Polish (polski)\n" "X-Additional-Translator: Janusz B. WiÅ›niewski\n" "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:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Wymagane jest użycie STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nie podano zasobu" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Połączenie zostaÅ‚o zastÄ…pione" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Przepisz tekst z obrazka" #: 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: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:227 msgid "CAPTCHA web page" msgstr "Strona internetowa CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Captcha jest poprawna." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "Nie autoryzowano" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd: Panel Administracyjny" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administracja" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Å»ródÅ‚o" #: 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: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:913 msgid "~s access rule configuration" msgstr "~s konfiguracja zasad dostÄ™pu" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Wirtualne Hosty" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Użytkownicy" #: 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:971 msgid "Users Last Activity" msgstr "Ostatnia aktywność użytkowników" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "PrzedziaÅ‚ czasu: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Miniony miesiÄ…c" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Miniony rok" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "CaÅ‚a aktywność" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Pokaż zwykłą tabelÄ™" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Pokaż tabelÄ™ caÅ‚kowitÄ…" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statystyki" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nie znaleziono" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "WÄ™zeÅ‚ nie zostaÅ‚ znaleziony" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Dodaj nowe" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Użytkownicy zarejestrowani" #: 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:1459 msgid "Offline Messages" msgstr "WiadomoÅ›ci offline" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Ostatnia aktywność" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nigdy" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "DostÄ™pny" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Użytkownicy zarejestrowani:" #: 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:1556 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:" #: 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: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:1673 msgid "User ~s" msgstr "Użytkownik ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Zasoby zalogowane:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "HasÅ‚o:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "UsuÅ„ użytkownika" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Brak danych" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "WÄ™zÅ‚y" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Uruchomione wÄ™zÅ‚y" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zatrzymane wÄ™zÅ‚y" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "WÄ™zeÅ‚ ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Baza danych" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Wykonaj kopie" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Porty nasÅ‚uchujÄ…ce" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aktualizuj" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Uruchom ponownie" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Zatrzymaj" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "ModuÅ‚y" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Błąd żądania RPC" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Tabele bazy na ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "ImiÄ™" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Typ bazy" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementy" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Pamięć" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Błąd" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Kopia zapasowa ~p" #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Zachowaj kopiÄ™ binarnÄ…:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Natychmiast odtwórz kopiÄ™ binarnÄ…:" #: 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:1999 msgid "Store plain text backup:" msgstr "Zachowaj kopiÄ™ w postaci tekstowej:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Natychmiast odtwórz kopiÄ™ z postaci tekstowej:" #: 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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Wyeksportuj wszystkie tabele jako zapytania SQL do pliku:" #: 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:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importuj użytkowników z katalogu roboczego serwera jabberd14" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Porty nasÅ‚uchujÄ…ce na " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "ModuÅ‚y na ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statystyki ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Czas pracy:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Czas CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transakcje zakoÅ„czone:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transakcje anulowane:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transakcje uruchomione ponownie:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transakcje zalogowane:" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Uaktualnij ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan aktualizacji" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Zmodyfikowane moduÅ‚y" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Skrypt aktualizacji" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Skrypt aktualizacji niskiego poziomu" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Sprawdź skrypt" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokół" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "ModuÅ‚" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opcje" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Uruchom" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Polecenia" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Na pewno usunąć wiadomość dnia?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Temat" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Treść wiadomoÅ›ci" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Brak treÅ›ci powiadomienia" #: mod_announce.erl:662 msgid "Announcements" msgstr "Powiadomienia" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "WyÅ›lij powiadomienie do wszystkich użytkowników" #: 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:668 msgid "Send announcement to all online users" msgstr "WyÅ›lij powiadomienie do wszystkich zalogowanych użytkowników" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Aktualizuj wiadomość dnia (bez wysyÅ‚ania)" #: 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:680 msgid "Delete message of the day" msgstr "UsuÅ„ wiadomość dnia" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "UsuÅ„ wiadomość dnia ze wszystkich hostów" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Konfiguracja" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Uruchom moduÅ‚y" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Zatrzymaj moduÅ‚y" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Przywróć z kopii" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Wykonaj kopie do pliku tekstowego" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importuj plik" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importuj katalog" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Restart usÅ‚ugi" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Wyłącz usÅ‚ugÄ™" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "UsuÅ„ użytkownika" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "ZakoÅ„cz sesjÄ™ uzytkownika" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "ZmieÅ„ hasÅ‚o użytkownika" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Pobierz statystyki użytkownika" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Pokaż liczbÄ™ zarejestrowanych użytkowników" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Pokaż liczbÄ™ zalogowanych użytkowników" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "ZarzÄ…dzanie użytkownikami" #: mod_configure.erl:525 msgid "All Users" msgstr "Wszyscy użytkownicy" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "WychodzÄ…ce połączenia s2s" #: mod_configure.erl:615 msgid "Backup Management" msgstr "ZarzÄ…dzanie kopiami zapasowymi" #: 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:762 msgid "To ~s" msgstr "Do ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Od ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Konfiguracja tabel bazy na " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Wybierz typ bazy dla tablel" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Kopia tylko na dysku" #: 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:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Kopia w pamiÄ™ci RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Kopia zdalna" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Zatrzymaj moduÅ‚y na " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Wybierz moduÅ‚y do zatrzymania" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Uruchom moduÅ‚y na " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Wprowadź listÄ™ {ModuÅ‚, [Opcje]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista modułów do uruchomienia" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Zapisz kopiÄ™ w pliku na " #: 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: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:1115 msgid "Restore Backup from File at " msgstr "Odtwórz bazÄ™ danych z kopii zapasowej na " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Zapisz kopiÄ™ zapasowÄ… w pliku tekstowym na " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Wprowadź scieżkÄ™ do pliku tekstowego" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importuj użytkownika z pliku na " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Wprowadź Å›cieżkÄ™ do roboczego pliku serwera jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importuj użytkowników z katalogu na " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Wprowadź Å›cieżkÄ™ do roboczego katalogu serwera jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Åšcieżka do katalogu" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Opóźnienie" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfiguracja listy dostÄ™powej" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listy dostÄ™powe" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Konfiguracja dostÄ™pu" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Weryfikacja hasÅ‚a" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Liczba zarejestrowanych użytkowników" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Liczba zalogowanych użytkowników" #: mod_configure.erl:1936 msgid "Last login" msgstr "Ostatnie logowanie" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Rozmiar listy kontaktów" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Adresy IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Zasoby" #: mod_configure.erl:2095 msgid "Administration of " msgstr "ZarzÄ…dzanie " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Wykonaj na użytkowniku" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Edytuj wÅ‚aÅ›ciwoÅ›ci" #: mod_fail2ban.erl:95 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_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: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:476 msgid "ejabberd IRC module" msgstr "ModuÅ‚ IRC ejabberd" #: 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:653 msgid "Registration in mod_irc for " msgstr "Rejestracja w mod_irc dla " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "Wprowadź nazwÄ™ użytkownika, port i kodowanie, których chcesz używać do " "łączenia z serwerami IRC" #: mod_irc.erl:667 msgid "IRC Username" msgstr "Nazwa użytkownika IRC" #: 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." msgstr "" "JeÅ›li chcesz ustawić inne hasÅ‚a, porty lub kodowania dla poszczególnych " "serwerów IRC, wypeÅ‚nij tÄ… listÄ™ wartoÅ›ciami w formacie '{\"irc server\"," "\"encoding\", port, \"password\"}'. DomyÅ›lne ta usÅ‚uga używa kodowania \"~s" "\", portu ~p, bez hasÅ‚a." #: 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 "" "PrzykÅ‚ad: [{\"wroclaw.irc.pl\",\"utf-8\"}, {\"warszawa.irc.pl\", " "\"iso8859-2\"}]." #: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parametry połączeÅ„" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Dołącz do kanaÅ‚u IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "KanaÅ‚ IRC (nie używaj #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Serwer IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Dołącz do kanaÅ‚u IRC." #: 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:1046 msgid "IRC settings" msgstr "Ustawienia IRC" #: 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 "" "Wprowadź nazwÄ™ użytkownika i kodowania których chcesz używać do łączenia z " "serwerami IRC. WciÅ›nij \"Dalej\" aby ustawić wiÄ™cej parametrów połączenia. " "WciÅ›nij \"ZakoÅ„cz\" aby zapisać ustawienia." #: mod_irc.erl:1060 msgid "IRC username" msgstr "Nazwa użytkownika IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "HasÅ‚o ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Kodowanie znaków dla serwera ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Serwer ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Rejestracja nazwy użytkownika na " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Nazwa użytkownika" #: 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" #: 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:249 msgid "Total rooms" msgstr "Wszystkich pokoi" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "StaÅ‚ych pokoi" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Zarejestrowanych nicków" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Lista pokoi" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Konfiguracja pokoju zmodyfikowana" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "dołącza do pokoju" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "opuszcza pokój" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "zostaÅ‚ wykluczony" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "zostaÅ‚ wyrzucony z powodu wyłączenia systemu" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "jest teraz znany jako" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " zmieniÅ‚ temat na: " #: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Pokój zostaÅ‚ stworzony" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Pokój zostaÅ‚ usuniÄ™ty" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Pokój zostaÅ‚ uruchomiony" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Pokój zostaÅ‚ zatrzymany" #: mod_muc_log.erl:503 msgid "Monday" msgstr "PoniedziaÅ‚ek" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Wtorek" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Åšroda" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Czwartek" #: mod_muc_log.erl:507 msgid "Friday" msgstr "PiÄ…tek" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sobota" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Niedziela" #: mod_muc_log.erl:513 msgid "January" msgstr "StyczeÅ„" #: mod_muc_log.erl:514 msgid "February" msgstr "Luty" #: mod_muc_log.erl:515 msgid "March" msgstr "Marzec" #: mod_muc_log.erl:516 msgid "April" msgstr "KwiecieÅ„" #: mod_muc_log.erl:517 msgid "May" msgstr "Maj" #: mod_muc_log.erl:518 msgid "June" msgstr "Czerwiec" #: mod_muc_log.erl:519 msgid "July" msgstr "Lipiec" #: mod_muc_log.erl:520 msgid "August" msgstr "SierpieÅ„" #: mod_muc_log.erl:521 msgid "September" msgstr "WrzesieÅ„" #: mod_muc_log.erl:522 msgid "October" msgstr "Październik" #: mod_muc_log.erl:523 msgid "November" msgstr "Listopad" #: mod_muc_log.erl:524 msgid "December" msgstr "GrudzieÅ„" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Konfiguracja pokoju" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Lista uczestników" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Nie ma nicka ~s w tym pokoju" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "NieprawidÅ‚owa przynależność: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "NieprawidÅ‚owa rola: ~s" #: 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:3359 msgid "Room title" msgstr "TytuÅ‚ pokoju" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Opis pokoju" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Utwórz pokój na staÅ‚e" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Pozwól wyszukiwać pokój" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Upublicznij listÄ™ uczestników" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Pokój zabezpieczony hasÅ‚em" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maksymalna liczba uczestników" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Bez limitu" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Prawdziwe Jabber ID widoczne dla" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "tylko moderatorzy" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "wszystkich" #: 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:3516 msgid "Make room moderated" msgstr "Pokój moderowany" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "DomyÅ›lni użytkownicy jako uczestnicy" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Pozwól użytkownikom zmieniać temat" #: 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:3533 msgid "Allow visitors to send private messages to" msgstr "Pozwól użytkownikom wysyÅ‚ać prywatne wiadomoÅ›ci" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "nikt" #: 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:3579 msgid "Allow users to send invites" msgstr "Pozwól użytkownikom wysyÅ‚ać zaproszenia" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Pozwól uczestnikom na zmianÄ™ nicka" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Pozwól użytkownikom wysyÅ‚ać zaproszenia" #: 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:3599 msgid "Make room CAPTCHA protected" msgstr "Pokój zabezpieczony captchÄ…" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Włącz archiwizowanie rozmów" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "PomiÅ„ Jabber ID z żądania CAPTCHA" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Włącz logowanie" #: 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:4190 msgid "Number of occupants" msgstr "Liczba uczestników" #: mod_muc_room.erl:4260 msgid "private, " msgstr "prywatny, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Żądanie gÅ‚osowe" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Zatwierdź lub odrzuć żądanie gÅ‚osowe" #: mod_muc_room.erl:4349 msgid "User JID" msgstr "Użytkownik " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Udzielić gÅ‚osu tej osobie?" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s zaprasza CiÄ™ do pokoju ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "hasÅ‚o to:" #: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "Serwis multicast ejabbera" #: 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:811 msgid "Time" msgstr "Czas" #: mod_offline.erl:812 msgid "From" msgstr "Od" #: mod_offline.erl:813 msgid "To" msgstr "Do" #: mod_offline.erl:814 msgid "Packet" msgstr "Pakiet" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "WiadomoÅ›ci offline:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "UsuÅ„ wszystkie wiadomoÅ›ci typu 'Offline'" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ModuÅ‚ SOCKS5 Bytestreams" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "PubSub" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ModuÅ‚ Publish-Subscribe" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Żądanie subskrybcji PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Wybierz, czy akceptować subskrypcjÄ™ tej jednostki" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID wÄ™zÅ‚a" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adres subskrybenta" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Dostarczaj zawartość publikacji wraz z powiadomieniami o zdarzeniach" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Dostarczaj powiadomienia o zdarzeniach" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Informuj subskrybentów o usuniÄ™ciu wÄ™zÅ‚a" #: 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:3755 msgid "Persist items to storage" msgstr "Przechowuj na staÅ‚e dane PubSub" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Przyjazna nazwa wÄ™zÅ‚a" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maksymalna liczba przechowywanych przedmiotów" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Czy pozwolić na subskrypcje" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "OkreÅ›l model dostÄ™pu" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Grupy kontaktów uprawnione do subskrypcji" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "OkreÅ›l model publikujÄ…cego" #: 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:3771 msgid "Specify the event message type" msgstr "OkreÅ›l typ wiadomoÅ›ci" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maksymalna wielkość powiadomienia w bajtach" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Kiedy wysÅ‚ać ostatnio opublikowanÄ… rzecz" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Dostarczaj powiadomienia tylko dostÄ™pnym użytkownikom" #: 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: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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "WystÄ…piÅ‚ błąd podczas tworzenia konta:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Twoje konto zostaÅ‚o usuniÄ™te." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Podczas usuwania konta wystÄ…piÅ‚ błąd:" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "HasÅ‚o do Twojego konta zostaÅ‚o zmienione." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Podczas próby zmiany hasÅ‚a wystÄ…piÅ‚ błąd:" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "ZakÅ‚adanie konta Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Załóż konto Jabber" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "UsuÅ„ konto Jabber" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nazwa użytkownika:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Pole nie rozróżnia wielkoÅ›ci liter: sÅ‚owo Hanna jest takie samo jak hAnna " "lub haNNa." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Te znaki sÄ… niedozwolone:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Serwer:" #: 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: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: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 "" "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: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 "" "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:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Weryfikacja hasÅ‚a:" #: mod_register_web.erl:269 msgid "Register" msgstr "Zarejestruj" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Stare hasÅ‚o:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nowe hasÅ‚o:" #: 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:480 msgid "Unregister" msgstr "Wyrejestruj" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Subskrypcja" #: mod_roster.erl:1437 msgid "Pending" msgstr "Oczekuje" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grupy" #: mod_roster.erl:1476 msgid "Validate" msgstr "Potwierdź" #: mod_roster.erl:1485 msgid "Remove" msgstr "UsuÅ„" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista kontaktów " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Dodaj Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Lista kontaktów" #: 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:1232 msgid "Name:" msgstr "Nazwa:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Opis:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "CzÅ‚onkowie:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "WyÅ›wietlane grupy:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupa " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Data urodzenia" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Miasto" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "PaÅ„stwo" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Nazwisko" #: 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 "" "WypeÅ‚nij formularz aby wyszukać użytkowników Jabbera (dodaj * na koniec " "zapytania aby wyszukać po fragmencie)" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "PeÅ‚na nazwa" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Drugie imiÄ™" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nazwa organizacji" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "DziaÅ‚" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Wyszukaj użytkowników w " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Wyszukiwanie vCard użytkowników" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ModuÅ‚ vCard ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Wyniki wyszukiwania dla " #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Ten uczestnik zostaÅ‚ wyrzucony z pokoju ponieważ wysÅ‚aÅ‚ komunikat błędu " #~ "do innego uczestnika" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Captcha jest poprawna." ejabberd-16.01/priv/msgs/gl.po0000644000232200023220000014233012645157216016534 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\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" "Content-Transfer-Encoding: 8bit\n" "X-Language: Galician (galego)\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "É obrigatorio usar STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Non se proporcionou recurso" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Substituído por unha nova conexión" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Introduza o texto que ves" #: 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:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "O CAPTCHA é válido." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Servidor ~b" #: 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" #: 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 "Non autorizado" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Ejabberd Administrador Web" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administración" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Cru" #: 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: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:913 msgid "~s access rule configuration" msgstr "Configuración das Regra de Acceso ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Hosts Virtuais" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Usuarios" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Usuarios conectados" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Última actividade dos usuarios" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periodo: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Último mes" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Último ano" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Toda a actividade" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrar Táboa Ordinaria" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrar Táboa Integral" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Non atopado" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo non atopado" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Engadir novo" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Usuarios rexistrados" #: 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:1459 msgid "Offline Messages" msgstr "Mensaxes diferidas" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última actividade" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nunca" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Conectado" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Usuarios rexistrados:" #: 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:1556 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:" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Usuario " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos conectados:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Contrasinal:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminar usuario" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Sen datos" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodos" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos funcionando" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos detidos" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nodo " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de datos" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Gardar copia de seguridade" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Portos de escoita" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Actualizar" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Deter" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" #: ejabberd_web_admin.erl:1866 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 " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo de almacenamiento" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementos" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memoria" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Erro" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Copia de seguridade de " #: 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 "" "Ten en conta que estas opcións só farán copia de seguridade da base de datos " "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:1969 msgid "Store binary backup:" msgstr "Gardar copia de seguridade binaria:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Restaurar inmediatamente copia de seguridade binaria:" #: 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:1999 msgid "Store plain text backup:" msgstr "Gardar copia de seguridade en texto plano:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" 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" #: 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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar usuarios do directorio spool de jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Portos de escoita en " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Módulos en " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Estatísticas de ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tempo desde o inicio:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tempo consumido de CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaccións finalizadas:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaccións abortadas:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaccións reiniciadas:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaccións rexistradas:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Actualizar" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan de actualización" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Módulos Modificados" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script de actualización" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script de actualización a baixo nivel" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Comprobación de script" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Porto" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocolo" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Módulo" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opcións" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Iniciar" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandos" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Está seguro de quere borrar a mensaxe do dia?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Asunto" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Corpo da mensaxe" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Non se proporcionou corpo de mensaxe para o anuncio" #: mod_announce.erl:662 msgid "Announcements" msgstr "Anuncios" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Enviar anuncio a todos os usuarios" #: 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:668 msgid "Send announcement to all online users" msgstr "Enviar anuncio a todos los usuarios conectados" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Actualizar mensaxe do dia, pero non envialo" #: 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:680 msgid "Delete message of the day" msgstr "Borrar mensaxe do dia" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Configuración" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar módulos" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Detener módulos" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar a ficheiro de texto" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar ficheiro" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar directorio" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reiniciar o servizo" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Deter o servizo" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Borrar usuario" #: 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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Cambiar contrasinal de usuario" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Ver estatísticas de usuario" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Ver número de usuarios rexistrados" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Ver número de usuarios conectados" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Administración de usuarios" #: mod_configure.erl:525 msgid "All Users" msgstr "Todos os usuarios" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Conexións S2S saíntes" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Xestión de copia de seguridade" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuarios de ficheiros spool de jabberd-1.4" #: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuración de táboas da base de datos en " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selecciona tipo de almacenamento das táboas" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copia en disco soamente" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copia en RAM e disco" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copia en RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copia remota" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Deter módulos en " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecciona módulos a deter" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar módulos en " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introduce lista de {Módulo, [Opcións]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista de módulos a iniciar" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Copia de seguridade de arquivos en " #: 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:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Ruta ao ficheiro" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaura copia de seguridade desde o ficheiro en " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Exporta copia de seguridade a ficheiro de texto en " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introduce ruta ao ficheiro de texto" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importa usuario desde ficheiro en " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Introduce ruta ao ficheiro jabberd14 spool" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar usuarios desde o directorio en " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Introduce a ruta ao directorio de jabberd14 spools" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Ruta ao directorio" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Atraso temporal" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuración da Lista de Control de Acceso" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listas de Control de Acceso" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuración de accesos" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verificación da contrasinal" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Número de usuarios rexistrados" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Número de usuarios conectados" #: mod_configure.erl:1936 msgid "Last login" msgstr "Última conexión" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Tamaño da lista de contactos" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Direccións IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Recursos" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administración de " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Acción no usuario" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propiedades" #: 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_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: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:476 msgid "ejabberd IRC module" 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 "" "Necesitas un cliente con soporte de x:data para configurar as opcións de " "mod_irc" #: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Rexistro en mod_irc para" #: mod_irc.erl:659 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" #: mod_irc.erl:667 msgid "IRC Username" msgstr "Nome de usuario en IRC" #: 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." msgstr "" "Se quere especificar codificaciones de caracteres diferentes, contrasinal ou " "servidor IRC rechea esta lista con valores no formato '{\"servidor irc\", " "\"codificación\", \"porto\", \"contrasinal\"}'. Este servizo utiliza por " "defecto a codificación \"~s\", porto ~p, sen contrasinal." #: 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 "" "Exemplo: [{\"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 "Parámetros de conexiones" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Entrar en canle IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canle de IRC (non poñer o primeiro #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Servidor IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Únete á canle de IRC aquí." #: 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:1046 msgid "IRC settings" msgstr "IRC axustes" #: 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 "" "Introduce o nome de usuario e codificaciones de carácteres que queiras usar " "ao conectar nos servidores de IRC. Presione 'Siguiente' para obtener más " "campos para rellenar Presione 'completo' para guardar axustes." #: mod_irc.erl:1060 msgid "IRC username" msgstr "Nome de usuario en IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Contrasinal ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Porto ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codificación de servidor ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servidor ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Rexistro do alcume en " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Alcume" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Salas de charla" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "sae da sala" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Usuarios rexistrados" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: 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:410 msgid "joins the room" msgstr "entra en la sala" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "sae da sala" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "foi bloqueado" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "foi expulsado por mor dun sistema de peche" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "cámbiase o nome a" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " puxo o asunto: " #: mod_muc_log.erl:493 #, fuzzy msgid "Chatroom is created" msgstr "Salas de charla" #: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "Salas de charla" #: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "Salas de charla" #: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "Salas de charla" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Luns" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Martes" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Mércores" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Xoves" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Venres" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sábado" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Domingo" #: mod_muc_log.erl:513 msgid "January" msgstr "Xaneiro" #: mod_muc_log.erl:514 msgid "February" msgstr "Febreiro" #: mod_muc_log.erl:515 msgid "March" msgstr "Marzo" #: mod_muc_log.erl:516 msgid "April" msgstr "Abril" #: mod_muc_log.erl:517 msgid "May" msgstr "Maio" #: mod_muc_log.erl:518 msgid "June" msgstr "Xuño" #: mod_muc_log.erl:519 msgid "July" msgstr "Xullo" #: mod_muc_log.erl:520 msgid "August" msgstr "Agosto" #: mod_muc_log.erl:521 msgid "September" msgstr "Setembro" #: mod_muc_log.erl:522 msgid "October" msgstr "Outubro" #: mod_muc_log.erl:523 msgid "November" msgstr "Novembro" #: mod_muc_log.erl:524 msgid "December" msgstr "Decembro" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuración da Sala" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Ocupantes da sala" #: 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" msgstr "" "Só os moderadores e os participantes se lles permite cambiar o tema nesta " "sala" #: 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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "O alcume ~s non existe na sala" #: 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:2846 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 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:3359 msgid "Room title" msgstr "Título da sala" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descrición da sala" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Sala permanente" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Sala publicamente visible" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "A lista de participantes é pública" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Protexer a sala con contrasinal" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Sen límite" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Os Jabber ID reais poden velos" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "só moderadores" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "calquera" #: 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:3516 msgid "Make room moderated" msgstr "Facer sala moderada" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Os usuarios son participantes por defecto" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permitir aos usuarios cambiar o asunto" #: mod_muc_room.erl:3525 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" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Permitir aos usuarios consultar a outros usuarios" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Permitir aos usuarios enviar invitacións" #: 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:3586 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" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Protexer a sala con CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Gardar históricos" #: 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:4190 msgid "Number of occupants" msgstr "Número de ocupantes" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privado" #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Usuario " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s invítache á sala ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "a contrasinal é" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "Data" #: mod_offline.erl:812 msgid "From" msgstr "De" #: mod_offline.erl:813 msgid "To" msgstr "Para" #: mod_offline.erl:814 msgid "Packet" msgstr "Paquete" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Mensaxes sen conexión:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Borrar Todas as Mensaxes Sen conexión" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publicar-Subscribir" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo de Publicar-Subscribir de ejabberd" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Petición de subscriptor de PubSub" #: 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:1559 msgid "Node ID" msgstr "Nodo IDE" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Dirección do subscriptor" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads xunto coas notificacións de eventos" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Entregar notificacións de eventos" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptores cando o nodo bórrase" #: 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:3755 msgid "Persist items to storage" msgstr "Persistir elementos ao almacenar" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nome para o nodo" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persisten" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Permitir subscripciones" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Especifica o modelo de acceso" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Lista de grupos autorizados a subscribir" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Especificar o modelo do publicante" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" #: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "Especifica o modelo de acceso" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Máximo tamaño do payload en bytes" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Cando enviar o último elemento publicado" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Só enviar notificacións aos usuarios dispoñibles" #: 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: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: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 "" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "" #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "" #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" #: mod_register_web.erl:214 msgid "" "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." msgstr "" #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "Nome de usuario en IRC" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "" #: 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:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" #: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" #: 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 "" #: 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:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Verificación da contrasinal" #: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Lista de contactos" #: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Contrasinal:" #: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Contrasinal:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" #: mod_register_web.erl:480 msgid "Unregister" msgstr "" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscripción" #: mod_roster.erl:1437 msgid "Pending" msgstr "Pendente" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grupos" #: mod_roster.erl:1476 msgid "Validate" msgstr "Validar" #: mod_roster.erl:1485 msgid "Remove" msgstr "Borrar" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista de contactos de " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Engadir ID Jabber" #: mod_roster.erl:1622 msgid "Roster" msgstr "Lista de contactos" #: 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:1232 msgid "Name:" msgstr "Nome:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descrición:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membros:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Mostrar grupos:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupo " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Jabber en Erlang" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Aniversario" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Cidade" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "País" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Apelido" #: 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 "" "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" msgstr "Nome completo" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Segundo nome" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nome da organización" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unidade da organización" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Buscar usuarios en " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Procura de usuario en vCard" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Módulo vCard para ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Buscar resultados por " #: 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 "Outgoing s2s Servers:" #~ msgstr "Servidores S2S saíntes:" #~ msgid "Delete" #~ msgstr "Eliminar" #~ msgid "This room is not anonymous" #~ msgstr "Sala non anónima" #~ 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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Este participante é expulsado da sala, porque el enviou unha mensaxe de " #~ "erro a outro participante" #~ 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" #, fuzzy #~ msgid "CAPTCHA test failed" #~ msgstr "O CAPTCHA é válido." #~ msgid "Encodings" #~ msgstr "Codificaciones" #~ msgid "(Raw)" #~ msgstr "(Cru)" #~ msgid "Specified nickname is already registered" #~ msgstr "O alcume especificado xa está rexistrado, terás que buscar outro" #~ msgid "Size" #~ msgstr "Tamaño" ejabberd-16.01/priv/msgs/nl.po0000644000232200023220000014625512645157216016555 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: Andreas van Cranenburgh \n" "Language-Team: \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:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Gebruik van STARTTLS is vereist" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Geen bron opgegeven" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Vervangen door een nieuwe verbinding" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Voer de getoonde tekst in" #: 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: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:227 msgid "CAPTCHA web page" msgstr "CAPTCHA webpagina." #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "De geautomatiseerde Turing-test is geslaagd." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "Niet geautoriseerd" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Webbeheer" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Beheer" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Ruw" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Access rules" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Access rules op ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuele hosts" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Gebruikers" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Online gebruikers" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Laatste activiteit van gebruikers" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periode: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Afgelopen maand" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Afgelopen jaar" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Alle activiteit" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Deel van tabel laten zien" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Volledige tabel laten zien" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistieken" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Niet gevonden" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Node niet gevonden" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Toevoegen" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Geregistreerde gebruikers" #: 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:1459 msgid "Offline Messages" msgstr "Offline berichten" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Laatste activiteit" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nooit" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Online" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Geregistreerde gebruikers:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Uitgaande s2s-verbindingen:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Uitgaande s2s-verbindingen:" #: 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: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:1673 msgid "User ~s" msgstr "Gebruiker ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Verbonden bronnen:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Wachtwoord:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Gebruiker verwijderen" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Geen gegevens" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodes" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Draaiende nodes" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Gestopte nodes" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Node ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Backup" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Openstaande poorten" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Bijwerken" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Herstarten" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stoppen" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC-oproepfout" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Databasetabellen van ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Naam" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Opslagmethode" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementen" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Geheugen" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Fout" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Backup maken van ~p" #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Binaire backup maken:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Binaire backup direct herstellen:" #: 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:1999 msgid "Store plain text backup:" msgstr "Backup naar een tekstbestand schrijven:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Backup in een tekstbestand direct herstellen:" #: 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: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: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: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:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importeer gebruikersdata via spool-bestanden van jabberd14" #: 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:2115 msgid "Listened Ports at " msgstr "Openstaande poorten op " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Modules op ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistieken van ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Uptime:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Processortijd:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Bevestigde transacties:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Afgebroken transacties:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Herstarte transacties:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Gelogde transacties:" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Opwaarderen van ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan voor de opwaardering" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Gewijzigde modules" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script voor de opwaardering" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Lowlevel script voor de opwaardering" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Controle van script" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Poort" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocol" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Module" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opties" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Starten" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Commando's" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Wilt u het bericht van de dag verwijderen?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Onderwerp" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Bericht" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "De mededeling bevat geen bericht" #: mod_announce.erl:662 msgid "Announcements" msgstr "Mededelingen" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Mededeling verzenden naar alle gebruikers" #: 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:668 msgid "Send announcement to all online users" msgstr "Mededeling verzenden naar alle online gebruikers" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Bericht van de dag bijwerken (niet verzenden)" #: 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:680 msgid "Delete message of the day" msgstr "Bericht van de dag verwijderen" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Instellingen" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Modules starten" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Modules stoppen" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Binaire backup direct herstellen" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Backup naar een tekstbestand schrijven" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Bestand importeren" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Directory importeren" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Herstart Service" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Stop Service" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Verwijder Gebruiker" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Verwijder Gebruikers-sessie" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Verander Gebruikerswachtwoord" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Gebruikers-statistieken Opvragen" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Aantal Geregistreerde Gebruikers Opvragen" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Aantal Aanwezige Gebruikers Opvragen" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gebruikersbeheer" #: mod_configure.erl:525 msgid "All Users" msgstr "Alle gebruikers" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Uitgaande s2s-verbindingen" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Backup" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importeer gebruikers via spool-bestanden van jabberd14" #: mod_configure.erl:762 msgid "To ~s" msgstr "Naar ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Van ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Instellingen van databasetabellen op " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Opslagmethode voor tabellen kiezen" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Harde schijf" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM en harde schijf" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Op andere nodes in de cluster" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Modules stoppen op " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecteer de modules die u wilt stoppen" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Modules starten op " #: 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:1080 msgid "List of modules to start" msgstr "Lijst met op te starten modules" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Binaire backup maken op " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Voer pad naar backupbestand in" #: 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:1115 msgid "Restore Backup from File at " msgstr "Binaire backup direct herstellen op " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Backup naar een tekstbestand schrijven op " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Voer pad naar backupbestand in" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importeer gebruiker via bestand op " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Voer pad naar jabberd14-spool-bestand in" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Gebruikers importeren vanaf directory op " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Voer pad naar jabberd14-spool-directory in" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Pad naar directory" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Vertraging" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Instellingen van access control lists" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Access control lists" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Toegangsinstellingen" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Wachtwoord Bevestiging" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Aantal Geregistreerde Gebruikers" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Aantal Aanwezige Gebruikers" #: mod_configure.erl:1936 msgid "Last login" msgstr "Laatste Aanmelding" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Contactlijst Groote" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP-adres" #: mod_configure.erl:1967 msgid "Resources" msgstr "Bronnen" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Beheer van " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Actie op gebruiker" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Eigenschappen bewerken" #: mod_fail2ban.erl:95 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd's IRC-module" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registratie van " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "Voer de gebruikersnaam, coderingen, poorten en wachtwoorden in die U wilt " "gebruiken voor het verbinden met IRC-servers" #: mod_irc.erl:667 msgid "IRC Username" msgstr "Gebruikersnaam voor IRC:" #: 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." msgstr "" "Als u verschillende poorten, wachtwoorden en coderingen wilt opgeven voor " "elke IRC-server, vul dan deze lijst met het volgende formaat: '{\"IRC-server" "\", \"codering\", poort, \"wachtwoord\"}'. Standaard gebruikt deze service " "de codering \"~s\", poort ~p, leeg wachtwoord." #: 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 "" "Voorbeeld: [{\"irc.example.org\", \"koi8-r\", 6667, \"geheim\"}, {\"vendetta." "example.net\", \"iso8859-1\", 7000}, {irc,testserver.nl\", \"utf-8\"}]." #: mod_irc.erl:713 msgid "Connections parameters" msgstr "Verbindingsparameters" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Ga IRC kanaal binnen" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanaal (zonder eerste #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC-server" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Ga het IRC kanaal binnen" #: 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:1046 msgid "IRC settings" msgstr "IRC instellingen" #: 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 "" "Voer de gebruikersnaam en de coderingen in die u wilt gebruiken voor " "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:1060 msgid "IRC username" msgstr "Gebruikersnaam voor IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Wachtwoord ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Poort ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Karakterset voor server ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registratie van een bijnaam op " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Bijnaam" #: 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" #: 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:249 msgid "Total rooms" msgstr "Aantal groepsgesprekken" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Permanente groepsgesprekken" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Geregistreerde gebruikersnamen" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Lijst van groepsgesprekken" #: 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:410 msgid "joins the room" msgstr "betrad de chatruimte" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "verliet de chatruimte" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "is verbannen" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "is weggestuurd vanwege een affiliatieverandering" #: 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:445 msgid "has been kicked because of a system shutdown" msgstr "is weggestuurd omdat het systeem gestopt wordt" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "heet nu" #: 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:493 msgid "Chatroom is created" msgstr "Gespreksruimte gecreëerd" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Gespreksruimte vernietigd" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Gespreksruimte gestart" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Gespreksruimte gestopt" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Maandag" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Dinsdag" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Woensdag" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Donderdag" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Vrijdag" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Zaterdag" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Zondag" #: mod_muc_log.erl:513 msgid "January" msgstr "Januari" #: mod_muc_log.erl:514 msgid "February" msgstr "Februari" #: mod_muc_log.erl:515 msgid "March" msgstr "Maart" #: mod_muc_log.erl:516 msgid "April" msgstr "April" #: mod_muc_log.erl:517 msgid "May" msgstr "Mei" #: mod_muc_log.erl:518 msgid "June" msgstr "Juni" #: mod_muc_log.erl:519 msgid "July" msgstr "Juli" #: mod_muc_log.erl:520 msgid "August" msgstr "Augustus" #: mod_muc_log.erl:521 msgid "September" msgstr "September" #: mod_muc_log.erl:522 msgid "October" msgstr "Oktober" #: mod_muc_log.erl:523 msgid "November" msgstr "November" #: mod_muc_log.erl:524 msgid "December" msgstr "December" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Instellingen van de chatruimte" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Aantal aanwezigen" #: 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" msgstr "" "Alleen moderators en deelnemers mogen het onderwerp van deze chatruimte " "veranderen" #: 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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "De bijnaam ~s bestaat niet in deze chatruimte" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Ongeldige affiliatie: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ongeldige rol: ~s" #: 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:3359 msgid "Room title" msgstr "Naam van de chatruimte" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Beschrijving" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Chatruimte blijvend maken" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Chatruimte doorzoekbaar maken" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Deelnemerslijst publiek maken" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Chatruimte beveiligen met een wachtwoord" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maximum aantal aanwezigen" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Geen limiet" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Jabber ID's kunnen achterhaald worden door" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderators" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "iedereen" #: 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:3516 msgid "Make room moderated" msgstr "Chatruimte gemodereerd maken" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Gebruikers standaard instellen als deelnemers" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Sta gebruikers toe het onderwerp te veranderen" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Gebruikers mogen privéberichten verzenden" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Gebruikers mogen privéberichten verzenden aan" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "niemand" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Gebruikers mogen naar andere gebruikers verzoeken verzenden" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Gebruikers mogen uitnodigingen verzenden" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Sta bezoekers toe hun naam te veranderen" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Gebruikers mogen stemaanvragen verzenden" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimale interval tussen stemaanvragen (in seconden)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Chatruimte beveiligen met een geautomatiseerde Turing test" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Zet bericht-archivering aan" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Geen CAPTCHA test voor Jabber IDs" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Logs aanzetten" #: 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:4190 msgid "Number of occupants" msgstr "Aantal aanwezigen" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privé, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Stemaanvraag" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Keur stemaanvraag goed of af." #: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID Gebruiker" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Stemaanvraag honoreren voor deze persoon?" #: 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:4507 msgid "the password is" msgstr "het wachtwoord is" #: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast service" #: 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:811 msgid "Time" msgstr "Tijd" #: mod_offline.erl:812 msgid "From" msgstr "Van" #: mod_offline.erl:813 msgid "To" msgstr "Aan" #: mod_offline.erl:814 msgid "Packet" msgstr "Pakket" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline berichten:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Verwijder alle offline berichten" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe module" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub abonnee verzoek" #: 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:1559 msgid "Node ID" msgstr "Node ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Abonnee Adres" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Berichten bezorgen samen met gebeurtenisnotificaties" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Gebeurtenisbevestigingen Sturen" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Abonnees informeren wanneer de node verwijderd word" #: 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:3755 msgid "Persist items to storage" msgstr "Items in het geheugen bewaren" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Bijnaam voor deze knoop" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maximum aantal in het geheugen te bewaren items" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Abonnementsaanvraag toestaan" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Geef toegangsmodel" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Contactlijst-groepen die mogen abonneren" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Publicatietype opgeven" #: 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:3771 msgid "Specify the event message type" msgstr "Geef type van eventbericht" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maximumgrootte van bericht in bytes" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Wanneer het laatst gepubliceerde item verzonden moet worden" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Notificaties alleen verzenden naar online gebruikers" #: 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: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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Er was een fout bij het creeern van de account:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Uw Jabber-account is succesvol verwijderd." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Er was een fout bij het verwijderen van de account." #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Het wachtwoord van Uw Jabber-account is succesvol veranderd." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Er was een fout bij het veranderen van het wachtwoord:" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Jabber-account registratie" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Registreer een Jabber-account" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Gebruikersnaam:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Dit is niet hoofdlettergevoelig: macbeth is hetzelfde als MacBeth en Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Niet-toegestane karakters:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Geef Uw wachtwoord aan niemand, zelfs niet aan de beheerders van deze Jabber-" "server." #: 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: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 "" "Sommige Jabber-clienten kunnen het wachtwoord opslaan op Uw computer. " "Gebruik deze mogelijkheid alleen als U vertrouwd dat Uw computer afdoende " "beveiligd is." #: 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 "" "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." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Wachtwoord Bevestiging:" #: mod_register_web.erl:269 msgid "Register" msgstr "Registreer" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Oud Wachtwoord:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nieuw Wachtwoord:" #: 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:480 msgid "Unregister" msgstr "Opheffen" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Inschrijving" #: mod_roster.erl:1437 msgid "Pending" msgstr "Bezig" #: mod_roster.erl:1438 msgid "Groups" msgstr "Groepen" #: mod_roster.erl:1476 msgid "Validate" msgstr "Bevestigen" #: mod_roster.erl:1485 msgid "Remove" msgstr "Verwijderen" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Roster van " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Jabber ID toevoegen" #: mod_roster.erl:1622 msgid "Roster" msgstr "Roster" #: 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:1232 msgid "Name:" msgstr "Naam:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Beschrijving:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Groepsleden:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Weergegeven groepen:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Groep " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Geboortedatum" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Plaats" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Land" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-mail" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Achternaam" #: 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 "" "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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Volledige naam" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Tussennaam" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organisatie" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Afdeling" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Gebruikers zoeken in " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Gebruikers zoeken" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd's vCard-module" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Zoekresultaten voor " #: 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 "Outgoing s2s Servers:" #~ msgstr "Uitgaande s2s-verbindingen:" #~ msgid "Delete" #~ msgstr "Verwijderen" #~ msgid "This room is not anonymous" #~ msgstr "Deze chatruimte is niet anoniem" #~ 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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Deze deelnemer wordt weggestuurd vanwege het sturen van een " #~ "foutmeldingsbericht aan een andere deelnemer" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "De geautomatiseerde Turing-test is geslaagd." ejabberd-16.01/priv/msgs/wa.po0000644000232200023220000014243512645157216016547 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "Last-Translator: Pablo Saratxaga\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Walon (Walloon)\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "L' eployaedje di STARTTL est oblidjî" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nole rissoûce di dnêye" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Replaecî pa on novea raloyaedje" #: 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: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: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:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "MÃ¥y" #: 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" #: 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 "Manaedjeu waibe ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Manaedjaedje" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Dinêyes brutes" #: 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: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:913 msgid "~s access rule configuration" msgstr "Apontiaedje des rîles d' accès a ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Forveyous sierveus" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Uzeus" #: 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:971 msgid "Users Last Activity" msgstr "Dierinne activité des uzeus" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Termene:" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Dierin moes" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Dierinne anêye" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Dispoy todi" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrer crexhince" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrer totÃ¥" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Sitatistikes" #: ejabberd_web_admin.erl:1014 #, fuzzy msgid "Not Found" msgstr "Nuk nén trové" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nuk nén trové" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Radjouter" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Sierveu" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Uzeus edjistrés" #: 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:1459 msgid "Offline Messages" msgstr "Messaedjes ki ratindèt" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Dierinne activité" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "MÃ¥y" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Raloyî" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Uzeus edjistrés:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Raloyaedjes s2s e rexhowe:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Raloyaedjes s2s e rexhowe:" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Uzeu " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Raloyî avou les rsoûces:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Sicret:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Disfacer l' uzeu" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Nole dinêye disponibe" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nuks" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nuks en alaedje" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nuks essoctés" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nuk " #: 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:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Copeye di sÃ¥vrité" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Pôrts drovous" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Mete a djoû" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Renonder" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Arester" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" #: ejabberd_web_admin.erl:1866 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 " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "No" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Sôre di wÃ¥rdaedje" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memwere" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Copeye di sÃ¥vrité po " #: 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 " "separately." msgstr "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Copeye di sÃ¥vrité binaire:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Rapexhî do côp foû d' ene copeye di sÃ¥vrité binaire:" #: 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:1999 msgid "Store plain text backup:" msgstr "Copeye di sÃ¥vrité tecse:" #: 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:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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:2087 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "Sititchî des uzeus Jabberd 1.4" #: 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 " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Sitatistikes di ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tins dispoy l' enondaedje:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tins CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaccions evoyeyes:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaccions arestêyes:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaccions renondêyes:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaccions wÃ¥rdêyes e djournÃ¥:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Metaedje a djoû " #: 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û" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Sicripe di metaedje a djoû" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Sicripe di metaedje a djoû d' bas livea" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Acertinaedje do scripe" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Pôrt" #: ejabberd_web_admin.erl:2439 #, fuzzy msgid "Protocol" msgstr "Pôrt" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Module" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Tchuzes" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Enonder" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandes" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Voloz vs vormint disfacer l' messaedje do djoû?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Sudjet" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Coir do messaedje" #: 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:662 msgid "Announcements" msgstr "Anonces" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Evoyî l' anonce a tos les uzeus" #: 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:668 msgid "Send announcement to all online users" msgstr "Evoyî l' anonce a tos les uzeus raloyîs" #: 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: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: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: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: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:680 msgid "Delete message of the day" msgstr "Disfacer l' messaedje do djoû" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Apontiaedjes" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Enonder des modules" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Arester des modules" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Rapexhî" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Schaper en on fitchî tecse" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Sititchî d' on fitchî" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Sititchî d' on ridant" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Renonder siervice" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Arester siervice" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Disfacer èn uzeu" #: 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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Candjî l' sicret d' l' uzeu" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Riçure les statistikes di l' uzeu" #: 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:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Riçure li nombe d' uzeus raloyîs" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Manaedjaedje des uzeus" #: mod_configure.erl:525 msgid "All Users" msgstr "Tos les uzeus" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Raloyaedjes s2s e rexhowe" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Manaedjaedje des copeyes di sÃ¥vrité" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Sititchî des uzeus Jabberd 1.4" #: mod_configure.erl:762 msgid "To ~s" msgstr "Viè ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Dispoy ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Apontiaedje des tÃ¥ves del bÃ¥ze di dnêyes so " #: 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:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copeye seulmint sol deure plake" #: 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:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copeye e memwere (RAM)" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copeye Ã¥ lon" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Arester les modules so " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Tchoezixhoz les modules a-z arester" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Renonder les modules so " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Dinez ene djivêye del cogne {Module, [Tchuzes]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Djivêye di modules a-z enonder" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Fé ene copeye di sÃ¥vrité dins on fitchî so " #: 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: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:1115 msgid "Restore Backup from File at " msgstr "Rapexhî dispoy li fitchî copeye di sÃ¥vrité so " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Copeye di sÃ¥vritè viè on fitchî tecse so " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Dinez l' tchimin viè l' fitchî tecse" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Sititchî uzeu d' on fitchî so " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Dinez l' tchimin viè l' fitchî di spool jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Sitichî des uzeus d' on ridant so " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Dinez l' tchimin viè l' ridant di spool jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Tchimin viè l' ridant" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "TÃ¥rdjaedje" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Apontiaedje des droets (ACL)" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Droets (ACL)" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Apontiaedje des accès" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Acertinaedje do scret" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Nombe d' uzeus edjîstrés" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Nombe d' uzeus raloyîs" #: mod_configure.erl:1936 msgid "Last login" msgstr "Dierin elodjaedje" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Grandeu del djivêye des soçons" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Adresses IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Rissoûces" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Manaedjaedje di " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Accion so l' uzeu" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Candjî les prôpietés" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "Module IRC po ejabberd" #: 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:653 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" #: 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»." #: 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\"}]." #: mod_irc.erl:713 msgid "Connections parameters" msgstr "" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" #: mod_irc.erl:903 #, fuzzy msgid "IRC server" msgstr "No d' uzeu IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "" #: 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" #: mod_irc.erl:1060 #, fuzzy msgid "IRC username" msgstr "No d' uzeu IRC" #: mod_irc.erl:1126 #, fuzzy msgid "Password ~b" msgstr "Sicret" #: mod_irc.erl:1137 #, fuzzy msgid "Port ~b" msgstr "Pôrt" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "" #: 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: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:941 msgid "Nickname Registration at " msgstr "Edjîstraedje di metou no amon " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Metou no" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "SÃ¥les di berdelaedje" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "cwite li sÃ¥le" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Uzeus edjistrés" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: 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:410 msgid "joins the room" msgstr "arive sol sÃ¥le" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "cwite li sÃ¥le" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "a stî bani" #: 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: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: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:450 msgid "is now known as" msgstr "est asteure kinoxhou come" #: 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:493 #, fuzzy msgid "Chatroom is created" msgstr "SÃ¥les di berdelaedje" #: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "SÃ¥les di berdelaedje" #: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "SÃ¥les di berdelaedje" #: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "SÃ¥les di berdelaedje" #: mod_muc_log.erl:503 msgid "Monday" msgstr "londi" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "mÃ¥rdi" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "mierkidi" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "djudi" #: mod_muc_log.erl:507 msgid "Friday" msgstr "vénrdi" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "semdi" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "dimegne" #: mod_muc_log.erl:513 msgid "January" msgstr "djanvî" #: mod_muc_log.erl:514 msgid "February" msgstr "fevrî" #: mod_muc_log.erl:515 msgid "March" msgstr "mÃ¥ss" #: mod_muc_log.erl:516 msgid "April" msgstr "avri" #: mod_muc_log.erl:517 msgid "May" msgstr "may" #: mod_muc_log.erl:518 msgid "June" msgstr "djun" #: mod_muc_log.erl:519 msgid "July" msgstr "djulete" #: mod_muc_log.erl:520 msgid "August" msgstr "awousse" #: mod_muc_log.erl:521 msgid "September" msgstr "setimbe" #: mod_muc_log.erl:522 msgid "October" msgstr "octôbe" #: mod_muc_log.erl:523 msgid "November" msgstr "nôvimbe" #: mod_muc_log.erl:524 msgid "December" msgstr "decimbe" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Apontiaedje del sÃ¥le" #: mod_muc_log.erl:932 #, fuzzy msgid "Room Occupants" msgstr "Nombe di prezints" #: 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 " "room" msgstr "" "Seulmint les moderateus et les pÃ¥rticipants polèt candjî l' sudjet dins " "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" #: 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: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:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiyaedje nén valide: ~s" #: mod_muc_room.erl:2846 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 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:3359 msgid "Room title" msgstr "Tite del sÃ¥le" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "Discrijhaedje:" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Rinde li sÃ¥le permaninte" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Rinde li sÃ¥le di berdelaedje cwerÃ¥ve publicmint" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Rinde publike li djivêye des pÃ¥rticipants" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Rinde li sÃ¥le di berdelaedje protedjeye pa scret" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Nombe macsimom di prezints" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Pont d' limite" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Mostrer les vraiys Jabber IDs a" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "les moderateus seulmint" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "tot l' minme kî" #: 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:3516 msgid "Make room moderated" msgstr "Rinde li sÃ¥le di berdelaedje moderêye" #: 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:3522 #, fuzzy msgid "Allow users to change the subject" msgstr "Les uzeus polèt candjî l' tite" #: 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: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 "" #: 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:3579 msgid "Allow users to send invites" msgstr "Les uzeus polèt evoyî priyaedjes" #: 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:3586 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" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: 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:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Mete en alaedje li djournÃ¥" #: 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:4190 msgid "Number of occupants" msgstr "Nombe di prezints" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privé, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Uzeu " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: 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:4507 msgid "the password is" msgstr "li scret est" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "Date" #: mod_offline.erl:812 msgid "From" msgstr "Di" #: mod_offline.erl:813 msgid "To" msgstr "Po" #: mod_offline.erl:814 msgid "Packet" msgstr "Paket" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Messaedjes ki ratindèt:" #: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "Messaedjes ki ratindèt" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Module SOCKS5 Bytestreams po ejabberd" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Eplaidaedje-abounmint" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Module d' eplaidaedje-abounmint po ejabberd" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Dimande d' eplaidaedje-abounmint d' èn abouné" #: 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:1559 msgid "Node ID" msgstr "ID d' nuk" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adresse di l' abouné" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Evoyî l' contnou avou les notifiaedjes d' evenmints" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Evoyî des notifiaedjes d' evenmints" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notifyî Ã¥zès abounés cwand l' nuk est disfacé" #: 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:3755 msgid "Persist items to storage" msgstr "Cayets permanints a wÃ¥rder" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "On no uzeu-ahessÃ¥ve pol nuk" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Nombe macsimoms di cayets permanints" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Si on permete les abounmints" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Sipecifyî l' modele d' accès" #: 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:3767 msgid "Specify the publisher model" msgstr "Dinez l' modele d' eplaideu" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" #: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "Sipecifyî l' modele d' accès" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Contnou macsimom en octets" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Cwand evoyî l' dierin cayet eplaidî" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Seulmint evoyî des notifiaedje Ã¥zès uzeus disponibes" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" #: 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: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 "" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "" #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "" #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" #: mod_register_web.erl:214 msgid "" "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." msgstr "" #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "No d' uzeu IRC" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "" #: 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:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" #: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" #: 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 "" #: 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:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Acertinaedje do scret" #: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Djivêye des soçons" #: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Sicret:" #: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Sicret:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" #: mod_register_web.erl:480 msgid "Unregister" msgstr "" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Abounmimnt" #: mod_roster.erl:1437 msgid "Pending" msgstr "Ratindant" #: mod_roster.erl:1438 msgid "Groups" msgstr "Groupes" #: mod_roster.erl:1476 msgid "Validate" msgstr "Valider" #: mod_roster.erl:1485 msgid "Remove" msgstr "Oister" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Djivêye des soçons da " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Radjouter èn ID Jabber" #: mod_roster.erl:1622 msgid "Roster" msgstr "Djivêye des soçons" #: 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:1232 msgid "Name:" msgstr "Pitit no:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Discrijhaedje:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Mimbes:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Groupes hÃ¥ynés:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Groupe " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Sierveu Jabber Erlang" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Date d' askepiaedje" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Veye" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Payis" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Emile" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "No d' famile" #: 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 "" "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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "No etir" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "No do mitan" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "No d' l' organizÃ¥cion" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unité d' l' organizÃ¥cion" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Cweri des uzeus dins " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Calpin des uzeus" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Module vCard ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Rizultats do cweraedje po " #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "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 "" #~ "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 "Encodings" #~ msgstr "Ecôdaedjes" #~ msgid "(Raw)" #~ msgstr "(Dinêyes brutes)" #~ msgid "Specified nickname is already registered" #~ msgstr "Li no metou dné est ddja edjîstré" #~ msgid "Size" #~ msgstr "Grandeu" ejabberd-16.01/priv/msgs/ejabberd.pot0000644000232200023220000011160012645157216020050 0ustar debalancedebalancemsgid "" msgstr "" "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:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" #: 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 "" #: ejabberd_oauth.erl:256 msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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 "" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "" #: 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:1459 msgid "Offline Messages" msgstr "" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "" #: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 #: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "" #: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "" #: ejabberd_web_admin.erl:1559 msgid "Incoming s2s Connections:" msgstr "" #: 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: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:1673 msgid "User ~s" msgstr "" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "" #: 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:1969 msgid "Store binary backup:" msgstr "" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "" #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "" #: mod_adhoc.erl:279 msgid "Pong" msgstr "" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "" #: mod_announce.erl:662 msgid "Announcements" msgstr "" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "" #: 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:672 msgid "Set message of the day and send to online users" msgstr "" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "" #: mod_announce.erl:680 msgid "Delete message of the day" msgstr "" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "" #: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 #: mod_configure.erl:1473 msgid "Get User Password" msgstr "" #: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "" #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "" #: mod_configure.erl:525 msgid "All Users" msgstr "" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "" #: mod_configure.erl:615 msgid "Backup Management" msgstr "" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "" #: mod_configure.erl:762 msgid "To ~s" msgstr "" #: mod_configure.erl:782 msgid "From ~s" msgstr "" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "" #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "" #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "" #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "" #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "" #: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "" #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "" #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "" #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "" #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "" #: mod_configure.erl:1936 msgid "Last login" msgstr "" #: mod_configure.erl:1963 msgid "Roster size" msgstr "" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "" #: mod_configure.erl:1967 msgid "Resources" msgstr "" #: mod_configure.erl:2095 msgid "Administration of " msgstr "" #: mod_configure.erl:2100 msgid "Action on user" msgstr "" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "" #: 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_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:220 mod_muc.erl:467 msgid "Access denied by service policy" msgstr "" #: mod_irc.erl:439 msgid "IRC Transport" msgstr "" #: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "" #: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" #: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "" #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" #: mod_irc.erl:667 msgid "IRC Username" msgstr "" #: 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." msgstr "" #: 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:713 msgid "Connections parameters" msgstr "" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" #: mod_irc.erl:903 msgid "IRC server" msgstr "" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "" #: 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:1060 msgid "IRC username" msgstr "" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "" #: 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: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:941 msgid "Nickname Registration at " msgstr "" #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "" #: 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 "" #: 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:249 msgid "Total rooms" msgstr "" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr "" #: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "" #: mod_muc_log.erl:503 msgid "Monday" msgstr "" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "" #: mod_muc_log.erl:507 msgid "Friday" msgstr "" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "" #: mod_muc_log.erl:513 msgid "January" msgstr "" #: mod_muc_log.erl:514 msgid "February" msgstr "" #: mod_muc_log.erl:515 msgid "March" msgstr "" #: mod_muc_log.erl:516 msgid "April" msgstr "" #: mod_muc_log.erl:517 msgid "May" msgstr "" #: mod_muc_log.erl:518 msgid "June" msgstr "" #: mod_muc_log.erl:519 msgid "July" msgstr "" #: mod_muc_log.erl:520 msgid "August" msgstr "" #: mod_muc_log.erl:521 msgid "September" msgstr "" #: mod_muc_log.erl:522 msgid "October" msgstr "" #: mod_muc_log.erl:523 msgid "November" msgstr "" #: mod_muc_log.erl:524 msgid "December" msgstr "" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "" #: 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:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "" #: 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:2772 msgid "Nickname ~s does not exist in the room" msgstr "" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "" #: 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:3359 msgid "Room title" msgstr "" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "" #: 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:3516 msgid "Make room moderated" msgstr "" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "" #: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" #: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "" #: mod_muc_room.erl:4260 msgid "private, " msgstr "" #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 msgid "User JID" msgstr "" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "" #: mod_offline.erl:812 msgid "From" msgstr "" #: mod_offline.erl:813 msgid "To" msgstr "" #: mod_offline.erl:814 msgid "Packet" msgstr "" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" #: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" #: 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: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 "" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "" #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "" #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" #: mod_register_web.erl:214 msgid "" "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." msgstr "" #: 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 "" #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "" #: 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:249 msgid "You can later change your password using a Jabber client." msgstr "" #: 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 "" #: 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:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "" #: mod_register_web.erl:269 msgid "Register" msgstr "" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "" #: mod_register_web.erl:370 msgid "New Password:" msgstr "" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" #: mod_register_web.erl:480 msgid "Unregister" msgstr "" #: mod_roster.erl:1436 msgid "Subscription" msgstr "" #: mod_roster.erl:1437 msgid "Pending" msgstr "" #: mod_roster.erl:1438 msgid "Groups" msgstr "" #: mod_roster.erl:1476 msgid "Validate" msgstr "" #: mod_roster.erl:1485 msgid "Remove" msgstr "" #: mod_roster.erl:1490 msgid "Roster of " msgstr "" #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "" #: mod_roster.erl:1622 msgid "Roster" msgstr "" #: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 #: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "" #: mod_shared_roster.erl:1232 msgid "Name:" msgstr "" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "" #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "" #: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "" #: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "" ejabberd-16.01/priv/msgs/fr.po0000644000232200023220000015051612645157216016546 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: Nicolas Vérité \n" "Language-Team: \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: French (française)\n" "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:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "L'utilisation de STARTTLS est impérative" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Aucune ressource fournie" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Remplacé par une nouvelle connexion" #: 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: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: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: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: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:227 msgid "CAPTCHA web page" msgstr "Page web de CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Le 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 msgid "User" msgstr "Utilisateur" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Serveur :" #: 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" #: 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 "Non autorisé" #: 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:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administration" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Brut" #: 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: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:913 msgid "~s access rule configuration" msgstr "Configuration des règles d'accès ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Serveurs virtuels" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Utilisateurs" #: 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:971 msgid "Users Last Activity" msgstr "Dernière activité des utilisateurs" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Période :" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Dernier mois" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Dernière année" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Toute activité" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Montrer la table ordinaire" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Montrer la table intégralement" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiques" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "NÅ“ud non trouvé" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Noeud non trouvé" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Ajouter" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Serveur" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Utilisateurs enregistrés" #: 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:1459 msgid "Offline Messages" msgstr "Messages en attente" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Dernière Activité" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Jamais" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "En ligne" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Utilisateurs enregistrés:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Connexions s2s sortantes:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Connexions s2s sortantes:" #: 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: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:1673 msgid "User ~s" msgstr "Utilisateur ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Ressources connectées:" #: 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:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Supprimer l'utilisateur" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Aucune information disponible" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Noeuds" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Noeuds actifs" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Noeuds arrêtés" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Noeud ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de données" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sauvegarde" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Ports ouverts" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Mettre à jour" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Redémarrer" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Arrêter" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Erreur d'appel RPC" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Tables de base de données sur ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nom" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Type de stockage" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Éléments" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Mémoire" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Erreur" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Sauvegarde de ~p" #: 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 "" "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:1969 msgid "Store binary backup:" msgstr "Sauvegarde binaire:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Restauration immédiate d'une sauvegarde binaire:" #: 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:1999 msgid "Store plain text backup:" msgstr "Sauvegarde texte:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restauration immédiate d'une sauvegarde texte:" #: 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: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: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: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:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importer des utilisateurs depuis un fichier spool Jabberd 1.4:" #: 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:2115 msgid "Listened Ports at " msgstr "Ports ouverts sur " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Modules sur ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistiques de ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Temps depuis le démarrage :" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Temps CPU :" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transactions commitées :" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transactions annulées :" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transactions redémarrées :" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transactions journalisées :" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Mise à jour de ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan de mise à jour" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Modules mis à jour" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script de mise à jour" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script de mise à jour de bas-niveau" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Validation du script" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocole" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Module" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Options" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Démarrer" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Commandes" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Confirmer la suppression du message du jour ?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Sujet" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Corps du message" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Pas de corps de message pour l'annonce" #: mod_announce.erl:662 msgid "Announcements" msgstr "Annonces" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Envoyer l'annonce à tous les utilisateurs" #: 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:668 msgid "Send announcement to all online users" msgstr "Envoyer l'annonce à tous les utilisateurs en ligne" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Mise à jour du message du jour (pas d'envoi)" #: 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:680 msgid "Delete message of the day" msgstr "Supprimer le message du jour" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Configuration" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Modules de démarrage" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Modules d'arrêt" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restauration" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Sauvegarder dans un fichier texte" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importer un fichier" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importer une répertoire" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Redémarrer le service" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Arrêter le service" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Supprimer l'utilisateur" #: 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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Changer le mot de passe de l'utilisateur" #: 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: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:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Récupérer le nombre d'utilisateurs enregistrés" #: 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:320 mod_configure.erl:523 msgid "User Management" msgstr "Gestion des utilisateurs" #: mod_configure.erl:525 msgid "All Users" msgstr "Tous les utilisateurs" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Connexions s2s sortantes" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestion des sauvegardes" #: 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:762 msgid "To ~s" msgstr "A ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuration des tables de base de données sur " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Choisissez un type de stockage pour les tables" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copie sur disque uniquement" #: 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:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copie en mémoire vive (RAM)" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copie distante" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Arrêter les modules sur " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Sélectionnez les modules à arrêter" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Démarrer les modules sur " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Entrez une liste de {Module, [Options]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Liste des modules à démarrer" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Sauvegarde sur fichier sur " #: 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: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:1115 msgid "Restore Backup from File at " msgstr "Restaurer la sauvegarde depuis le fichier sur " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Enregistrer la sauvegarde dans un fichier texte sur " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Entrez le chemin vers le fichier texte" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importer un utilisateur depuis le fichier sur " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Entrez le chemin vers le fichier spool jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importer des utilisateurs depuis le répertoire sur " #: 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:1184 msgid "Path to Dir" msgstr "Chemin vers le répertoire" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Délais" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuration des droits (ACL)" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Droits (ACL)" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuration d'accès" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Vérification du mot de passe" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Nombre d'utilisateurs enregistrés" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Nombre d'utilisateurs en ligne" #: mod_configure.erl:1936 msgid "Last login" msgstr "Dernière connexion" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Taille de la liste de contacts" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Adresses IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Ressources" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administration de " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Action sur l'utilisateur" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Modifier les propriétés" #: mod_fail2ban.erl:95 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_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: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:476 msgid "ejabberd IRC module" msgstr "Module IRC ejabberd" #: 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:653 msgid "Registration in mod_irc for " msgstr "Enregistrement du mod_irc pour " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" 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:667 msgid "IRC Username" msgstr "Nom d'utilisateur IRC" #: 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." msgstr "" "Si vous voulez préciser différents ports, mots de passe, et encodages pour " "les serveurs IRC, remplissez cette liste avec des valeurs dans le format " "'{\"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:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." msgstr "" "Exemple: [{\"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 "Paramètres de connexion" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Rejoindre un canal IRC" #: 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:903 msgid "IRC server" msgstr "Serveur IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Rejoindre un canal IRC ici" #: 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:1046 msgid "IRC settings" msgstr "Configuration IRC" #: 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 "" "Entrez le nom d'utilisateur et les encodages que vous souhaitez utiliser " "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:1060 msgid "IRC username" msgstr "Nom d'utilisateur IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Mot de passe ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codage pour le serveur ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Serveur ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Enregistrement d'un pseudo sur " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Pseudo" #: 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" #: 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:249 msgid "Total rooms" msgstr "Nombre de salons" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Salons persistent" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Pseudos enregistrés" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Liste des salons" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Configuration du salon modifiée" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "rejoint le salon" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "quitte le salon" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "a été banni" #: 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: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: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:450 msgid "is now known as" msgstr "est maintenant connu comme" #: 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:493 msgid "Chatroom is created" msgstr "Le salon de discussion est créé" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Le salon de discussion est détruit" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Le salon de discussion a démarré" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Le salon de discussion est stoppé" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Lundi" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Mardi" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Mercredi" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Jeudi" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Vendredi" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Samedi" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Dimanche" #: mod_muc_log.erl:513 msgid "January" msgstr "Janvier" #: mod_muc_log.erl:514 msgid "February" msgstr "Février" #: mod_muc_log.erl:515 msgid "March" msgstr "Mars" #: mod_muc_log.erl:516 msgid "April" msgstr "Avril" #: mod_muc_log.erl:517 msgid "May" msgstr "Mai" #: mod_muc_log.erl:518 msgid "June" msgstr "Juin" #: mod_muc_log.erl:519 msgid "July" msgstr "Juillet" #: mod_muc_log.erl:520 msgid "August" msgstr "Août" #: mod_muc_log.erl:521 msgid "September" msgstr "Septembre" #: mod_muc_log.erl:522 msgid "October" msgstr "Octobre" #: mod_muc_log.erl:523 msgid "November" msgstr "Novembre" #: mod_muc_log.erl:524 msgid "December" msgstr "Décembre" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuration du salon" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Occupants du salon" #: 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" msgstr "" "Seuls les modérateurs et les participants peuvent changer le sujet dans ce " "salon" #: 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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Le pseudo ~s n'existe pas dans ce salon" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Affiliation invalide : ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Role invalide : ~s" #: 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:3359 msgid "Room title" msgstr "Titre du salon" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Description :" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Rendre le salon persistant" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Rendre le salon public" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Rendre la liste des participants publique" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Protéger le salon par mot de passe" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Nombre maximum d'occupants" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Pas de limite" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Rendre le Jabber ID réel visible pour" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "modérateurs seulement" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "tout le monde" #: 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:3516 msgid "Make room moderated" msgstr "Rendre le salon modéré" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Les utilisateurs sont par défaut participant" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Autoriser les utilisateurs à changer le sujet" #: 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:3533 msgid "Allow visitors to send private messages to" msgstr "Autoriser les visiteurs à envoyer des messages privés" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "personne" #: 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:3579 msgid "Allow users to send invites" msgstr "Permettre aux utilisateurs d'envoyer des invitations" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Autoriser les visiteurs à changer de pseudo" #: 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:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervalle minimum entre les demandes de 'voice' (en secondes)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Protéger le salon par un CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Activer l'archivage de messages" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Exempter des Jabberd IDs du test CAPTCHA" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Activer l'archivage" #: 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:4190 msgid "Number of occupants" msgstr "Nombre d'occupants" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privé" #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Demande de 'voice'" #: 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:4349 msgid "User JID" msgstr "JID de l'utilisateur " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Accorder 'voice' à cet utilisateur" #: 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:4507 msgid "the password is" msgstr "le mot de passe est" #: mod_multicast.erl:291 msgid "Multicast" msgstr "Multidiffusion" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "Service de Multidiffusion d'ejabberd" #: 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:811 msgid "Time" msgstr "Heure" #: mod_offline.erl:812 msgid "From" msgstr "De" #: mod_offline.erl:813 msgid "To" msgstr "A" #: mod_offline.erl:814 msgid "Packet" msgstr "Paquet" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Messages en attente :" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Effacer tous les messages hors ligne" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publication-Abonnement" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Module Publish-Subscribe d'ejabberd" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Demande d'abonnement PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Accepter cet abonnement ?" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Identifiant du nÅ“ud" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adresse de l'abonné" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Inclure le contenu du message avec la notification" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Envoyer les notifications d'événement" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Avertir les abonnés lorsque le nÅ“ud est supprimé" #: 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:3755 msgid "Persist items to storage" msgstr "Stockage persistant des éléments" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nom convivial pour le noeud" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Nombre maximum d'éléments à stocker" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Autoriser l'abonnement ?" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Définir le modèle d'accès" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Groupes de liste de contact autorisés à s'abonner" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Définir le modèle de publication" #: 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:3771 msgid "Specify the event message type" msgstr "Définir le type de message d'événement" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Taille maximum pour le contenu du message en octet" #: 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:3777 msgid "Only deliver notifications to available users" msgstr "Envoyer les notifications uniquement aux utilisateurs disponibles" #: 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: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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Il y a eu une erreur en créant le compte :" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Votre compte Jabber a été effacé avec succès." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Il y a eu une erreur en effaçant le compte :" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Le mot de passe de votre compte Jabber a été changé avec succès." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Il y a eu une erreur en changeant le mot de passe :" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Enregistrement du Compte Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Enregistrer un compte Jabber" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nom d'utilisateur :" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "C'est insensible à la casse : macbeth est identique à MacBeth et Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Caractères non-autorisés :" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Serveur :" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Ne révélez votre mot de passe à personne, pas même l'administrateur de ce " "serveur." #: 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: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 "" "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." #: 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 "" "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é." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Vérification du mot de passe :" #: mod_register_web.erl:269 msgid "Register" msgstr "Enregistrer" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Ancien mot de passe:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nouveau mot de passe:" #: 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:480 msgid "Unregister" msgstr "Effacer" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Abonnement" #: mod_roster.erl:1437 msgid "Pending" msgstr "En suspens" #: mod_roster.erl:1438 msgid "Groups" msgstr "Groupes" #: mod_roster.erl:1476 msgid "Validate" msgstr "Valider" #: mod_roster.erl:1485 msgid "Remove" msgstr "Enlever" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Liste de contact de " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Ajouter un Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Liste de contacts" #: 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:1232 msgid "Name:" msgstr "Nom :" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Description :" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membres :" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Groupes affichés :" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Groupe " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Serveur Jabber Erlang" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Date d'anniversaire" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Ville" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Pays" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Nom de famille" #: 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 "" "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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nom complet" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Autre nom" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nom de l'organisation" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unité de l'organisation" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Rechercher des utilisateurs " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Recherche dans l'annnuaire" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Module vCard ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Résultats de recherche pour " #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Ce participant est expulsé du salon pour avoir envoyé un message erronée " #~ "à un autre participant" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Le CAPTCHA est valide" #~ msgid "Encodings" #~ msgstr "Encodages" #~ msgid "(Raw)" #~ msgstr "(Brut)" ejabberd-16.01/priv/msgs/sk.po0000644000232200023220000014602612645157216016555 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.x\n" "PO-Revision-Date: 2012-04-29 18:25+0000\n" "Last-Translator: Marek BeÄka \n" "Language: sk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Slovak (slovenÄina)\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" "X-Additional-Translator: Juraj Michalek\n" "X-Additional-Translator: SkLUG\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Je vyžadované použitie STARTTLS " #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nebol poskytnutý žiadny zdroj" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Nahradené novým spojením" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Zadajte zobrazený text" #: 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: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:227 msgid "CAPTCHA web page" msgstr "Webová stránka CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Platná CAPTCHA." #: 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ľ" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Server ~b" #: 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" #: 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 "Neautorizovaný" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administrácia" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Surové dáta" #: 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: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:913 msgid "~s access rule configuration" msgstr "~s konfigurácia prístupového pravidla" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuálne servery" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Používatelia" #: 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:971 msgid "Users Last Activity" msgstr "Posledná aktivita používateľa" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "ÄŒas:" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Posledný mesiac" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Posledný rok" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "VÅ¡etky aktivity" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "ZobraziÅ¥ bežnú tabuľku" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "ZobraziÅ¥ kompletnú tabuľku" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Å tatistiky" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nebol nájdený" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Uzol nenájdený" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "PridaÅ¥ nový" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Server" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrovaní používatelia" #: 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:1459 msgid "Offline Messages" msgstr "Offline správy" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Posledná aktivita" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nikdy" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Online" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrovaní používatelia:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Odchádzajúce s2s spojenia:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Odchádzajúce s2s spojenia:" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Používateľ " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Pripojené zdroje:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Heslo:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "OdstrániÅ¥ užívateľa" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Žiadne dáta" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Uzly" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Bežiace uzly" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zastavené uzly" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Uzol" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databáza" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "ZálohovaÅ¥" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Otvorené portov" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "AktualizovaÅ¥" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "ReÅ¡tart" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "ZastaviÅ¥" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduly" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Chyba RPC volania" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Databázové tabuľky na " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Meno" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Typ úložiska" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Prvky" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Pamäť" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Chyba" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Záloha " #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "UložiÅ¥ binárnu zálohu:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Okamžite obnoviÅ¥ binárnu zálohu:" #: 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:1999 msgid "Store plain text backup:" msgstr "UložiÅ¥ zálohu do textového súboru:" #: 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: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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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: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:2115 msgid "Listened Ports at " msgstr "Otvorené porty na " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduly na " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Å tatistiky ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Uptime:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "ÄŒas procesoru" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transakcie potvrdená" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transakcie zruÅ¡ená" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transakcie reÅ¡tartovaná" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transakcie zaznamenaná" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "AktualizovaÅ¥ " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "AktualizovaÅ¥ plán" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Modifikované moduly" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Aktualizované skripty" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Nízkoúrovňový aktualizaÄný skript" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Kontrola skriptu" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokol" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Nastavenia" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Å tart" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Príkazy" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "SkutoÄne zmazaÅ¥ správu dňa?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Predmet" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Telo správy" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Správa neobsahuje text" #: mod_announce.erl:662 msgid "Announcements" msgstr "Oznámenia" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "OdoslaÅ¥ oznam vÅ¡etkým používateľom" #: 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:668 msgid "Send announcement to all online users" msgstr "OdoslaÅ¥ zoznam vÅ¡etkým online používateľom" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "AktualizovaÅ¥ správu dňa (neodosielaÅ¥)" #: 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:680 msgid "Delete message of the day" msgstr "ZmazaÅ¥ správu dňa" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Konfigurácia" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "SpustiÅ¥ moduly" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "ZastaviÅ¥ moduly" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "ObnoviÅ¥" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "UložiÅ¥ do textového súboru" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Import súboru" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Import adresára" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "ReÅ¡tartovaÅ¥ službu" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Vypnúť službu" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "VymazaÅ¥ užívateľa" #: 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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "ZmeniÅ¥ heslo užívateľa" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "ZobraziÅ¥ Å¡tatistiku užívateľa" #: 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:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "ZobraziÅ¥ poÄet pripojených užívateľov" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Správa užívateľov" #: mod_configure.erl:525 msgid "All Users" msgstr "VÅ¡etci užívatelia" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Odchádzajúce s2s spojenia" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Správa zálohovania" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "ImportovaÅ¥ užívateľov z jabberd14 spool súborov" #: mod_configure.erl:762 msgid "To ~s" msgstr "Pre ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Od ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Konfigurácia databázových tabuliek " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Vyberte typ úložiska pre tabuľky" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Len kópia disku" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Kópia RAM a disku" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Kópia RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Vzdialená kópia" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "ZastaviÅ¥ moduly na " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Vyberte moduly, ktoré majú byÅ¥ zastavené" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "SpustiÅ¥ moduly na " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Vložte zoznam modulov {Modul, [Parametre]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Zoznam modulov, ktoré majú byÅ¥ spustené" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Záloha do súboru na " #: 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: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:1115 msgid "Restore Backup from File at " msgstr "ObnoviÅ¥ zálohu zo súboru na " #: 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:1141 msgid "Enter path to text file" msgstr "Zadajte cestu k textovému súboru" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "ImportovaÅ¥ užívateľa zo súboru na " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Zadajte cestu k spool súboru jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "ImportovaÅ¥ užívateľov z adresára na " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Zadajte cestu k jabberd14 spool adresáru" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Cesta k adresáru" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "ÄŒasový posun" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfigurácia zoznamu prístupových oprávnení (ACL)" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Zoznamy prístupových oprávnení (ACL)" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Konfigurácia prístupu" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Overenie hesla" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "PoÄet registrovaných užívateľov" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "PoÄet online užívateľov" #: mod_configure.erl:1936 msgid "Last login" msgstr "Posledné prihlásenie" #: mod_configure.erl:1963 msgid "Roster size" msgstr "PoÄet kontaktov v zozname" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresa" #: mod_configure.erl:1967 msgid "Resources" msgstr "Zdroje" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administrácia " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Operácia aplikovaná na užívateľa" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "EditovaÅ¥ vlastnosti" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modul" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registrácia do mod_irc na" #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "Vložte meno používateľa, kódovanie, porty a heslo ktoré chcete používaÅ¥ pri " "pripojení na IRC server" #: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC prezývka" #: 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." msgstr "" "Ak chcete zadaÅ¥ iné porty, heslá a kódovania pre IRC servery, vyplnte zoznam " "s hodnotami vo formáte '{\"irc server\",\"kódovanie\", \"port\", \"heslo" "\"}'. Predvolenéi hodnoty pre túto službu sú: kódovanie \"~s\", port ~p a " "žiadne heslo." #: 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 "" "Príklad: [{\"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 "Parametre spojenia" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Pripojit IRC kanál" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanál (bez poÄiatoÄnej #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC server" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "PropojiÅ¥ IRC kanál sem." #: 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:1046 msgid "IRC settings" msgstr "Nastavania IRC" #: 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 "" "Vložte meno používateľa a kódovanie, ktoré chcete používaÅ¥ pri pripojení na " "IRC servery. Kliknutím na tlaÄítko 'ÄŽalej' môžete zadaÅ¥ niektoré ÄalÅ¡ie " "hodnoty. Pomocou 'UkonÄiÅ¥ ' uložíte nastavenia." #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC prezývka" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Heslo ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Kódovanie pre server ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registrácia prezývky na " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Prezývka" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Diskusné miestnosti" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "odiÅ¡iel(a) z miestnosti" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Registrovaní používatelia" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Nastavenie diskusnej miestnosti bolo zmenené" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "vstúpil(a) do miestnosti" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "odiÅ¡iel(a) z miestnosti" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "bol(a) zablokovaný(á)" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "bol vyhodený(á) kvôli reÅ¡tartu systému" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "sa premenoval(a) na" #: 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:493 msgid "Chatroom is created" msgstr "Diskusná miestnosÅ¥ je vytvorená" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Diskusná miestnosÅ¥ je zruÅ¡ená" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Diskusná miestnosÅ¥ je obnovená" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Diskusná miestnosÅ¥ je pozastavená" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Pondelok" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Utorok" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Streda" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Å tvrtok" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Piatok" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sobota" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Nedeľa" #: mod_muc_log.erl:513 msgid "January" msgstr "Január" #: mod_muc_log.erl:514 msgid "February" msgstr "Február" #: mod_muc_log.erl:515 msgid "March" msgstr "Marec" #: mod_muc_log.erl:516 msgid "April" msgstr "Apríl" #: mod_muc_log.erl:517 msgid "May" msgstr "Máj" #: mod_muc_log.erl:518 msgid "June" msgstr "Jún" #: mod_muc_log.erl:519 msgid "July" msgstr "Júl" #: mod_muc_log.erl:520 msgid "August" msgstr "August" #: mod_muc_log.erl:521 msgid "September" msgstr "September" #: mod_muc_log.erl:522 msgid "October" msgstr "Október" #: mod_muc_log.erl:523 msgid "November" msgstr "November" #: mod_muc_log.erl:524 msgid "December" msgstr "December" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Nastavenia miestnosti" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Ľudí v miestnosti" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Prezývka ~s v miestnosti neexistuje" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Neplatné priradenie: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Neplatná rola: ~s" #: 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:3359 msgid "Room title" msgstr "Názov miestnosti" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Popis miestnosti" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "NastaviÅ¥ miestnosÅ¥ ako trvalú" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "NastaviÅ¥ miestnosÅ¥ ako verejne prehľadávateľnú" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "NastaviÅ¥ zoznam zúÄastnených ako verejný" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "ChrániÅ¥ miestnosÅ¥ heslom" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "PoÄet úÄastníkov" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Bez limitu" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "ZobrazovaÅ¥ skutoÄné Jabber ID" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderátorom" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "vÅ¡etkým" #: 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:3516 msgid "Make room moderated" msgstr "NastaviÅ¥ miestnosÅ¥ ako moderovanú" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Užívatelia sú implicitne Älenmi" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "PovoliÅ¥ užívateľom meniÅ¥ tému" #: 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:3533 msgid "Allow visitors to send private messages to" msgstr "PovoliÅ¥ užívateľom odosielaÅ¥ súkromné správy" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "nikto" #: 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:3579 msgid "Allow users to send invites" msgstr "PovoliÅ¥ používateľom posielanie pozvánok" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "NávÅ¡tevníci môžu meniÅ¥ prezývky" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "PovoliÅ¥ používateľom posielanie pozvánok" #: 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:3599 msgid "Make room CAPTCHA protected" msgstr "ChrániÅ¥ miestnosÅ¥ systémom CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: 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:3621 msgid "Enable logging" msgstr "Zapnúť zaznamenávanie histórie" #: 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:4190 msgid "Number of occupants" msgstr "PoÄet zúÄastnených" #: mod_muc_room.erl:4260 msgid "private, " msgstr "súkromná, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "ŽiadosÅ¥ o Voice" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Povolte alebo zamietnite žiadosÅ¥ o Voice." #: mod_muc_room.erl:4349 msgid "User JID" msgstr "Používateľ " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "PrideltiÅ¥ Voice tejto osobe?" #: 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:4507 msgid "the password is" msgstr "heslo je" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "ÄŒas" #: mod_offline.erl:812 msgid "From" msgstr "Od" #: mod_offline.erl:813 msgid "To" msgstr "Pre" #: mod_offline.erl:814 msgid "Packet" msgstr "Paket" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline správy" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "OdstrániÅ¥ vÅ¡etky offline správy" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "ŽiadosÅ¥ odberateľa PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Zvolte, Äi chcete povoliÅ¥ toto odoberanie" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID uzlu" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adresa odberateľa" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "DoruÄiÅ¥ náklad s upozornením na udalosÅ¥" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "DoruÄiÅ¥ oznamy o udalosti" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "UpozorniÅ¥ prihlásených používateľov na zmazanie uzlu" #: 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:3755 msgid "Persist items to storage" msgstr "UložiÅ¥ položky natrvalo do úložiska" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Prístupný názov pre uzol" #: 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:3761 msgid "Whether to allow subscriptions" msgstr "PovoliÅ¥ prihlasovanie" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "UveÄte model prístupu" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Skupiny kontaktov, ktoré môžu odoberaÅ¥" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Å pecifikovaÅ¥ model publikovania" #: 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:3771 msgid "Specify the event message type" msgstr "UveÄte typ pre správu o udalosti" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maximálny náklad v bajtoch" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Kedy odoslaÅ¥ posledne publikovanú položku" #: 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:3779 msgid "The collections with which a node is affiliated" msgstr "Kolekcie asociované s uzlom" #: 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: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ý." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Pri vytváraní úÄtu nastala chyba: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Váš Jabber úÄet bol úspeÅ¡ne odstránený." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Pri ruÅ¡ení úÄtu nastala chyba:" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Heslo k Jabber úÄtu bolo úspeÅ¡ne zmenené." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Pri zmene hesla nastala chyba: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Registrácia jabber úÄtu" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "ZaregistrovaÅ¥ Jabber úÄet" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "IRC prezývka" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Veľké a malé písmená sa nerozliÅ¡ujú: macbeth je to isté ako MacBeth a " "Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Nepovolené znaky:" #: 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: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: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: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 "" "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: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 "" "Zapamätajte si heslo alebo si ho zapíšte na papier. Jabber neposkytuje " "automatickú funkciu ako zistiÅ¥ zabudnuté heslo. " #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Overenie hesla" #: mod_register_web.erl:269 msgid "Register" msgstr "Zoznam kontaktov" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Staré heslo:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nové heslo:" #: 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:480 msgid "Unregister" msgstr "ZruÅ¡iÅ¥ úÄet" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Prihlásenie" #: mod_roster.erl:1437 msgid "Pending" msgstr "ÄŒakajúce" #: mod_roster.erl:1438 msgid "Groups" msgstr "Skupiny" #: mod_roster.erl:1476 msgid "Validate" msgstr "OveriÅ¥" #: mod_roster.erl:1485 msgid "Remove" msgstr "OdstrániÅ¥" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Zoznam kontaktov " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "PridaÅ¥ Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Zoznam kontaktov" #: 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:1232 msgid "Name:" msgstr "Meno:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Popis:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "ÄŒlenovia:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Zobrazené skupiny:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Skupina " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Dátum narodenia" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Mesto" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Krajina" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-mail" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Priezvisko" #: 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 "" "Pre vyhľadanie Jabber používateľa vyplňte formulár (pridajte znak * na " "koniec, pre vyhľadanie podreÅ¥azca)" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Celé meno: " #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Prostredné meno: " #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Meno organizácie: " #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "OrganizaÄná jednotka: " #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "HľadaÅ¥ užívateľov v " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "HľadaÅ¥ užívateľov vo vCard" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard modul" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "HľadaÅ¥ výsledky pre " #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "ÚÄastník bol vyhodený z miestnosti, pretože poslal chybovú správu inému " #~ "úÄastníkovi" #~ 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 "Captcha test failed" #~ msgstr "Platná CAPTCHA." #~ msgid "Encodings" #~ msgstr "Kódovania" #~ msgid "(Raw)" #~ msgstr "(Raw)" #~ msgid "Specified nickname is already registered" #~ msgstr "Zadaná prezývka je už registrovaná" #~ msgid "Size" #~ msgstr "VeľkosÅ¥" #~ msgid "You must fill in field \"nick\" in the form" #~ msgstr "Musíte vyplniÅ¥ políÄko \"prezývka\" vo formulári" ejabberd-16.01/priv/msgs/ca.po0000644000232200023220000014675612645157216016535 0ustar debalancedebalance# Jan, 2012. msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \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" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Catalan (català)\n" "X-Additional-Translator: Vicent Alberola Canet\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.6.10\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "És obligatori utilitzar STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Recurs no disponible" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Reemplaçat per una nova connexió" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Introdueix el text que veus" #: 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: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:227 msgid "CAPTCHA web page" msgstr "Pàgina web del CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "El CAPTCHA es vàlid." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "No autoritzat" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Web d'administració del ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administració" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "en format text" #: 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: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:913 msgid "~s access rule configuration" msgstr "Configuració de les Regles d'Accés ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Hosts virtuals" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Usuaris" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Usuaris conectats" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Última activitat d'usuari" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Període: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Últim mes" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Últim any" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Tota l'activitat" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrar Taula Ordinaria" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrar Taula Integral" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estadístiques" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "No Trobat" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Node no trobat" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Afegir nou" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Usuaris registrats" #: 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:1459 msgid "Offline Messages" msgstr "Missatges offline" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última activitat" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Mai" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Connectat" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Usuaris registrats:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Connexions d'eixida s2s" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Connexions d'eixida 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 msgid "None" msgstr "Cap" #: 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:1673 msgid "User ~s" msgstr "Usuari ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos connectats:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Contrasenya:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminar usuari" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "No hi ha dades" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodes" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodes funcionant" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodes parats" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Node ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de dades" #: 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:1845 msgid "Listened Ports" msgstr "Ports a l'escolta" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Actualitzar" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Detindre" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Mòduls" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Error de cridada RPC" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Taules de la base de dades en ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nom" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipus d'emmagatzematge" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elements" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memòria" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Error" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Còpia de seguretat de ~p" #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Guardar una còpia de seguretat binària:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Restaurar una còpia de seguretat binària ara mateix." #: 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:1999 msgid "Store plain text backup:" msgstr "Guardar una còpia de seguretat en format de text pla:" #: 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: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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Exporta totes les taules a un fitxer SQL:" #: 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:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar dades d'usuaris del directori de spool de jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Ports a la escolta en " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Mòduls en ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Estadístiques de ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Temps en marxa" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Temps de CPU" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaccions Realitzades:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaccions Avortades" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaccions reiniciades" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaccions registrades" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Actualitzar ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Pla d'actualització" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Mòduls modificats" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script d'actualització" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script d'actualització de baix nivell" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Comprovar script" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocol" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Mòdul" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opcions" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Iniciar" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandaments" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Segur que vols eliminar el missatge del dia?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Assumpte" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Missatge" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "No hi ha proveedor per al missatge anunci" #: mod_announce.erl:662 msgid "Announcements" msgstr "Anuncis" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Enviar anunci a tots els usuaris" #: 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:668 msgid "Send announcement to all online users" msgstr "Enviar anunci a tots els usuaris connectats" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Actualitzar el missatge del dia (no enviar)" #: 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:680 msgid "Delete message of the day" msgstr "Eliminar el missatge del dia" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Configuració" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar mòduls" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Parar mòduls" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar a fitxer de text" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar fitxer" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar directori" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reiniciar el Servei" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Apager el Servei" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Eliminar Usuari" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Finalitzar Sesió d'Usuari" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Canviar Contrasenya d'Usuari" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Obtenir Estadístiques d'Usuari" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Obtenir Número d'Usuaris Registrats" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Obtenir Número d'Usuaris Connectats" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gestió d'Usuaris" #: mod_configure.erl:525 msgid "All Users" msgstr "Tots els usuaris" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Connexions s2s d'eixida" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestió de còpia de seguretat" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuaris de jabberd14" #: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuració de la base de dades en " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selecciona el tipus d'almacenament de les taules" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Còpia sols en disc" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Còpia en RAM i disc" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Còpia en RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Còpia remota" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Detindre mòduls en " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecciona mòduls a detindre" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar mòduls en " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introdueix llista de {mòdul, [opcions]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Llista de mòduls a iniciar" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Desar còpia de seguretat a fitxer en " #: 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:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Ruta al fitxer" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaura còpia de seguretat des del fitxer en " #: 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:1141 msgid "Enter path to text file" msgstr "Introdueix ruta al fitxer de text" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importa usuari des de fitxer en " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Introdueix ruta al fitxer jabberd14 spool" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar usuaris des del directori en " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Introdueix la ruta al directori de jabberd14 spools" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Ruta al directori" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Temps de retard" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuració de la Llista de Control d'Accés" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Llistes de Control de Accés" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuració d'accesos" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verificació de la Contrasenya" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Número d'Usuaris Registrats" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Número d'usuaris connectats" #: mod_configure.erl:1936 msgid "Last login" msgstr "Últim login" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Tamany de la llista" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Adreça IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Recursos" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administració de " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Acció en l'usuari" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propietats" #: mod_fail2ban.erl:95 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_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: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:476 msgid "ejabberd IRC module" msgstr "mòdul ejabberd IRC" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registre en mod_irc per a" #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" 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:667 msgid "IRC Username" msgstr "Nom d'usuari al IRC" #: 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." msgstr "" "Si vols especificar codificacions de caràcters diferents per a cada servidor " "IRC emplena aquesta llista amb els valors amb el format '{\"servidor irc\", " "\"codificació\", port, \"contrasenya\"}'. Aquest servei utilitza per " "defecte la codificació \"~s\", port ~p, no contrasenya." #: 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 "" "Exemple: [{\"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 "Paràmetres de connexió" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Entra a canal d'IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canal d'IRC (no posis la primera #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Servidor d'IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Entra al canal d'IRC aquí." #: 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:1046 msgid "IRC settings" msgstr "Configuració d'IRC." #: 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 "" "Introdueix el nom d'usuari i les codificacions de caràcters per a utilitzar " "als servidors de IRC. Apreta \"Seguent\" per veure més caps per omplir. " "Apreta \"Completar\" per guardar la configuració. " #: mod_irc.erl:1060 msgid "IRC username" msgstr "Nom d'usuari al IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Contrasenya ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codificació pel servidor ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servidor ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registre del sobrenom en " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Sobrenom" #: 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" #: 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:249 msgid "Total rooms" msgstr "Nombre total de sales" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Sales permanents" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Sobrenoms registrats" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Llista de sales" #: 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:410 msgid "joins the room" msgstr "Entrar a la sala" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "Deixar la sala" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "Has sigut banejat" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "Has sigut expulsat perquè el sistema s'ha apagat" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "ara es conegut com" #: 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:493 msgid "Chatroom is created" msgstr "La sala s'ha creat" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "La sala s'ha destruït" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "La sala s'ha iniciat" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "La sala s'ha aturat" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Dilluns" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Dimarts" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Dimecres" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Dijous" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Divendres" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Dissabte" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Diumenge" #: mod_muc_log.erl:513 msgid "January" msgstr "Gener" #: mod_muc_log.erl:514 msgid "February" msgstr "Febrer" #: mod_muc_log.erl:515 msgid "March" msgstr "Març" #: mod_muc_log.erl:516 msgid "April" msgstr "Abril" #: mod_muc_log.erl:517 msgid "May" msgstr "Maig" #: mod_muc_log.erl:518 msgid "June" msgstr "Juny" #: mod_muc_log.erl:519 msgid "July" msgstr "Juliol" #: mod_muc_log.erl:520 msgid "August" msgstr "Agost" #: mod_muc_log.erl:521 msgid "September" msgstr "Setembre" #: mod_muc_log.erl:522 msgid "October" msgstr "Octubre" #: mod_muc_log.erl:523 msgid "November" msgstr "Novembre" #: mod_muc_log.erl:524 msgid "December" msgstr "Decembre" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuració de la sala" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Nombre d'ocupants" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "El sobrenom ~s no existeix a la sala" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliació invàlida: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Rol invàlid: ~s" #: 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:3359 msgid "Room title" msgstr "Títol de la sala" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descripció de la sala:" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Crear una sala persistent" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Crear una sala pública" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Crear una llista de participants pública" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Crear una sala amb contrasenya" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Número màxim d'ocupants" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Sense Llímit" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Presentar Jabber ID's reals a" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "només moderadors" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "qualsevol" #: 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:3516 msgid "Make room moderated" msgstr "Crear una sala moderada" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Els usuaris són participants per defecte" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permetre que els usuaris canviin el tema" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permetre que els usuaris envien missatges privats" #: 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:3551 msgid "nobody" msgstr "ningú" #: 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:3579 msgid "Allow users to send invites" msgstr "Permetre que els usuaris envien invitacions" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Permetre als visitants canviar el sobrenom" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Permetre als visitants enviar peticions de veu" #: 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:3599 msgid "Make room CAPTCHA protected" msgstr "Crear una sala protegida per CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Activar l'emmagatzematge de missatges" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excloure Jabber IDs de la comprovació CAPTCHA" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Habilitar el registre de la conversa" #: 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:4190 msgid "Number of occupants" msgstr "Número d'ocupants" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privat" #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Petició de veu" #: 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:4349 msgid "User JID" msgstr "JID del usuari " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Concedir veu a aquesta persona?" #: 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:4507 msgid "the password is" msgstr "la contrasenya és" #: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "Servei de Multicast d'ejabberd" #: 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:811 msgid "Time" msgstr "Data" #: mod_offline.erl:812 msgid "From" msgstr "De" #: mod_offline.erl:813 msgid "To" msgstr "Per a" #: mod_offline.erl:814 msgid "Packet" msgstr "Paquet" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Missatges fora de línia:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Eliminar tots els missatges offline" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "mòdul ejabberd SOCKS5 Bytestreams" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publicar-subscriure't" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Mòdul ejabberd Publicar-Subscriure" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Petició de subscriptor PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Tria si aprova aquesta entitat de subscripció" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID del Node" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adreça del Subscriptor" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads junt a les notificacions d'events" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Entrega de notificacions d'events" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscriptors quan canvia la configuració del node" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptors quan el node és eliminat" #: 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:3755 msgid "Persist items to storage" msgstr "Persistir elements al guardar" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nom per al node" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Màxim # d'elements que persistixen" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Permetre subscripcions" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Especificar el model d'accés" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Llista de grups que tenen permés subscriures" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Especificar el model del publicant" #: 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:3771 msgid "Specify the event message type" msgstr "Especifica el tipus de missatge d'event" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Màxim tamany del payload en bytes" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Quan s'ha enviat l'última publicació" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Sols enviar notificacions als usuaris disponibles" #: 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: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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Hi ha hagut un error creant el compte: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "El teu compte Jabber ha sigut esborrat correctament." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Hi ha hagut un error esborrant el compte: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "La contrasenya del teu compte Jabber s'ha canviat correctament." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Hi ha hagut un error canviant la contrasenya: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Registre de compte Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Registrar un compte Jabber" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nom d'usuari:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Això no distingeix majúscules de minúscules: macbeth es el mateix que " "MacBeth i Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Caràcters no permesos:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Servidor:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "No li donis la teva contrasenya a ningú, ni tan sols als administradors del " "servidor Jabber." #: 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: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 "" "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." #: 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 "" "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." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verificació de la Contrasenya:" #: mod_register_web.erl:269 msgid "Register" msgstr "Registrar" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Antiga contrasenya:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nova Contrasenya:" #: 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:480 msgid "Unregister" msgstr "Anul·lar el registre" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscripció" #: mod_roster.erl:1437 msgid "Pending" msgstr "Pendent" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grups" #: mod_roster.erl:1476 msgid "Validate" msgstr "Validar" #: mod_roster.erl:1485 msgid "Remove" msgstr "Borrar" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Llista de contactes de " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Afegir Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Llista de contactes" #: 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:1232 msgid "Name:" msgstr "Nom:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descripció:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membre:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Mostrar grups:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grup " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Erlang Jabber" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Aniversari" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Ciutat" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Pais" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Cognom" #: 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 "" "Emplena el formulari per a buscar usuaris Jabber. Afegix * al final d'un " "camp per a buscar subcadenes." #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nom complet" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Segon nom" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nom de la organizació" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unitat de la organizació" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Cerca usuaris en " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Recerca de vCard d'usuari" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Mòdul ejabberd vCard" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Resultat de la búsqueda" #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Aquest participant ha sigut expulsat de la sala perque ha enviat un " #~ "missatge erroni a un altre participant" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "El CAPTCHA es vàlid." ejabberd-16.01/priv/msgs/id.msg0000644000232200023220000006201212645157216016674 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Akses Konfigurasi"}. {"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"}. {"Add Jabber ID","Tambah Jabber ID"}. {"Add New","Tambah Baru"}. {"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?"}. {"Allow users to change the subject","Perbolehkan pengguna untuk mengganti topik"}. {"Allow users to query other users","Perbolehkan pengguna untuk mengetahui pengguna lain"}. {"Allow users to send invites","Perbolehkan pengguna mengirimkan undangan"}. {"Allow users to send private messages","perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi"}. {"Allow visitors to change nickname","Perbolehkan visitor mengganti nama julukan"}. {"Allow visitors to send status text in presence updates","Izinkan pengunjung untuk mengirim teks status terbaru"}. {"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"}. {"Backup Management","Manajemen Backup"}. {"Backup to File at ","Backup ke File pada"}. {"Bad format","Format yang buruk"}. {"Birthday","Hari Lahir"}. {"CAPTCHA web page","CAPTCHA laman web"}. {"Change Password","Ubah Kata Sandi"}. {"Change User Password","Ubah User Password"}. {"Characters not allowed:","Karakter tidak diperbolehkan:"}. {"Chatroom configuration modified","Konfigurasi ruang chat diubah"}. {"Chatroom is created","Ruang chat telah dibuat"}. {"Chatroom is destroyed","Ruang chat dilenyapkan"}. {"Chatroom is started","Ruang chat dimulai"}. {"Chatroom is stopped","Ruang chat dihentikan"}. {"Chatrooms","Ruangan Chat"}. {"Choose a username and password to register with this server","Pilih nama pengguna dan kata sandi untuk mendaftar dengan layanan ini"}. {"Choose modules to stop","Pilih Modul untuk berhenti"}. {"Choose storage type of tables","Pilih jenis penyimpanan tabel"}. {"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:"}. {"Connections parameters","Parameter Koneksi"}. {"Country","Negara"}. {"CPU Time:","Waktu CPU:"}. {"Database","Database"}. {"Database Tables Configuration at ","Database Tabel Konfigurasi pada"}. {"December","Desember"}. {"Default users as participants","pengguna pertama kali masuk sebagai participant"}. {"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"}. {"Delete User","Hapus Pengguna"}. {"Deliver event notifications","Memberikan pemberitahuan acara"}. {"Deliver payloads with event notifications","Memberikan muatan dengan pemberitahuan acara"}. {"Description:","Keterangan:"}. {"Disc only copy","Hanya salinan dari disc"}. {"Displayed Groups:","Tampilkan Grup:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Jangan memberitahukan kata sandi Anda ke siapapun, bahkan para administrator dari layanan Jabber."}. {"Dump Backup to Text File at ","Dump Backup ke File Teks di"}. {"Dump to Text File","Dump menjadi File Teks"}. {"Edit Properties","Ganti Properti"}. {"ejabberd IRC module","ejabberd IRC modul"}. {"ejabberd MUC module","ejabberd MUC Module"}. {"ejabberd Publish-Subscribe module","Modul ejabberd Setujui-Pertemanan"}. {"ejabberd SOCKS5 Bytestreams module","modul ejabberd SOCKS5 Bytestreams"}. {"ejabberd vCard module","Modul ejabberd vCard"}. {"ejabberd Web Admin","Admin Web ejabberd"}. {"Elements","Elemen-elemen"}. {"Email","Email"}. {"Enable logging","Aktifkan catatan"}. {"Encoding for server ~b","Pengkodean untuk layanan ~b"}. {"End User Session","Akhir Sesi Pengguna"}. {"Enter list of {Module, [Options]}","Masukkan daftar {Modul, [Options]}"}. {"Enter nickname you want to register","Masukkan nama julukan Anda jika ingin mendaftar"}. {"Enter path to backup file","Masukkan path untuk file cadangan"}. {"Enter path to jabberd14 spool dir","Masukkan path ke direktori spool jabberd14"}. {"Enter path to jabberd14 spool file","Masukkan path ke file jabberd14 spool"}. {"Enter path to text file","Masukkan path ke file teks"}. {"Enter the text you see","Masukkan teks yang Anda lihat"}. {"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.","Masukkan username dan pengkodean yang ingin Anda gunakan untuk menghubungkan ke layanan IRC. Tekan 'Selanjutnya' untuk mendapatkan lagi formulir kemudian Tekan 'Lengkap' untuk menyimpan pengaturan."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Masukkan username, pengkodean, port dan sandi yang ingin Anda gunakan untuk menghubungkan ke layanan IRC"}. {"Erlang Jabber Server","Layanan Erlang Jabber"}. {"Error","Kesalahan"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Contoh: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Ekspor data dari semua pengguna pada layanan ke berkas PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Ekspor data pengguna pada sebuah host ke berkas PIEFXIS (XEP-0227):"}. {"Family Name","Nama Keluarga (marga)"}. {"February","Februari"}. {"Fill in fields to search for any matching Jabber User","Isi kolom untuk mencari pengguna Jabber yang sama"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Isi formulir untuk pencarian pengguna Jabber yang cocok (Tambahkan * ke mengakhiri pengisian untuk menyamakan kata)"}. {"Friday","Jumat"}. {"From","Dari"}. {"From ~s","Dari ~s"}. {"Full Name","Nama Lengkap"}. {"Get Number of Online Users","Dapatkan Jumlah User Yang Online"}. {"Get Number of Registered Users","Dapatkan Jumlah Pengguna Yang Terdaftar"}. {"Get User Last Login Time","Dapatkan Waktu Login Terakhir Pengguna "}. {"Get User Password","Dapatkan User Password"}. {"Get User Statistics","Dapatkan Statistik Pengguna"}. {"Group ","Grup"}. {"Groups","Grup"}. {"has been banned","telah dibanned"}. {"has been kicked because of an affiliation change","telah dikick karena perubahan afiliasi"}. {"has been kicked because of a system shutdown","telah dikick karena sistem shutdown"}. {"has been kicked because the room has been changed to members-only","telah dikick karena ruangan telah diubah menjadi hanya untuk member"}. {"has been kicked","telah dikick"}. {" has set the subject to: ","telah menetapkan topik yaitu:"}. {"Host","Host"}. {"If you don't see the CAPTCHA image here, visit the web page.","Jika Anda tidak melihat gambar CAPTCHA disini, silahkan kunjungi halaman web."}. {"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.","Jika Anda ingin menentukan port yang berbeda, sandi, pengkodean untuk layanan IRC, isi daftar ini dengan nilai-nilai dalam format '{\"server irc \", \"encoding \", port, \"sandi \"}'. Secara default ini menggunakan layanan \"~s \" pengkodean, port ~p, kata sandi kosong."}. {"Import Directory","Impor Direktori"}. {"Import File","Impor File"}. {"Import user data from jabberd14 spool file:","Impor data pengguna dari sekumpulan berkas jabberd14:"}. {"Import User from File at ","Impor Pengguna dari File pada"}. {"Import users data from a PIEFXIS file (XEP-0227):","impor data-data pengguna dari sebuah PIEFXIS (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","Channel IRC (tidak perlu menempatkan # sebelumnya)"}. {"IRC server","Layanan IRC"}. {"IRC settings","Pengaturan IRC"}. {"IRC Transport","IRC Transport"}. {"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"}. {"January","Januari"}. {"Join IRC channel","Gabung channel IRC"}. {"joins the room","bergabung ke ruangan"}. {"Join the IRC channel here.","Gabung ke channel IRC disini"}. {"Join the IRC channel in this Jabber ID: ~s","Gabung ke channel IRC dengan Jabber ID: ~s"}. {"July","Juli"}. {"June","Juni"}. {"Last Activity","Aktifitas Terakhir"}. {"Last login","Terakhir Login"}. {"Last month","Akhir bulan"}. {"Last year","Akhir tahun"}. {"leaves the room","meninggalkan ruangan"}. {"Listened Ports at ","Mendeteksi Port-port di"}. {"Listened Ports","Port Terdeteksi"}. {"List of modules to start","Daftar modul untuk memulai"}. {"Low level update script","Perbaruan naskah tingkat rendah"}. {"Make participants list public","Buat daftar participant diketahui oleh public"}. {"Make room CAPTCHA protected","Buat ruangan dilindungi dengan CAPTCHA"}. {"Make room members-only","Buat ruangan hanya untuk member saja"}. {"Make room moderated","Buat ruangan hanya untuk moderator saja"}. {"Make room password protected","Buat ruangan yang dilindungi dengan kata sandi"}. {"Make room persistent","Buat ruangan menjadi permanent"}. {"Make room public searchable","Buat ruangan dapat dicari"}. {"March","Maret"}. {"Maximum Number of Occupants","Maksimum Jumlah Penghuni"}. {"Max # of items to persist","Max item untuk bertahan"}. {"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"}. {"Modules","Modul"}. {"Monday","Senin"}. {"Name:","Nama:"}. {"Name","Nama"}. {"Never","Tidak Pernah"}. {"New Password:","Password Baru:"}. {"Nickname","Nama Julukan"}. {"Nickname Registration at ","Pendaftaran Julukan pada"}. {"Nickname ~s does not exist in the room","Nama Julukan ~s tidak berada di dalam ruangan"}. {"No body provided for announce message","Tidak ada isi pesan yang disediakan untuk mengirimkan pesan"}. {"No Data","Tidak Ada Data"}. {"Node ID","ID Node"}. {"Node not found","Node tidak ditemukan"}. {"Nodes","Node-node"}. {"No limit","Tidak terbatas"}. {"None","Tak satupun"}. {"No resource provided","Tidak ada sumber daya yang disediakan"}. {"Not Found","Tidak Ditemukan"}. {"Notify subscribers when items are removed from the node","Beritahu pelanggan ketika item tersebut dikeluarkan dari node"}. {"Notify subscribers when the node configuration changes","Beritahu pelanggan ketika ada perubahan konfigurasi node"}. {"Notify subscribers when the node is deleted","Beritahu pelanggan ketika node dihapus"}. {"November","Nopember"}. {"Number of occupants","Jumlah Penghuni"}. {"Number of online users","Jumlah pengguna online"}. {"Number of registered users","Jumlah pengguna terdaftar"}. {"October","Oktober"}. {"Offline Messages:","Pesan Offline:"}. {"Offline Messages","Pesan Offline"}. {"OK","YA"}. {"Old Password:","Password Lama:"}. {"Online","Online"}. {"Online Users:","Pengguna Online:"}. {"Online Users","Pengguna Yang Online"}. {"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:"}. {"Owner privileges required","Hak istimewa owner dibutuhkan"}. {"Packet","Paket"}. {"Password ~b","Kata Sandi ~b"}. {"Password:","Kata Sandi:"}. {"Password","Sandi"}. {"Password Verification:","Verifikasi Kata Sandi:"}. {"Password Verification","Verifikasi Sandi"}. {"Path to Dir","Jalur ke Dir"}. {"Path to File","Jalur ke File"}. {"Pending","Tertunda"}. {"Period: ","Periode:"}. {"Persist items to storage","Pertahankan item ke penyimpanan"}. {"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.","Harap dicatat bahwa pilihan ini hanya akan membuat cadangan builtin Mnesia database. Jika Anda menggunakan modul ODBC, anda juga perlu untuk membuat cadangan database SQL Anda secara terpisah."}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. {"Present real Jabber IDs to","Tampilkan Jabber ID secara lengkap"}. {"private, ","pribadi, "}. {"Protocol","Protocol"}. {"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"}. {"Register","Mendaftar"}. {"Registration in mod_irc for ","Pendaftaran di mod_irc untuk"}. {"Remote copy","Salinan Remote"}. {"Remove All Offline Messages","Hapus Semua Pesan Offline"}. {"Remove","Menghapus"}. {"Remove User","Hapus Pengguna"}. {"Replaced by new connection","Diganti dengan koneksi baru"}. {"Resources","Sumber daya"}. {"Restart","Jalankan Ulang"}. {"Restart Service","Restart Layanan"}. {"Restore Backup from File at ","Kembalikan Backup dari File pada"}. {"Restore binary backup after next ejabberd restart (requires less memory):","Mengembalikan cadangan yang berpasanagn setelah ejabberd berikutnya dijalankan ulang (memerlukan memori lebih sedikit):"}. {"Restore binary backup immediately:","Segera mengembalikan cadangan yang berpasangan:"}. {"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"}. {"Roster groups allowed to subscribe","Kelompok kontak yang diizinkan untuk berlangganan"}. {"Roster","Kontak"}. {"Roster of ","Kontak dari"}. {"Roster size","Ukuran Daftar Kontak"}. {"RPC Call Error","Panggilan Kesalahan RPC"}. {"Running Nodes","Menjalankan Node"}. {"~s access rule configuration","~s aturan akses konfigurasi"}. {"Saturday","Sabtu"}. {"Script check","Periksa naskah"}. {"Search Results for ","Hasil Pencarian untuk"}. {"Search users in ","Pencarian pengguna dalam"}. {"Send announcement to all online users","Kirim pengumuman untuk semua pengguna yang online"}. {"Send announcement to all online users on all hosts","Kirim pengumuman untuk semua pengguna yang online pada semua host"}. {"Send announcement to all users","Kirim pengumuman untuk semua pengguna"}. {"Send announcement to all users on all hosts","Kirim pengumuman untuk semua pengguna pada semua host"}. {"September","September"}. {"Server ~b","Layanan ~b"}. {"Server:","Layanan:"}. {"Set message of the day and send to online users","Mengatur pesan harian dan mengirimkan ke pengguna yang online"}. {"Set message of the day on all hosts and send to online users","Mengatur pesan harian pada semua host dan kirimkan ke pengguna yang online"}. {"Shared Roster Groups","Berbagi grup kontak"}. {"Show Integral Table","Tampilkan Tabel Terpisah"}. {"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 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"}. {"~s's Offline Messages Queue","Antrian Pesan Offline ~s"}. {"Start Modules at ","Mulai Modul pada"}. {"Start Modules","Memulai Modul"}. {"Start","Mulai"}. {"Statistics of ~p","statistik dari ~p"}. {"Statistics","Statistik"}. {"Stop","Hentikan"}. {"Stop Modules at ","Hentikan Modul pada"}. {"Stop Modules","Hentikan Modul"}. {"Stopped Nodes","Menghentikan node"}. {"Storage Type","Jenis Penyimpanan"}. {"Store binary backup:","Penyimpanan cadangan yang berpasangan:"}. {"Store plain text backup:","Simpan cadangan teks biasa:"}. {"Subject","Subyek"}. {"Submit","Serahkan"}. {"Submitted","Ulangi masukan"}. {"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:"}. {"There was an error deleting the account: ","Ada kesalahan saat menghapus akun:"}. {"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."}. {"Thursday","Kamis"}. {"Time delay","Waktu tunda"}. {"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"}. {"Update","Memperbarui"}. {"Update message of the day (don't send)","Rubah pesan harian (tidak dikirim)"}. {"Update message of the day on all hosts (don't send)","Rubah pesan harian pada semua host (tidak dikirim)"}. {"Update plan","Rencana Perubahan"}. {"Update script","Perbarui naskah"}. {"Uptime:","Sampai saat:"}. {"Use of STARTTLS required","Penggunaan STARTTLS diperlukan"}. {"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"}. ejabberd-16.01/priv/msgs/pt.msg0000644000232200023220000001572512645157216016734 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Configuração de acessos"}. {"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"}. {"Backup to File at ","Guardar cópia de segurança para ficheiro em "}. {"Birthday","Data de nascimento"}. {"Change Password","Mudar palavra-chave"}. {"Choose a username and password to register with this server","Escolha um nome de utilizador e palavra-chave para se registar neste servidor"}. {"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"}. {"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 "}. {"Dump to Text File","Exportar para ficheiro de texto"}. {"Edit Properties","Editar propriedades"}. {"ejabberd IRC module","Módulo de IRC ejabberd"}. {"ejabberd MUC module","Módulo MUC de ejabberd"}. {"ejabberd vCard module","Módulo vCard de ejabberd"}. {"Enter list of {Module, [Options]}","Introduza lista de {módulos, [opções]}"}. {"Enter nickname you want to register","Introduza a alcunha que quer registar"}. {"Enter path to backup file","Introduza o caminho do ficheiro de cópia de segurança"}. {"Enter path to jabberd14 spool dir","Introduza o caminho para o directório de spools do jabberd14"}. {"Enter path to jabberd14 spool file","Introduza o caminho para o ficheiro de spool do jabberd14"}. {"Enter path to text file","Introduza caminho para o ficheiro de texto"}. {"Erlang Jabber Server","Servidor Jabber em Erlang"}. {"Family Name","Apelido"}. {"Fill in fields to search for any matching Jabber User","Preencha os campos para procurar utilizadores Jabber coincidentes"}. {"From","De"}. {"From ~s","De ~s"}. {"Full Name","Nome completo"}. {"Groups","Grupos"}. {" has set the subject to: "," colocou o tópico: "}. {"Import Directory","Importar directório"}. {"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 "}. {"List of modules to start","Lista de módulos a iniciar"}. {"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"}. {"Never","Nunca"}. {"Nickname","Alcunha"}. {"Nickname Registration at ","Registo da alcunha em "}. {"Nickname ~s does not exist in the room","A alcunha ~s não existe na sala"}. {"Node not found","Nodo não encontrado"}. {"Nodes","Nodos"}. {"None","Nenhum"}. {"No resource provided","Não foi passado nenhum recurso"}. {"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"}. {"Path to Dir","Caminho para o directório"}. {"Path to File","Caminho do ficheiro"}. {"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"}. {"Remove User","Eliminar utilizador"}. {"Restart","Reiniciar"}. {"Restore Backup from File at ","Restaura cópia de segurança a partir do ficheiro em "}. {"Restore","Restaurar"}. {"Room title","Título da sala"}. {"Roster","Lista de contactos"}. {"Roster of ","Lista de contactos de "}. {"Running Nodes","Nodos a correr"}. {"~s access rule configuration","Configuração das Regra de Acesso ~s"}. {"Search users in ","Procurar utilizadores em "}. {"Start Modules at ","Iniciar os módulos em "}. {"Start Modules","Iniciar módulos"}. {"Statistics","Estatísticas"}. {"Stop Modules at ","Parar módulos em "}. {"Stop Modules","Parar módulos"}. {"Stop","Parar"}. {"Stopped Nodes","Nodos parados"}. {"Storage Type","Tipo de armazenagem"}. {"Submit","Enviar"}. {"Subscription","Subscrição"}. {"Time","Data"}. {"To","Para"}. {"To ~s","A ~s"}. {"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"}. ejabberd-16.01/priv/msgs/pt.po0000644000232200023220000013573612645157216016571 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "Last-Translator: Iceburn\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Portuguese (português)\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Não foi passado nenhum recurso" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "" #: 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: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: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:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Nunca" #: 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" #: 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 #, fuzzy msgid "ejabberd Web Admin" msgstr "Administração do ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 #, fuzzy msgid "Administration" msgstr "Administração de " #: 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: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: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: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:782 ejabberd_web_admin.erl:881 #, fuzzy msgid "Raw" msgstr "modo texto" #: 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: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:913 msgid "~s access rule configuration" msgstr "Configuração das Regra de Acesso ~s" #: ejabberd_web_admin.erl:931 #, fuzzy msgid "Virtual Hosts" msgstr "Servidores virtuales" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Utilizadores" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Utilizadores ligados" #: ejabberd_web_admin.erl:971 #, fuzzy msgid "Users Last Activity" msgstr "Última actividade" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "" #: ejabberd_web_admin.erl:991 #, fuzzy msgid "All activity" msgstr "Última actividade" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" #: ejabberd_web_admin.erl:1014 #, fuzzy msgid "Not Found" msgstr "Nodo não encontrado" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo não encontrado" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Adicionar novo" #: ejabberd_web_admin.erl:1338 #, fuzzy msgid "Host" msgstr "Nome do servidor" #: ejabberd_web_admin.erl:1339 #, fuzzy msgid "Registered Users" msgstr "Utilizadores registados" #: 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:1459 #, fuzzy msgid "Offline Messages" msgstr "Mensagens diferidas" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última actividade" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Nunca" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Ligado" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 #, fuzzy msgid "Registered Users:" msgstr "Utilizadores registados" #: 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:1556 #, fuzzy msgid "Outgoing s2s Connections:" msgstr "Conexões S2S para fora" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Conexões S2S para fora" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Utilizador" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos conectados:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Palavra-chave:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminar utilizador" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodos" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos a correr" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos parados" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nodo" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "" #: 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:1845 #, fuzzy msgid "Listened Ports" msgstr "Portas em escuta em " #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Actualizar" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Parar" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" #: ejabberd_web_admin.erl:1866 #, fuzzy msgid "RPC Call Error" msgstr "Erro na chamada RPC" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabelas da BD em " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo de armazenagem" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memória" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Guardar cópia de segurança" #: 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:1969 #, fuzzy msgid "Store binary backup:" msgstr "Armazenar uma cópia de segurança no ficheiro" #: 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:1979 #, fuzzy msgid "Restore binary backup immediately:" msgstr "Recuperar uma cópia de segurança a partir de ficheiro" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "" #: 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:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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: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:2115 msgid "Listened Ports at " msgstr "Portas em escuta em " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Parar módulos em " #: ejabberd_web_admin.erl:2175 #, fuzzy msgid "Statistics of ~p" msgstr "Estatísticas" #: ejabberd_web_admin.erl:2179 #, fuzzy msgid "Uptime:" msgstr "Tempo de funcionamento" #: ejabberd_web_admin.erl:2183 #, fuzzy msgid "CPU Time:" msgstr "Tempo de processador consumido" #: ejabberd_web_admin.erl:2191 #, fuzzy msgid "Transactions Committed:" msgstr "Transacções realizadas" #: ejabberd_web_admin.erl:2195 #, fuzzy msgid "Transactions Aborted:" msgstr "Transacções abortadas" #: ejabberd_web_admin.erl:2199 #, fuzzy msgid "Transactions Restarted:" msgstr "Transacções reiniciadas" #: ejabberd_web_admin.erl:2203 #, fuzzy msgid "Transactions Logged:" msgstr "Transacções armazenadas" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Actualizar" #: ejabberd_web_admin.erl:2254 #, fuzzy msgid "Update plan" msgstr "Actualizar" #: ejabberd_web_admin.erl:2255 #, fuzzy msgid "Modified modules" msgstr "Iniciar módulos" #: ejabberd_web_admin.erl:2256 #, fuzzy msgid "Update script" msgstr "Actualizar" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Porta" #: ejabberd_web_admin.erl:2439 #, fuzzy msgid "Protocol" msgstr "Porta" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Módulo" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opções" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 #, fuzzy msgid "Start" msgstr "Reiniciar" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "" #: mod_adhoc.erl:176 mod_adhoc.erl:265 #, fuzzy msgid "Ping" msgstr "Pendente" #: mod_adhoc.erl:279 msgid "Pong" msgstr "" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 #, fuzzy msgid "Subject" msgstr "Enviar" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "" #: mod_announce.erl:662 msgid "Announcements" msgstr "" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "" #: 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:672 msgid "Set message of the day and send to online users" msgstr "" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "" #: mod_announce.erl:680 #, fuzzy msgid "Delete message of the day" msgstr "Eliminar os seleccionados" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Configuração" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar módulos" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Parar módulos" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar para ficheiro de texto" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar ficheiro" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar directório" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 #, fuzzy msgid "Restart Service" msgstr "Reiniciar" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 #, fuzzy msgid "Delete User" msgstr "Eliminar" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "" #: 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:185 mod_configure.erl:546 #, fuzzy msgid "Change User Password" msgstr "Mudar palavra-chave" #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 #, fuzzy msgid "Get User Statistics" msgstr "Estatísticas" #: mod_configure.erl:191 mod_configure.erl:552 #, fuzzy msgid "Get Number of Registered Users" msgstr "Utilizadores registados" #: mod_configure.erl:194 mod_configure.erl:554 #, fuzzy msgid "Get Number of Online Users" msgstr "Utilizadores ligados" #: mod_configure.erl:320 mod_configure.erl:523 #, fuzzy msgid "User Management" msgstr "Gestão da BD" #: mod_configure.erl:525 msgid "All Users" msgstr "Todos os utilizadores" #: mod_configure.erl:526 #, fuzzy msgid "Outgoing s2s Connections" msgstr "Conexões S2S para fora" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestão de cópias de segurança" #: 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:762 msgid "To ~s" msgstr "A ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" #: mod_configure.erl:1002 #, fuzzy msgid "Database Tables Configuration at " msgstr "Configuração de tabelas da BD em " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Seleccione o tipo de armazenagem das tabelas" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Cópia apenas em disco" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Cópia em RAM e em disco" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Cópia em RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Cópia remota" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Parar módulos em " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Seleccione os módulos a parar" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar os módulos em " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introduza lista de {módulos, [opções]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista de módulos a iniciar" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Guardar cópia de segurança para ficheiro em " #: 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:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Caminho do ficheiro" #: 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:1136 msgid "Dump Backup to Text File at " msgstr "Exporta cópia de segurança para ficheiro de texto em " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introduza caminho para o ficheiro de texto" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importar utilizador a partir do ficheiro em " #: 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:1177 msgid "Import Users from Dir at " msgstr "Importar utilizadores a partir do directório em " #: 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:1184 msgid "Path to Dir" msgstr "Caminho para o directório" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuração da Lista de Controlo de Acesso" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listas de Controlo de Acesso" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuração de acessos" #: mod_configure.erl:1356 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_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "" #: mod_configure.erl:1540 #, fuzzy msgid "Number of registered users" msgstr "Utilizadores registados" #: mod_configure.erl:1559 #, fuzzy msgid "Number of online users" msgstr "Utilizadores ligados" #: mod_configure.erl:1936 msgid "Last login" msgstr "" #: mod_configure.erl:1963 #, fuzzy msgid "Roster size" msgstr "Lista de contactos" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "" #: mod_configure.erl:1967 #, fuzzy msgid "Resources" msgstr "Restaurar" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administração de " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Acção no utilizador" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propriedades" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "Módulo de IRC ejabberd" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registo no mod_irc para" #: mod_irc.erl:659 #, fuzzy msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "Introduza o nome de utilizador e codificações de caracteres que quer usar ao " "conectar-se aos servidores de IRC" #: mod_irc.erl:667 msgid "IRC Username" msgstr "Nome do utilizador de 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 "" "Se deseja especificar codificações de caracteres diferentes para cada " "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: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:713 msgid "Connections parameters" msgstr "" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" #: mod_irc.erl:903 #, fuzzy msgid "IRC server" msgstr "Nome do utilizador de IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "" #: 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 "" "Introduza o nome de utilizador e codificações de caracteres que quer usar ao " "conectar-se aos servidores de IRC" #: mod_irc.erl:1060 #, fuzzy msgid "IRC username" msgstr "Nome do utilizador de IRC" #: mod_irc.erl:1126 #, fuzzy msgid "Password ~b" msgstr "Palavra-chave" #: mod_irc.erl:1137 #, fuzzy msgid "Port ~b" msgstr "Porta" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registo da alcunha em " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Alcunha" #: 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" #: 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:249 msgid "Total rooms" msgstr "" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Utilizadores registados" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 #, fuzzy msgid "Chatroom configuration modified" msgstr "Configuração para " #: mod_muc_log.erl:410 msgid "joins the room" msgstr "" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "" #: 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:493 #, fuzzy msgid "Chatroom is created" msgstr "Configuração para " #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "" #: mod_muc_log.erl:503 msgid "Monday" msgstr "" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "" #: mod_muc_log.erl:507 msgid "Friday" msgstr "" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "" #: mod_muc_log.erl:513 msgid "January" msgstr "" #: mod_muc_log.erl:514 msgid "February" msgstr "" #: mod_muc_log.erl:515 msgid "March" msgstr "" #: mod_muc_log.erl:516 msgid "April" msgstr "" #: mod_muc_log.erl:517 msgid "May" msgstr "" #: mod_muc_log.erl:518 msgid "June" msgstr "" #: mod_muc_log.erl:519 msgid "July" msgstr "" #: mod_muc_log.erl:520 msgid "August" msgstr "" #: mod_muc_log.erl:521 msgid "September" msgstr "" #: mod_muc_log.erl:522 msgid "October" msgstr "" #: mod_muc_log.erl:523 #, fuzzy msgid "November" msgstr "Nunca" #: mod_muc_log.erl:524 msgid "December" msgstr "" #: mod_muc_log.erl:912 #, fuzzy msgid "Room Configuration" msgstr "Configuração" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "" #: 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: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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "A alcunha ~s não existe na sala" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliação inválida: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Papel inválido: ~s" #: 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:3359 msgid "Room title" msgstr "Título da sala" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "Subscrição" #: mod_muc_room.erl:3369 #, fuzzy msgid "Make room persistent" msgstr "Tornar a sala permanente?" #: mod_muc_room.erl:3375 #, fuzzy msgid "Make room public searchable" msgstr "Tornar a sala publicamente visível?" #: mod_muc_room.erl:3378 #, fuzzy msgid "Make participants list public" msgstr "Tornar pública a lista de participantes?" #: mod_muc_room.erl:3380 #, fuzzy msgid "Make room password protected" msgstr "Proteger a sala com palavra-chave?" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 #, fuzzy msgid "anyone" msgstr "Nenhum" #: 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:3516 msgid "Make room moderated" msgstr "Tornar a sala moderada" #: mod_muc_room.erl:3519 #, fuzzy msgid "Default users as participants" msgstr "Os utilizadores são membros por omissão?" #: 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:3525 #, fuzzy msgid "Allow users to send private messages" msgstr "Permitir que os utilizadores enviem mensagens privadas?" #: 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:3551 msgid "nobody" msgstr "" #: mod_muc_room.erl:3576 #, fuzzy msgid "Allow users to query other users" msgstr "Permitir aos utilizadores consultar outros utilizadores?" #: mod_muc_room.erl:3579 #, fuzzy msgid "Allow users to send invites" msgstr "Permitir que os utilizadores enviem convites?" #: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" #: mod_muc_room.erl:3586 #, fuzzy msgid "Allow visitors to change nickname" msgstr "Permitir aos utilizadores mudar o tópico?" #: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permitir que os utilizadores enviem convites?" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: mod_muc_room.erl:3599 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Proteger a sala com palavra-chave?" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" #: mod_muc_room.erl:3621 #, fuzzy msgid "Enable logging" msgstr "Guardar históricos?" #: 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:4190 msgid "Number of occupants" msgstr "" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privado" #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Utilizador" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "" #: mod_muc_room.erl:4507 #, fuzzy msgid "the password is" msgstr "Mudar palavra-chave" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 #, fuzzy msgid "ejabberd Multicast service" msgstr "Utilizadores do ejabberd" #: 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:811 msgid "Time" msgstr "Data" #: mod_offline.erl:812 msgid "From" msgstr "De" #: mod_offline.erl:813 msgid "To" msgstr "Para" #: mod_offline.erl:814 msgid "Packet" msgstr "Pacote" #: mod_offline.erl:992 #, fuzzy msgid "Offline Messages:" msgstr "Mensagens diferidas:" #: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "Mensagens diferidas" #: mod_proxy65_service.erl:248 #, fuzzy msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Módulo vCard de ejabberd" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "" #: mod_pubsub.erl:1222 #, fuzzy msgid "ejabberd Publish-Subscribe module" msgstr "Módulo pub/sub de ejabberd" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "" #: mod_pubsub.erl:1559 #, fuzzy msgid "Node ID" msgstr "Nodo" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" #: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" #: 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: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 "" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "" #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "" #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "" #: mod_register_web.erl:175 mod_register_web.erl:183 #, fuzzy msgid "Jabber Account Registration" msgstr "Configuração das Listas de Controlo de Acesso do ejabberd" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" #: mod_register_web.erl:214 msgid "" "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." msgstr "" #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "Nome do utilizador de IRC" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "Nunca" #: 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:249 msgid "You can later change your password using a Jabber client." msgstr "" #: 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 "" #: 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:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "" #: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Lista de contactos" #: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Palavra-chave:" #: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Palavra-chave:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" #: mod_register_web.erl:480 msgid "Unregister" msgstr "" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscrição" #: mod_roster.erl:1437 msgid "Pending" msgstr "Pendente" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grupos" #: mod_roster.erl:1476 msgid "Validate" msgstr "" #: mod_roster.erl:1485 msgid "Remove" msgstr "Remover" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista de contactos de " #: mod_roster.erl:1504 #, fuzzy msgid "Add Jabber ID" msgstr "Adicionar Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Lista de contactos" #: 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:1232 #, fuzzy msgid "Name:" msgstr "Nome" #: mod_shared_roster.erl:1236 #, fuzzy msgid "Description:" msgstr "Subscrição" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "" #: mod_shared_roster.erl:1259 #, fuzzy msgid "Group " msgstr "Grupos" #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Jabber em Erlang" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Data de nascimento" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Cidade" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "País" #: mod_vcard.erl:490 mod_vcard.erl:625 #, fuzzy msgid "Email" msgstr "email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Apelido" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nome completo" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Segundo nome" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nome da organização" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unidade da organização" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Procurar utilizadores em " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Módulo vCard de ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 #, fuzzy msgid "Search Results for " msgstr "Procurar utilizadores em " #: 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" #, fuzzy #~ msgid "Outgoing s2s Servers:" #~ msgstr "Servidores S2S de saída" #~ msgid "Delete" #~ msgstr "Eliminar" #, fuzzy #~ msgid "This room is not anonymous" #~ msgstr "Tornar a sala anónima?" #~ msgid "Encodings" #~ msgstr "Codificações" #, fuzzy #~ msgid "(Raw)" #~ msgstr "(modo texto)" #~ msgid "Specified nickname is already registered" #~ msgstr "A alcunha especificada já está registada" #~ msgid "Size" #~ msgstr "Tamanho" #~ msgid "Backup Management at " #~ msgstr "Gestão da cópia de segurança em " #~ msgid "Choose host name" #~ msgstr "Introduza o nome do servidor" #~ msgid "Choose users to remove" #~ msgstr "Seleccione utilizadores a eliminar" #~ msgid "DB" #~ msgstr "BD" #~ msgid "Dump a database in a text file" #~ msgstr "Exportar uma Base de Dados para um ficheiro de texto" #~ msgid "Host name" #~ msgstr "Nome do servidor" #~ msgid "Hostname Configuration" #~ msgstr "Configuração do nome do servidor" #~ msgid "Install a database fallback from a file" #~ msgstr "Instalar uma recuperação de BD desde um ficheiro" #~ msgid "It is not allowed to send normal messages to the conference" #~ msgstr "Impedir o envio de mensagens normais para a sala" #~ msgid "Listened Ports Management" #~ msgstr "Gestão das portas em escuta" #~ msgid "Make room moderated?" #~ msgstr "Tornar a sala moderada?" #~ msgid "Remove Users" #~ msgstr "Eliminar utilizadores" #~ msgid "Restore a database from a text file" #~ msgstr "Restaurar uma Base de Dados a partir de ficheiro de texto" #~ msgid "Results of search in " #~ msgstr "Resultados da procura em " #~ msgid "ejabberd (c) 2002-2005 Alexey Shchepin, 2005 Process One" #~ msgstr "ejabberd (c) 2002-2005 Alexey Shchepin, 2005 Process One" #~ msgid "ejabberd access rules configuration" #~ msgstr "Configuração das Regras de Acesso do ejabberd" #~ msgid "~p statistics" #~ msgstr "Estatísticas de ~p" ejabberd-16.01/priv/msgs/ru.po0000644000232200023220000017357212645157216016574 0ustar debalancedebalance# , 2010. msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \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" "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:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Ð’Ñ‹ обÑзаны иÑпользовать STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Ðе указан реÑурÑ" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Заменено новым Ñоединением" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Введите увиденный текÑÑ‚" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Ваши ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ðº ~s блокируютÑÑ. Ð”Ð»Ñ ÑнÑÑ‚Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸ перейдите по ÑÑылке ~s" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "ЕÑли вы не видите изображение капчи, перейдите по ÑÑылке." #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "СÑылка на капчу" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Проверка капчи прошла уÑпешно." #: 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 "Пользователь" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "ÐдминиÑтрирование" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Ðеобработанный формат" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Правила доÑтупа" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð° доÑтупа ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Виртуальные хоÑты" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Пользователи" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Подключённые пользователи" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "СтатиÑтика поÑледнего Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Период" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "За поÑледний меÑÑц" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "За поÑледний год" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Ð’ÑÑ ÑтатиÑтика" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Показать обычную таблицу" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Показать интегральную таблицу" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "СтатиÑтика" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Ðе Ðайдено" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Узел не найден" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Добавить" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "ХоÑÑ‚" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "ЗарегиÑтрированные пользователи" #: 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:1459 msgid "Offline Messages" msgstr "Офлайновые ÑообщениÑ" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "ПоÑледнее подключение" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Ðикогда" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Подключён" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "ЗарегиÑтрированные пользователи:" #: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 #: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Подключённые пользователи:" #: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "ИÑходÑщие s2s-Ñерверы:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" 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 msgid "None" msgstr "Ðет" #: 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:1673 msgid "User ~s" msgstr "Пользователь ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Подключённые реÑурÑÑ‹:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Пароль:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Удалить пользователÑ" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Ðет данных" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Узлы" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Работающие узлы" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "ОÑтановленные узлы" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Узел ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "База данных" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Резервное копирование" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "ПроÑлушиваемые порты" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Обновить" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "ПерезапуÑтить" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "ОÑтановить" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Модули" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Ошибка вызова RPC" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Таблицы базы данных на ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Ðазвание" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Тип таблицы" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Элементы" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "ПамÑть" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Ошибка" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Резервное копирование ~p" #: 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 "" "Заметьте, что здеÑÑŒ производитÑÑ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¾Ðµ копирование только вÑтроенной " "базы данных Mnesia. ЕÑли Ð’Ñ‹ также иÑпользуете другое хранилище данных " "(например Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ð¼Ð¾Ð´ÑƒÐ»Ñ ODBC), то его резервное копирование Ñледует " "оÑущеÑтвлÑть отдельно." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Сохранить бинарную резервную копию:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "ВоÑÑтановить из бинарной резервной копии немедленно:" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "ВоÑÑтановить из бинарной резервной копии при Ñледующем запуÑке (требует " "меньше памÑти):" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Сохранить текÑтовую резервную копию:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "ВоÑÑтановить из текÑтовой резервной копии немедленно:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Импорт пользовательÑких данных из файла формата PIEFXIS (XEP-0227):" #: 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:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "ЭкÑпорт пользовательÑких данных домена в файлы формата PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "ЭкÑпортировать вÑе таблицы в виде SQL запроÑов в файл:" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Импорт пользовательÑких данных из буферного файла jabberd14:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Импорт пользовательÑких данных из буферной директории jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "ПроÑлушиваемые порты на " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Модули на ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "ÑтатиÑтика узла ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "ПроцеÑÑорное времÑ:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Транзакции завершенные:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Транзакции отмененные:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Транзакции перезапущенные:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Транзакции запротоколированные:" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Обновление ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "План обновлениÑ" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Изменённые модули" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Сценарий обновлениÑ" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Ðизкоуровневый Ñценарий обновлениÑ" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Проверка ÑценариÑ" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Порт" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Протокол" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Модуль" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Параметры" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "ЗапуÑтить" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Команды" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Пинг" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Понг" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "ДейÑтвительно удалить Ñообщение днÑ?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Тема" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Тело ÑообщениÑ" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Тело объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð½Ðµ должно быть пуÑтым" #: mod_announce.erl:662 msgid "Announcements" msgstr "ОбъÑвлениÑ" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "РазоÑлать объÑвление вÑем пользователÑм" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "РазоÑлать объÑвление вÑем пользователÑм на вÑех виртуальных Ñерверах" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "РазоÑлать объÑвление вÑем подключённым пользователÑм" #: 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:672 msgid "Set message of the day and send to online users" msgstr "УÑтановить Ñообщение Ð´Ð½Ñ Ð¸ разоÑлать его подключённым пользователÑм" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "УÑтановить Ñообщение Ð´Ð½Ñ Ð½Ð° вÑех виртуальных Ñерверах и разоÑлать его " "подключённым пользователÑм" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Обновить Ñообщение Ð´Ð½Ñ (не раÑÑылать)" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Обновить Ñообщение Ð´Ð½Ñ Ð½Ð° вÑех виртуальных Ñерверах (не раÑÑылать)" #: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Удалить Ñообщение днÑ" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Удалить Ñообщение Ð´Ð½Ñ Ñо вÑех виртуальных Ñерверов" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "КонфигурациÑ" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "ЗапуÑк модулей" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "ОÑтановка модулей" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "ВоÑÑтановление из резервной копии" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Копирование в текÑтовый файл" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Импорт из файла" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Импорт из директории" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "ПерезапуÑтить Ñлужбу" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "ОÑтановить Ñлужбу" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Удалить пользователÑ" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Завершить ÑÐµÐ°Ð½Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ" #: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 #: mod_configure.erl:1473 msgid "Get User Password" msgstr "Получить пароль пользователÑ" #: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Изменить пароль пользователÑ" #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Получить Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Получить ÑтатиÑтику по пользователю" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Получить количеÑтво зарегиÑтрированных пользователей" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Получить количеÑтво подключённых пользователей" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Управление пользователÑми" #: mod_configure.erl:525 msgid "All Users" msgstr "Ð’Ñе пользователи" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "ИÑходÑщие s2s-ÑоединениÑ" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Управление резервным копированием" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Импорт пользователей из Ñпула jabberd14" #: mod_configure.erl:762 msgid "To ~s" msgstr "К ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "От ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ† базы данных на " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Выберите тип Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "только диÑк" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "ОЗУ и диÑк" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "ОЗУ" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "не хранитÑÑ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "ОÑтановка модулей на " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Выберите модули, которые Ñледует оÑтановить" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "ЗапуÑк модулей на " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Введите ÑпиÑок вида {Module, [Options]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "СпиÑок запуÑкаемых модулей" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Резервное копирование в файл на " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Введите путь к резервному файлу" #: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Путь к файлу" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "ВоÑÑтановление из резервной копии на " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Копирование в текÑтовый файл на " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Введите путь к текÑтовому файлу" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Импорт Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð· файла на " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Введите путь к файлу из Ñпула jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Импорт пользователей из директории на " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Введите путь к директории Ñпула jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Путь к директории" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "По иÑтечение" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÑпиÑков ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупом" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "СпиÑки ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупом" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð´Ð¾Ñтупа" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Проверка паролÑ" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "КоличеÑтво зарегиÑтрированных пользователей" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "КоличеÑтво подключённых пользователей" #: mod_configure.erl:1936 msgid "Last login" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего подключениÑ" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Размер ÑпиÑка контактов" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP адреÑа" #: mod_configure.erl:1967 msgid "Resources" msgstr "РеÑурÑÑ‹" #: mod_configure.erl:2095 msgid "Administration of " msgstr "ÐдминиÑтрирование " #: mod_configure.erl:2100 msgid "Action on user" msgstr "ДейÑтвие над пользователем" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Изменить параметры" #: 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_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:220 mod_muc.erl:467 msgid "Access denied by service policy" msgstr "ДоÑтуп запрещён политикой Ñлужбы" #: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC ТранÑпорт" #: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC модуль" #: 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:653 msgid "Registration in mod_irc for " msgstr "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð² mod_irc Ð´Ð»Ñ " #: 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:667 msgid "IRC Username" msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ IRC" #: 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." msgstr "" "Чтобы указать различные порты, пароли, кодировки Ð´Ð»Ñ Ñ€Ð°Ð·Ð½Ñ‹Ñ… Ñерверов IRC, " "заполните ÑпиÑок значениÑми в формате '{\"Ñервер IRC\", \"кодировка\", порт, " "\"пароль\"}'. По умолчанию ÑÐµÑ€Ð²Ð¸Ñ Ð¸Ñпользует кодировку \"~s\", порт ~p, " "пуÑтой пароль." #: 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 "" "Пример: [{\"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 "Параметры ÑоединениÑ" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "ПриÑоединитьÑÑ Ðº каналу IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Канал IRC (без Ñимвола #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Сервер IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "ПриÑоединÑйтеÑÑŒ к каналу IRC" #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "ПриÑоединитьÑÑ Ðº каналу IRC Ñ Jabber ID: ~s" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "ÐаÑтройки IRC" #: 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 "" "Введите Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ кодировки, которые будут иÑпользоватьÑÑ Ð¿Ñ€Ð¸ " "подключении к IRC-Ñерверам. Ðажмите 'Далее' Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… " "полей Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ. Ðажмите 'Завершить' Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð½Ð°Ñтроек." #: mod_irc.erl:1060 msgid "IRC username" msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Пароль ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Порт ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Кодировка Ñервера ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Сервер ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñевдонима на " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "ПÑевдоним" #: 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 модуль" #: 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:249 msgid "Total rooms" msgstr "Ð’Ñе комнаты" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "ПоÑтоÑнные комнаты" #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "ЗарегиÑтрированные пÑевдонимы" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "СпиÑок комнат" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ изменилаÑÑŒ" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "вошёл(а) в комнату" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "вышел(а) из комнаты" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "запретили входить в комнату" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "выгнали из комнаты вÑледÑтвие Ñмены ранга" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "выгнали из комнаты потому что она Ñтала только Ð´Ð»Ñ Ñ‡Ð»ÐµÐ½Ð¾Ð²" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "выгнали из комнаты из-за оÑтанова ÑиÑтемы" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "изменил(а) Ð¸Ð¼Ñ Ð½Ð°" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " уÑтановил(а) тему: " #: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Комната Ñоздана" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Комната уничтожена" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Комната запущена" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Комната оÑтановлена" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Понедельник" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Вторник" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Среда" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Четверг" #: mod_muc_log.erl:507 msgid "Friday" msgstr "ПÑтница" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Суббота" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "ВоÑкреÑенье" #: mod_muc_log.erl:513 msgid "January" msgstr "ÑнварÑ" #: mod_muc_log.erl:514 msgid "February" msgstr "февралÑ" #: mod_muc_log.erl:515 msgid "March" msgstr "марта" #: mod_muc_log.erl:516 msgid "April" msgstr "апрелÑ" #: mod_muc_log.erl:517 msgid "May" msgstr "маÑ" #: mod_muc_log.erl:518 msgid "June" msgstr "июнÑ" #: mod_muc_log.erl:519 msgid "July" msgstr "июлÑ" #: mod_muc_log.erl:520 msgid "August" msgstr "авгуÑта" #: mod_muc_log.erl:521 msgid "September" msgstr "ÑентÑбрÑ" #: mod_muc_log.erl:522 msgid "October" msgstr "октÑбрÑ" #: mod_muc_log.erl:523 msgid "November" msgstr "ноÑбрÑ" #: mod_muc_log.erl:524 msgid "December" msgstr "декабрÑ" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "УчаÑтники комнаты" #: 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:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Только модераторы могут изменÑть тему в Ñтой комнате" #: 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:2772 msgid "Nickname ~s does not exist in the room" msgstr "ПÑевдоним ~s в комнате отÑутÑтвует" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "ÐедопуÑтимый ранг: ~s" #: 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:3348 msgid "Configuration of room ~s" msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ ~s" #: mod_muc_room.erl:3359 msgid "Room title" msgstr "Ðазвание комнаты" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "ОпиÑание комнаты" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Сделать комнату поÑтоÑнной" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Сделать комнату видимой вÑем" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Сделать ÑпиÑок учаÑтников видимым вÑем" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Сделать комнату защищённой паролем" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "МакÑимальное количеÑтво учаÑтников" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Ðе ограничено" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Сделать реальные Jabber ID учаÑтников видимыми" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "только модераторам" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "вÑем учаÑтникам" #: 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:3516 msgid "Make room moderated" msgstr "Сделать комнату модерируемой" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Сделать пользователей учаÑтниками по умолчанию" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Разрешить пользователÑм изменÑть тему" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Разрешить приватные ÑообщениÑ" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Разрешить поÑетителÑм поÑылать приватные ÑообщениÑ" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "никто" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Разрешить iq-запроÑÑ‹ к пользователÑм" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Разрешить пользователÑм поÑылать приглашениÑ" #: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Разрешить поÑетителÑм вÑтавлÑть текcÑ‚ ÑтатуÑа в ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ приÑутÑтвии" #: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Разрешить поÑетителÑм изменÑть пÑевдоним" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Разрешить поÑетителÑм запрашивать право голоÑа" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Минимальный интервал между запроÑами на право голоÑа" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Сделать комнату защищённой капчей" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Включить хранение Ñообщений" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "ИÑключить показ капчи Ð´Ð»Ñ ÑпиÑка Jabber ID" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Включить журналирование" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Чтобы Ñконфигурировать комнату, требуетÑÑ x:data-ÑовмеÑтимый клиент" #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "ЧиÑло приÑутÑтвующих" #: mod_muc_room.erl:4260 msgid "private, " msgstr "приватнаÑ, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° право голоÑа" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Подтвердите или отклоните право голоÑа." #: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID пользователÑ" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "ПредоÑтавить голоÑ?" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s приглашает Ð²Ð°Ñ Ð² комнату ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "пароль:" #: mod_multicast.erl:291 msgid "Multicast" msgstr "МультикаÑÑ‚" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast ÑервиÑ" #: 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:811 msgid "Time" msgstr "ВремÑ" #: mod_offline.erl:812 msgid "From" msgstr "От кого" #: mod_offline.erl:813 msgid "To" msgstr "Кому" #: mod_offline.erl:814 msgid "Packet" msgstr "Пакет" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Офлайновые ÑообщениÑ:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Удалить вÑе офлайновые ÑообщениÑ" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams модуль" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "ПубликациÑ-ПодпиÑка" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Модуль ejabberd Публикации-ПодпиÑки" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñчика PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Решите: предоÑтавить ли подпиÑку Ñтому объекту." #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID узла" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "ÐÐ´Ñ€ÐµÑ Ð¿Ð¾Ð´Ð¿Ð¸Ñчика" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Разрешить Ñтому Jabber ID подпиÑатьÑÑ Ð½Ð° данный узел?" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "ДоÑтавлÑть вмеÑте Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñми o публикациÑÑ… Ñами публикации" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "ДоÑтавлÑть ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ ÑобытиÑÑ…" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "УведомлÑть подпиÑчиков об изменении конфигурации Ñборника" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "УведомлÑть подпиÑчиков об удалении Ñборника" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "УведомлÑть подпиÑчиков об удалении публикаций из Ñборника" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "СохранÑть публикации в хранилище" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Легко запоминаемое Ð¸Ð¼Ñ Ð´Ð»Ñ ÑƒÐ·Ð»Ð°" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "МакÑимальное чиÑло ÑохранÑемых публикаций" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Разрешить подпиÑку" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Укажите механизм ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупом" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Группы ÑпиÑка контактов, которым разрешена подпиÑка" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ð¸" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Очищать вÑе запиÑи автора публикации когда он отключаетÑÑ" #: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Укажите тип ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ Ñобытии" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "МакÑимальный размер полезной нагрузки в байтах" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Когда поÑылать поÑледний опубликованный Ñлемент" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "ДоÑтавлÑть ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ доÑтупным пользователÑм" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Ð˜Ð¼Ñ ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ð¸, в которую входит узел" #: 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: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-аккаунт был уÑпешно Ñоздан." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Ошибка при Ñоздании аккаунта:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Ваш Jabber-аккаунт был уÑпешно удален." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Ошибка при удалении аккаунта:" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Пароль Вашего Jabber-аккаунта был уÑпешно изменен." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Ошибка при Ñмене паролÑ:" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Jabber-аккаунта" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "ЗарегиÑтрировать Jabber-аккаунт" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Удалить Jabber-аккаунт" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "ЗдеÑÑŒ Ð’Ñ‹ можете Ñоздать Jabber-аккаунт на Ñтом Jabber-Ñервере. Ваш JID " "(Jabber-идентификатор) будет в виде: \"пользователь@Ñервер\". ПожалуйÑта, " "внимательно читайте инÑтрукции Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÐµÐ¹." #: 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 "" "РегиÑтр не имеет значениÑ: \"маша\" и \"МÐШÐ\" будет ÑчитатьÑÑ Ð¾Ð´Ð½Ð¸Ð¼ и тем " "же именем." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "ÐедопуÑтимые Ñимволы:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Сервер:" #: 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:249 msgid "You can later change your password using a Jabber client." msgstr "Позже Ð’Ñ‹ можете изменить пароль через 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 "" "Ðекоторые Jabber-клиенты могут ÑохранÑть пароль на Вашем компьютере. " "ИÑпользуйте Ñту функцию только в том Ñлучае, еÑли Ñчитаете Ñто безопаÑным." #: 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 "" "Запомните пароль или запишите его на бумаге, которую Ñохраните в безопаÑном " "меÑте. Ð’ Jabber'е нет автоматизированного ÑредÑтва воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð² " "том Ñлучае, еÑли Ð’Ñ‹ его забудете." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Проверка паролÑ:" #: mod_register_web.erl:269 msgid "Register" msgstr "ЗарегиÑтрировать" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Старый пароль:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Ðовый пароль:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "ЗдеÑÑŒ Ð’Ñ‹ можете удалить Jabber-аккаунт Ñ Ñтого Ñервера." #: mod_register_web.erl:480 msgid "Unregister" msgstr "Удалить" #: mod_roster.erl:1436 msgid "Subscription" msgstr "ПодпиÑка" #: mod_roster.erl:1437 msgid "Pending" msgstr "Ожидание" #: mod_roster.erl:1438 msgid "Groups" msgstr "Группы" #: mod_roster.erl:1476 msgid "Validate" msgstr "Утвердить" #: mod_roster.erl:1485 msgid "Remove" msgstr "Удалить" #: mod_roster.erl:1490 msgid "Roster of " msgstr "РоÑтер Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Добавить Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "РоÑтер" #: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 #: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Группы общих контактов" #: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Ðазвание:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "ОпиÑание:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Члены:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Видимые группы:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Группа " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "День рождениÑ" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Город" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Страна" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð°" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "ФамилиÑ" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Полное имÑ" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "ОтчеÑтво" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Ðазвание организации" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Отдел организации" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "ПоиÑк пользователей в " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "ПоиÑк пользователей по vCard" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard модуль" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Результаты поиÑка в " #: mod_vcard_ldap.erl:502 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 "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Этого учаÑтника выгнали из комнаты за то, что он поÑлал Ñообщение об " #~ "ошибке" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Этого учаÑтника выгнали из комнаты за то, что он поÑлал Ñообщение об " #~ "ошибке другому учаÑтнику" #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Этого учаÑтника выгнали из комнаты за то, что он поÑлал приÑутÑтвие Ñ " #~ "ошибкой" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Проверка капчи прошла уÑпешно." ejabberd-16.01/priv/msgs/es.msg0000644000232200023220000006775712645157216016734 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"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"}. {"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"}. {"Add Jabber ID","Añadir Jabber ID"}. {"Add New","Añadir nuevo"}. {"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?"}. {"Allow users to change the subject","Permitir a los usuarios cambiar el asunto"}. {"Allow users to query other users","Permitir a los usuarios consultar a otros usuarios"}. {"Allow users to send invites","Permitir a los usuarios enviar invitaciones"}. {"Allow users to send private messages","Permitir a los usuarios enviar mensajes privados"}. {"Allow visitors to change nickname","Permitir a los visitantes cambiarse el apodo"}. {"Allow visitors to send private messages to","Permitir a los visitantes enviar mensajes privados a"}. {"Allow visitors to send status text in presence updates","Permitir a los visitantes enviar texto de estado en las actualizaciones de presencia"}. {"Allow visitors to send voice requests","Permitir a los visitantes enviar peticiones de voz"}. {"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"}. {"Backup Management","Gestión de copia de seguridad"}. {"Backup of ~p","Copia de seguridad de ~p"}. {"Backup to File at ","Guardar copia de seguridad en fichero en "}. {"Bad format","Mal formato"}. {"Birthday","Cumpleaños"}. {"CAPTCHA web page","Página web de CAPTCHA"}. {"Change Password","Cambiar contraseña"}. {"Change User Password","Cambiar contraseña de usuario"}. {"Characters not allowed:","Caracteres no permitidos:"}. {"Chatroom configuration modified","Configuración de la sala modificada"}. {"Chatroom is created","Se ha creado la sala"}. {"Chatroom is destroyed","Se ha destruido la sala"}. {"Chatroom is started","Se ha iniciado la sala"}. {"Chatroom is stopped","Se ha detenido la sala"}. {"Chatrooms","Salas de charla"}. {"Choose a username and password to register with this server","Escoge un nombre de usuario y contraseña para registrarte en este servidor"}. {"Choose modules to stop","Selecciona módulos a detener"}. {"Choose storage type of tables","Selecciona tipo de almacenamiento de las tablas"}. {"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:"}. {"Connections parameters","Parámetros de conexiones"}. {"Country","País"}. {"CPU Time:","Tiempo consumido de CPU:"}. {"Database","Base de datos"}. {"Database Tables at ~p","Tablas de la base de datos en ~p"}. {"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 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"}. {"Delete User","Borrar usuario"}. {"Deliver event notifications","Entregar notificaciones de eventos"}. {"Deliver payloads with event notifications","Enviar contenidos junto con las notificaciones de eventos"}. {"Description:","Descripción:"}. {"Disc only copy","Copia en disco solamente"}. {"Displayed Groups:","Mostrar grupos:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","No le digas tu contraseña a nadie, ni siquiera a los administradores del servidor Jabber."}. {"Dump Backup to Text File at ","Exporta copia de seguridad a fichero de texto en "}. {"Dump to Text File","Exportar a fichero de texto"}. {"Edit Properties","Editar propiedades"}. {"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"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"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]}"}. {"Enter nickname you want to register","Introduce el apodo que quieras registrar"}. {"Enter path to backup file","Introduce ruta al fichero de copia de seguridad"}. {"Enter path to jabberd14 spool dir","Introduce la ruta al directorio de jabberd14 spools"}. {"Enter path to jabberd14 spool file","Introduce ruta al fichero jabberd14 spool"}. {"Enter path to text file","Introduce ruta al fichero de texto"}. {"Enter the text you see","Teclea el texto que ves"}. {"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.","Introduce el nombre de usuario y codificaciones de carácteres que quieras usar al conectar en los servidores de IRC. Pulsa Siguiente para conseguir más campos en el formulario. Pulsa Completar para guardar las opciones."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Introduce el nombre de usuario, codificaciones de carácteres, puertos y contraseñas que quieras usar al conectar en los servidores de IRC"}. {"Erlang Jabber Server","Servidor Jabber en Erlang"}. {"Error","Error"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Ejemplo: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Excluir Jabber IDs de las pruebas de CAPTCHA"}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Rellena el formulario para buscar usuarios Jabber. Añade * al final de un campo para buscar subcadenas."}. {"Friday","viernes"}. {"From","De"}. {"From ~s","De ~s"}. {"Full Name","Nombre completo"}. {"Get Number of Online Users","Ver número de usuarios conectados"}. {"Get Number of Registered Users","Ver número de usuarios registrados"}. {"Get User Last Login Time","Ver fecha de la última conexión de usuario"}. {"Get User Password","Ver contraseña de usuario"}. {"Get User Statistics","Ver estadísticas de usuario"}. {"Grant voice to this person?","¿Conceder voz a esta persona?"}. {"Group ","Grupo "}. {"Groups","Grupos"}. {"has been banned","ha sido bloqueado"}. {"has been kicked because of an affiliation change","ha sido expulsado por un cambio de su afiliación"}. {"has been kicked because of a system shutdown","ha sido expulsado porque el sistema se va a detener"}. {"has been kicked because the room has been changed to members-only","ha sido expulsado porque la sala es ahora solo para miembros"}. {"has been kicked","ha sido expulsado"}. {" has set the subject to: "," ha puesto el asunto: "}. {"Host","Dominio"}. {"If you don't see the CAPTCHA image here, visit the web page.","Si no ves la imagen CAPTCHA aquí, visita la página web."}. {"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 quieres especificar distintos codificaciones de carácteres, contraseñas o puertos para cada servidor IRC rellena esta lista con valores en el formato '{\"servidor irc\", \"codificación\", \"puerto\", \"contrasela\"}'. Este servicio usa por defecto la codificación \"~s\", puerto ~p, sin contraseña."}. {"Import Directory","Importar directorio"}. {"Import File","Importar fichero"}. {"Import user data from jabberd14 spool file:","Importar usuario de fichero spool de jabberd14:"}. {"Import User from File at ","Importa usuario desde fichero en "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importar usuarios desde un fichero PIEFXIS (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","Canal IRC (no pongas el # del principio)"}. {"IRC server","Servidor IRC"}. {"IRC settings","Opciones de IRC"}. {"IRC Transport","Transporte de IRC"}. {"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"}. {"January","enero"}. {"Join IRC channel","Entrar en canal IRC"}. {"joins the room","entra en la sala"}. {"Join the IRC channel here.","Entrar en el canal de IRC aquí"}. {"Join the IRC channel in this Jabber ID: ~s","Entra en el canal de IRC en esta dirección Jabber: ~s"}. {"July","julio"}. {"June","junio"}. {"Last Activity","Última actividad"}. {"Last login","Última conexión"}. {"Last month","Último mes"}. {"Last year","Último año"}. {"leaves the room","sale de la sala"}. {"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"}. {"Make room members-only","Sala sólo para miembros"}. {"Make room moderated","Sala moderada"}. {"Make room password protected","Proteger la sala con contraseña"}. {"Make room persistent","Sala permanente"}. {"Make room public searchable","Sala públicamente visible"}. {"March","marzo"}. {"Maximum Number of Occupants","Número máximo de ocupantes"}. {"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"}. {"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"}. {"New Password:","Nueva contraseña:"}. {"Nickname","Apodo"}. {"Nickname Registration at ","Registro del apodo en "}. {"Nickname ~s does not exist in the room","El apodo ~s no existe en la sala"}. {"nobody","nadie"}. {"No body provided for announce message","No se ha proporcionado cuerpo de mensaje para el anuncio"}. {"No Data","Sin datos"}. {"Node ID","Nodo ID"}. {"Node not found","Nodo no encontrado"}. {"Node ~p","Nodo ~p"}. {"Nodes","Nodos"}. {"No limit","Sin límite"}. {"None","Ninguno"}. {"No resource provided","No se ha proporcionado recurso"}. {"Not Found","No encontrado"}. {"Notify subscribers when items are removed from the node","Notificar subscriptores cuando los elementos se borran del nodo"}. {"Notify subscribers when the node configuration changes","Notificar subscriptores cuando cambia la configuración del nodo"}. {"Notify subscribers when the node is deleted","Notificar subscriptores cuando el nodo se borra"}. {"November","noviembre"}. {"Number of occupants","Número de ocupantes"}. {"Number of online users","Número de usuarios conectados"}. {"Number of registered users","Número de usuarios registrados"}. {"October","octubre"}. {"Offline Messages:","Mensajes diferidos:"}. {"Offline Messages","Mensajes diferidos"}. {"OK","Aceptar"}. {"Old Password:","Contraseña antigua:"}. {"Online","Conectado"}. {"Online Users:","Usuarios conectados:"}. {"Online Users","Usuarios conectados"}. {"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"}. {"Owner privileges required","Se requieren privilegios de propietario de la sala"}. {"Packet","Paquete"}. {"Password ~b","Contraseña ~b"}. {"Password:","Contraseña:"}. {"Password","Contraseña"}. {"Password Verification:","Verificación de la contraseña:"}. {"Password Verification","Verificación de la contraseña"}. {"Path to Dir","Ruta al directorio"}. {"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."}. {"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"}. {"Present real Jabber IDs to","Los Jabber ID reales pueden verlos"}. {"private, ","privado"}. {"Protocol","Protocolo"}. {"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:"}. {"Registered Users","Usuarios registrados"}. {"Register","Registrar"}. {"Registration in mod_irc for ","Registro en mod_irc para"}. {"Remote copy","Copia remota"}. {"Remove All Offline Messages","Borrar todos los mensajes diferidos"}. {"Remove","Borrar"}. {"Remove User","Eliminar usuario"}. {"Replaced by new connection","Reemplazado por una nueva conexión"}. {"Resources","Recursos"}. {"Restart","Reiniciar"}. {"Restart Service","Reiniciar el servicio"}. {"Restore Backup from File at ","Restaura copia de seguridad desde el fichero en "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Restaurar copia de seguridad binaria en el siguiente reinicio de ejabberd (requiere menos memoria que si instantánea):"}. {"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"}. {"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"}. {"Roster groups allowed to subscribe","Grupos de contactos que pueden suscribirse"}. {"Roster","Lista de contactos"}. {"Roster of ","Lista de contactos de "}. {"Roster size","Tamaño de la lista de contactos"}. {"RPC Call Error","Error en la llamada RPC"}. {"Running Nodes","Nodos funcionando"}. {"~s access rule configuration","Configuración de las Regla de Acceso ~s"}. {"Saturday","sábado"}. {"Script check","Comprobación de script"}. {"Search Results for ","Buscar resultados por "}. {"Search users in ","Buscar usuarios en "}. {"Send announcement to all online users","Enviar anuncio a todos los usuarios conectados"}. {"Send announcement to all online users on all hosts","Enviar anuncio a todos los usuarios conectados en todos los dominios"}. {"Send announcement to all users","Enviar anuncio a todos los usuarios"}. {"Send announcement to all users on all hosts","Enviar anuncio a todos los usuarios en todos los dominios"}. {"September","septiembre"}. {"Server ~b","Servidor ~b"}. {"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"}. {"Show Integral Table","Mostrar Tabla Integral"}. {"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 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"}. {"~s's Offline Messages Queue","Cola de mensajes diferidos de ~s"}. {"Start","Iniciar"}. {"Start Modules at ","Iniciar módulos en "}. {"Start Modules","Iniciar módulos"}. {"Statistics","Estadísticas"}. {"Statistics of ~p","Estadísticas de ~p"}. {"Stop","Detener"}. {"Stop Modules at ","Detener módulos en "}. {"Stop Modules","Detener módulos"}. {"Stopped Nodes","Nodos detenidos"}. {"Storage Type","Tipo de almacenamiento"}. {"Store binary backup:","Guardar copia de seguridad binaria:"}. {"Store plain text backup:","Guardar copia de seguridad en texto plano:"}. {"Subject","Asunto"}. {"Submit","Enviar"}. {"Submitted","Enviado"}. {"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:"}. {"There was an error deleting the account: ","Hubo un error borrando la cuenta."}. {"This IP address is blacklisted in ~s","Esta dirección IP está en la lista negra en ~s"}. {"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."}. {"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"}. {"Update","Actualizar"}. {"Update message of the day (don't send)","Actualizar mensaje del dia, pero no enviarlo"}. {"Update message of the day on all hosts (don't send)","Actualizar el mensaje del día en todos los dominos (pero no enviarlo)"}. {"Update ~p","Actualizar ~p"}. {"Update plan","Plan de actualización"}. {"Update script","Script de actualización"}. {"Uptime:","Tiempo desde el inicio:"}. {"Use of STARTTLS required","Es obligatorio usar STARTTLS"}. {"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"}. {"User","Usuario"}. {"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"}. ejabberd-16.01/priv/msgs/ca.msg0000644000232200023220000006747212645157216016702 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"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"}. {"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"}. {"Add Jabber ID","Afegir Jabber ID"}. {"Add New","Afegir nou"}. {"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"}. {"Allow users to change the subject","Permetre que els usuaris canviin el tema"}. {"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 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"}. {"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"}. {"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"}. {"CAPTCHA web page","Pàgina web del CAPTCHA"}. {"Change Password","Canviar Contrasenya"}. {"Change User Password","Canviar Contrasenya d'Usuari"}. {"Characters not allowed:","Caràcters no permesos:"}. {"Chatroom configuration modified","Configuració de la sala de xat modificada"}. {"Chatroom is created","La sala s'ha creat"}. {"Chatroom is destroyed","La sala s'ha destruït"}. {"Chatroom is started","La sala s'ha iniciat"}. {"Chatroom is stopped","La sala s'ha aturat"}. {"Chatrooms","Sales de xat"}. {"Choose a username and password to register with this server","Tria nom d'usuari i contrasenya per a registrar-te en aquest servidor"}. {"Choose modules to stop","Selecciona mòduls a detindre"}. {"Choose storage type of tables","Selecciona el tipus d'almacenament de les taules"}. {"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:"}. {"Connections parameters","Paràmetres de connexió"}. {"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 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"}. {"Delete User","Eliminar Usuari"}. {"Deliver event notifications","Entrega de notificacions d'events"}. {"Deliver payloads with event notifications","Enviar payloads junt a les notificacions d'events"}. {"Description:","Descripció:"}. {"Disc only copy","Còpia sols en disc"}. {"Displayed Groups:","Mostrar grups:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","No li donis la teva contrasenya a ningú, ni tan sols als administradors del servidor Jabber."}. {"Dump Backup to Text File at ","Exporta còpia de seguretat a fitxer de text en "}. {"Dump to Text File","Exportar a fitxer de text"}. {"Edit Properties","Editar propietats"}. {"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"}. {"ejabberd Web Admin","Web d'administració del ejabberd"}. {"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 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"}. {"Enter path to text file","Introdueix ruta al fitxer de text"}. {"Enter the text you see","Introdueix el text que veus"}. {"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.","Introdueix el nom d'usuari i les codificacions de caràcters per a utilitzar als servidors de IRC. Apreta \"Seguent\" per veure més caps per omplir. Apreta \"Completar\" per guardar la configuració. "}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Introdueix el nom d'usuari, les codificacions de caràcters, els ports i contrasenyes per a utilitzar al connectar als servidors de IRC"}. {"Erlang Jabber Server","Servidor Erlang Jabber"}. {"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):"}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Emplena el formulari per a buscar usuaris Jabber. Afegix * al final d'un camp per a buscar subcadenes."}. {"Friday","Divendres"}. {"From","De"}. {"From ~s","De ~s"}. {"Full Name","Nom complet"}. {"Get Number of Online Users","Obtenir Número d'Usuaris Connectats"}. {"Get Number of Registered Users","Obtenir Número d'Usuaris Registrats"}. {"Get User Last Login Time","Obtenir la última connexió d'Usuari"}. {"Get User Password","Obtenir Contrasenya d'usuari"}. {"Get User Statistics","Obtenir Estadístiques d'Usuari"}. {"Grant voice to this person?","Concedir veu a aquesta persona?"}. {"Group ","Grup "}. {"Groups","Grups"}. {"has been banned","Has sigut banejat"}. {"has been kicked because of an affiliation change","Has sigut expulsat a causa d'un canvi d'afiliació"}. {"has been kicked because of a system shutdown","Has sigut expulsat perquè el sistema s'ha apagat"}. {"has been kicked because the room has been changed to members-only","Has sigut expulsat perquè la sala ha canviat a sols membres"}. {"has been kicked","Has sigut expulsat"}. {" has set the subject to: "," ha posat l'assumpte: "}. {"Host","Host"}. {"If you don't see the CAPTCHA image here, visit the web page.","Si no veus la imatge CAPTCHA açí, visita la pàgina web."}. {"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 vols especificar codificacions de caràcters diferents per a cada servidor IRC emplena aquesta llista amb els valors amb el format '{\"servidor irc\", \"codificació\", port, \"contrasenya\"}'. Aquest servei utilitza per defecte la codificació \"~s\", port ~p, no contrasenya."}. {"Import Directory","Importar directori"}. {"Import File","Importar fitxer"}. {"Import user data from jabberd14 spool file:","Importar dades d'usuaris de l'arxiu de spool de jabberd14"}. {"Import User from File at ","Importa usuari des de fitxer en "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importar dades d'usuaris des d'un arxiu PIEFXIS (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","Canal d'IRC (no posis la primera #)"}. {"IRC server","Servidor d'IRC"}. {"IRC settings","Configuració d'IRC."}. {"IRC Transport","Transport a IRC"}. {"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"}. {"January","Gener"}. {"Join IRC channel","Entra a canal d'IRC"}. {"joins the room","Entrar a la sala"}. {"Join the IRC channel here.","Entra al canal d'IRC aquí."}. {"Join the IRC channel in this Jabber ID: ~s","Entra al canal d'IRC en aquesta Jabber ID: ~s"}. {"July","Juliol"}. {"June","Juny"}. {"Last Activity","Última activitat"}. {"Last login","Últim login"}. {"Last month","Últim mes"}. {"Last year","Últim any"}. {"leaves the room","Deixar la sala"}. {"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"}. {"Make room members-only","Crear una sala de \"només membres\""}. {"Make room moderated","Crear una sala moderada"}. {"Make room password protected","Crear una sala amb contrasenya"}. {"Make room persistent","Crear una sala persistent"}. {"Make room public searchable","Crear una sala pública"}. {"March","Març"}. {"Maximum Number of Occupants","Número màxim d'ocupants"}. {"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"}. {"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 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"}. {"No resource provided","Recurs no disponible"}. {"Not Found","No Trobat"}. {"Notify subscribers when items are removed from the node","Notificar subscriptors quan els elements són eliminats del node"}. {"Notify subscribers when the node configuration changes","Notificar subscriptors quan canvia la configuració del node"}. {"Notify subscribers when the node is deleted","Notificar subscriptors quan el node és eliminat"}. {"November","Novembre"}. {"Number of occupants","Número d'ocupants"}. {"Number of online users","Número d'usuaris connectats"}. {"Number of registered users","Número d'Usuaris Registrats"}. {"October","Octubre"}. {"Offline Messages:","Missatges fora de línia:"}. {"Offline Messages","Missatges offline"}. {"OK","Acceptar"}. {"Old Password:","Antiga contrasenya:"}. {"Online","Connectat"}. {"Online Users","Usuaris conectats"}. {"Online Users:","Usuaris en línia:"}. {"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"}. {"Owner privileges required","Es requerixen privilegis de propietari de la sala"}. {"Packet","Paquet"}. {"Password ~b","Contrasenya ~b"}. {"Password:","Contrasenya:"}. {"Password","Contrasenya"}. {"Password Verification:","Verificació de la Contrasenya:"}. {"Password Verification","Verificació de la Contrasenya"}. {"Path to Dir","Ruta al directori"}. {"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."}. {"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"}. {"Present real Jabber IDs to","Presentar Jabber ID's reals a"}. {"private, ","privat"}. {"Protocol","Protocol"}. {"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:"}. {"Registered Users","Usuaris registrats"}. {"Register","Registrar"}. {"Registration in mod_irc for ","Registre en mod_irc per a"}. {"Remote copy","Còpia remota"}. {"Remove All Offline Messages","Eliminar tots els missatges offline"}. {"Remove","Borrar"}. {"Remove User","Eliminar usuari"}. {"Replaced by new connection","Reemplaçat per una nova connexió"}. {"Resources","Recursos"}. {"Restart","Reiniciar"}. {"Restart Service","Reiniciar el Servei"}. {"Restore Backup from File at ","Restaura còpia de seguretat des del fitxer en "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Restaurar una còpia de seguretat binària després de reiniciar el ejabberd (requereix menys memòria:"}. {"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"}. {"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"}. {"Roster groups allowed to subscribe","Llista de grups que tenen permés subscriures"}. {"Roster","Llista de contactes"}. {"Roster of ","Llista de contactes de "}. {"Roster size","Tamany de la llista"}. {"RPC Call Error","Error de cridada RPC"}. {"Running Nodes","Nodes funcionant"}. {"~s access rule configuration","Configuració de les Regles d'Accés ~s"}. {"Saturday","Dissabte"}. {"Script check","Comprovar script"}. {"Search Results for ","Resultat de la búsqueda"}. {"Search users in ","Cerca usuaris en "}. {"Send announcement to all online users","Enviar anunci a tots els usuaris connectats"}. {"Send announcement to all online users on all hosts","Enviar anunci a tots els usuaris connectats a tots els hosts"}. {"Send announcement to all users","Enviar anunci a tots els usuaris"}. {"Send announcement to all users on all hosts","Enviar anunci a tots els usuaris de tots els hosts"}. {"September","Setembre"}. {"Server ~b","Servidor ~b"}. {"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"}. {"Show Integral Table","Mostrar Taula Integral"}. {"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 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"}. {"~s's Offline Messages Queue","~s's cua de missatges offline"}. {"Start","Iniciar"}. {"Start Modules at ","Iniciar mòduls en "}. {"Start Modules","Iniciar mòduls"}. {"Statistics","Estadístiques"}. {"Statistics of ~p","Estadístiques de ~p"}. {"Stop","Detindre"}. {"Stop Modules at ","Detindre mòduls en "}. {"Stop Modules","Parar mòduls"}. {"Stopped Nodes","Nodes parats"}. {"Storage Type","Tipus d'emmagatzematge"}. {"Store binary backup:","Guardar una còpia de seguretat binària:"}. {"Store plain text backup:","Guardar una còpia de seguretat en format de text pla:"}. {"Subject","Assumpte"}. {"Submit","Enviar"}. {"Submitted","Enviat"}. {"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: "}. {"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."}. {"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"}. {"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"}. {"Use of STARTTLS required","És obligatori utilitzar STARTTLS"}. {"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"}. {"User","Usuari"}. {"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"}. ejabberd-16.01/priv/msgs/fr.msg0000644000232200023220000007040712645157216016716 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Configuration d'accès"}. {"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"}. {"Add Jabber ID","Ajouter un Jabber ID"}. {"Add New","Ajouter"}. {"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"}. {"Allow users to change the subject","Autoriser les utilisateurs à changer le sujet"}. {"Allow users to query other users","Permettre aux utilisateurs d'envoyer des requêtes aux autres utilisateurs"}. {"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"}. {"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"}. {"Backup of ~p","Sauvegarde de ~p"}. {"Backup","Sauvegarde"}. {"Backup to File at ","Sauvegarde sur fichier sur "}. {"Bad format","Mauvais format"}. {"Birthday","Date d'anniversaire"}. {"CAPTCHA web page","Page web de CAPTCHA"}. {"Change Password","Modifier le mot de passe"}. {"Change User Password","Changer le mot de passe de l'utilisateur"}. {"Characters not allowed:","Caractères non-autorisés :"}. {"Chatroom configuration modified","Configuration du salon modifiée"}. {"Chatroom is created","Le salon de discussion est créé"}. {"Chatroom is destroyed","Le salon de discussion est détruit"}. {"Chatroom is started","Le salon de discussion a démarré"}. {"Chatroom is stopped","Le salon de discussion est stoppé"}. {"Chatrooms","Salons de discussion"}. {"Choose a username and password to register with this server","Choisissez un nom d'utilisateur et un mot de passe pour s'enregistrer sur ce serveur"}. {"Choose modules to stop","Sélectionnez les modules à arrêter"}. {"Choose storage type of tables","Choisissez un type de stockage pour les tables"}. {"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:"}. {"Connections parameters","Paramètres de connexion"}. {"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 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"}. {"Description:","Description :"}. {"Disc only copy","Copie sur disque uniquement"}. {"Displayed Groups:","Groupes affichés :"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Ne révélez votre mot de passe à personne, pas même l'administrateur de ce serveur."}. {"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"}. {"ejabberd Web Admin","Console Web d'administration de ejabberd"}. {"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]}"}. {"Enter nickname you want to register","Entrez le pseudo que vous souhaitez enregistrer"}. {"Enter path to backup file","Entrez le chemin vers le fichier de sauvegarde"}. {"Enter path to jabberd14 spool dir","Entrez le chemin vers le répertoire de spool jabberd14"}. {"Enter path to jabberd14 spool file","Entrez le chemin vers le fichier spool jabberd14"}. {"Enter path to text file","Entrez le chemin vers le fichier texte"}. {"Enter the text you see","Tapez le texte que vous voyez"}. {"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.","Entrez le nom d'utilisateur et les encodages que vous souhaitez utiliser pour vous connecter aux serveurs IRC. Appuyez sur 'Suivant' pour pour avoir d'autres champs à remplir. Appuyez sur 'Terminer' pour sauver les paramètres."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Entrez le nom d'utilisateur, les encodages, les ports et mots de passe que vous souhaitez utiliser pour vous connecter aux serveurs IRC"}. {"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"}. {"February","Février"}. {"Fill in fields to search for any matching Jabber User","Remplissez les champs pour rechercher un utilisateur Jabber"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Remplissez le formulaire pour recherche un utilisateur Jabber (Ajouter * à la fin du champ pour chercher n'importe quelle fin de chaîne"}. {"Friday","Vendredi"}. {"From","De"}. {"From ~s","De ~s"}. {"Full Name","Nom complet"}. {"Get Number of Online Users","Récupérer le nombre d'utilisateurs en ligne"}. {"Get Number of Registered Users","Récupérer le nombre d'utilisateurs enregistrés"}. {"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"}. {"has been kicked","a été expulsé"}. {"has been kicked because of an affiliation change","a été éjecté à cause d'un changement d'autorisation"}. {"has been kicked because of a system shutdown","a été éjecté en raison de l'arrêt du système"}. {"has been kicked because the room has been changed to members-only","a été éjecté car la salle est désormais réservée aux membres"}. {" has set the subject to: "," a changé le sujet pour: "}. {"Host","Serveur"}. {"If you don't see the CAPTCHA image here, visit the web page.","SI vous ne voyez pas l'image CAPTCHA ici, visitez la page web."}. {"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 vous voulez préciser différents ports, mots de passe, et encodages pour les serveurs IRC, remplissez cette liste avec des valeurs dans le format '{\"serveur irc\", \"encodage\", port, \"mot de passe\"}'. Par défaut ce service utilise l'encodage \"~s\", port ~p, mot de passe vide."}. {"Import Directory","Importer une répertoire"}. {"Import File","Importer un fichier"}. {"Import user data from jabberd14 spool file:","Importer des utilisateurs depuis un fichier spool Jabberd 1.4:"}. {"Import User from File at ","Importer un utilisateur depuis le fichier sur "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importer les données utilisateurs à partir d'un fichier PIEFXIS (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","Canal IRC (ne pas insérer le premier caractère #)"}. {"IRC server","Serveur IRC"}. {"IRC settings","Configuration IRC"}. {"IRC Transport","Passerelle IRC"}. {"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"}. {"January","Janvier"}. {"Join IRC channel","Rejoindre un canal IRC"}. {"joins the room","rejoint le salon"}. {"Join the IRC channel here.","Rejoindre un canal IRC ici"}. {"Join the IRC channel in this Jabber ID: ~s","Rejoindre un canal IRC avec ce Jabber ID: ~s"}. {"July","Juillet"}. {"June","Juin"}. {"Last Activity","Dernière Activité"}. {"Last login","Dernière connexion"}. {"Last month","Dernier mois"}. {"Last year","Dernière année"}. {"leaves the room","quitte le salon"}. {"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"}. {"Make room members-only","Réserver le salon aux membres uniquement"}. {"Make room moderated","Rendre le salon modéré"}. {"Make room password protected","Protéger le salon par mot de passe"}. {"Make room persistent","Rendre le salon persistant"}. {"Make room public searchable","Rendre le salon public"}. {"March","Mars"}. {"Maximum Number of Occupants","Nombre maximum d'occupants"}. {"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"}. {"Modules at ~p","Modules sur ~p"}. {"Modules","Modules"}. {"Monday","Lundi"}. {"Multicast","Multidiffusion"}. {"Multi-User Chat","Discussion de groupe"}. {"Name:","Nom :"}. {"Name","Nom"}. {"Never","Jamais"}. {"New Password:","Nouveau mot de passe:"}. {"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"}. {"No resource provided","Aucune ressource fournie"}. {"Not Found","NÅ“ud non trouvé"}. {"Notify subscribers when items are removed from the node","Avertir les abonnés lorsque des éléments sont supprimés sur le nÅ“ud"}. {"Notify subscribers when the node configuration changes","Avertir les abonnés lorsque la configuration du nÅ“ud change"}. {"Notify subscribers when the node is deleted","Avertir les abonnés lorsque le nÅ“ud est supprimé"}. {"November","Novembre"}. {"Number of occupants","Nombre d'occupants"}. {"Number of online users","Nombre d'utilisateurs en ligne"}. {"Number of registered users","Nombre d'utilisateurs enregistrés"}. {"October","Octobre"}. {"Offline Messages:","Messages en attente :"}. {"Offline Messages","Messages en attente"}. {"OK","OK"}. {"Old Password:","Ancien mot de passe:"}. {"Online","En ligne"}. {"Online Users:","Utilisateurs connectés:"}. {"Online Users","Utilisateurs en ligne"}. {"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"}. {"Owner privileges required","Les droits de propriétaire sont nécessaires"}. {"Packet","Paquet"}. {"Password ~b","Mot de passe ~b"}. {"Password:","Mot de passe:"}. {"Password","Mot de passe"}. {"Password Verification:","Vérification du mot de passe :"}. {"Password Verification","Vérification du mot de passe"}. {"Path to Dir","Chemin vers le répertoire"}. {"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."}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. {"Present real Jabber IDs to","Rendre le Jabber ID réel visible pour"}. {"private, ","privé"}. {"Protocol","Protocole"}. {"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:"}. {"Registered Users","Utilisateurs enregistrés"}. {"Register","Enregistrer"}. {"Registration in mod_irc for ","Enregistrement du mod_irc pour "}. {"Remote copy","Copie distante"}. {"Remove All Offline Messages","Effacer tous les messages hors ligne"}. {"Remove","Enlever"}. {"Remove User","Supprimer l'utilisateur"}. {"Replaced by new connection","Remplacé par une nouvelle connexion"}. {"Resources","Ressources"}. {"Restart","Redémarrer"}. {"Restart Service","Redémarrer le service"}. {"Restore Backup from File at ","Restaurer la sauvegarde depuis le fichier sur "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Restauration de la sauvegarde binaire après redémarrage (nécessite moins de mémoire):"}. {"Restore binary backup immediately:","Restauration immédiate d'une sauvegarde binaire:"}. {"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"}. {"Roster groups allowed to subscribe","Groupes de liste de contact autorisés à s'abonner"}. {"Roster","Liste de contacts"}. {"Roster of ","Liste de contact de "}. {"Roster size","Taille de la liste de contacts"}. {"RPC Call Error","Erreur d'appel RPC"}. {"Running Nodes","Noeuds actifs"}. {"~s access rule configuration","Configuration des règles d'accès ~s"}. {"Saturday","Samedi"}. {"Script check","Validation du script"}. {"Search Results for ","Résultats de recherche pour "}. {"Search users in ","Rechercher des utilisateurs "}. {"Send announcement to all online users","Envoyer l'annonce à tous les utilisateurs en ligne"}. {"Send announcement to all online users on all hosts","Envoyer l'annonce à tous les utilisateurs en ligne sur tous les serveurs"}. {"Send announcement to all users","Envoyer l'annonce à tous les utilisateurs"}. {"Send announcement to all users on all hosts","Envoyer une annonce à tous les utilisateurs de tous les domaines"}. {"September","Septembre"}. {"Server ~b","Serveur ~b"}. {"Server:","Serveur :"}. {"Set message of the day and send to online users","Définir le message du jour et l'envoyer aux utilisateurs en ligne"}. {"Set message of the day on all hosts and send to online users","Définir le message du jour pour tous domaines et l'envoyer aux utilisateurs en ligne"}. {"Shared Roster Groups","Groupes de liste de contacts partagée"}. {"Show Integral Table","Montrer la table intégralement"}. {"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 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"}. {"~s's Offline Messages Queue","~s messages en file d'attente"}. {"Start","Démarrer"}. {"Start Modules at ","Démarrer les modules sur "}. {"Start Modules","Modules de démarrage"}. {"Statistics of ~p","Statistiques de ~p"}. {"Statistics","Statistiques"}. {"Stop","Arrêter"}. {"Stop Modules at ","Arrêter les modules sur "}. {"Stop Modules","Modules d'arrêt"}. {"Stopped Nodes","Noeuds arrêtés"}. {"Storage Type","Type de stockage"}. {"Store binary backup:","Sauvegarde binaire:"}. {"Store plain text backup:","Sauvegarde texte:"}. {"Subject","Sujet"}. {"Submit","Soumettre"}. {"Submitted","Soumis"}. {"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 :"}. {"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."}. {"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"}. {"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"}. {"Update message of the day (don't send)","Mise à jour du message du jour (pas d'envoi)"}. {"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 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"}. {"User","Utilisateur"}. {"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"}. ejabberd-16.01/priv/msgs/vi.msg0000644000232200023220000004456212645157216016730 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Cấu Hình Truy Cập"}. {"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"}. {"Add Jabber ID","Thêm Jabber ID"}. {"Add New","Thêm Má»›i"}. {"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"}. {"Allow users to send invites","Cho phép ngưá»i sá»­ dụng gá»­i lá»i má»i"}. {"Allow users to send private messages","Cho phép ngưá»i sá»­ dụng gá»­i thư riêng"}. {"All Users","Tất Cả Ngưá»i Sá»­ Dụng"}. {"Announcements","Thông báo"}. {"anyone","bất kỳ ai"}. {"April","Tháng Tư"}. {"August","Tháng Tám"}. {"Backup Management","Quản lý Sao Lưu Dá»± Phòng"}. {"Backup","Sao lưu dá»± phòng"}. {"Backup to File at ","Sao lưu dá»± phòng ra Tập Tin tại"}. {"Bad format","Äịnh dạng há»ng"}. {"Birthday","Ngày sinh"}. {"Change Password","Thay Äổi Mật Khẩu"}. {"Change User Password","Thay Äổi Mật Khẩu Ngưá»i Sá»­ Dụng"}. {"Chatroom configuration modified","Cấu hình phòng trò chuyện được chỉnh sá»­a"}. {"Chatrooms","Phòng trò chuyện"}. {"Choose a username and password to register with this server","Chá»n má»™t tên truy cập và mật khẩu để đăng ký vá»›i máy chá»§ này"}. {"Choose modules to stop","Chá»n môđun để dừng"}. {"Choose storage type of tables","Chá»n loại bảng lưu trữ"}. {"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"}. {"CPU Time:","Thá»i Gian CPU:"}. {"Database","CÆ¡ sở dữ liệu"}. {"Database Tables Configuration at ","Cấu Hình Bảng CÆ¡ Sở Dữ Liệu tại"}. {"December","Tháng Mưá»i Hai"}. {"Default users as participants","Ngưá»i sá»­ dụng mặc định là ngưá»i tham dá»±"}. {"Delete message of the day on all hosts","Xóa thư trong ngày trên tất cả các máy chá»§"}. {"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"}. {"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ả:"}. {"Disc only copy","Chỉ sao chép vào đĩa"}. {"Displayed Groups:","Nhóm được hiển thị:"}. {"Dump Backup to Text File at ","Kết Xuất Sao Lưu ra Tập Tin Văn Bản tại"}. {"Dump to Text File","Kết xuất ra Tập Tin Văn Bản"}. {"Edit Properties","Chỉnh Sá»­a Thuá»™c Tính"}. {"ejabberd IRC module","Môdun ejabberd IRC Bản quyá»n"}. {"ejabberd MUC module","Môdun ejabberd MUC Bản quyá»n"}. {"ejabberd Publish-Subscribe module","Môdun ejabberd Xuất Bản-Äăng Ký Bản quyá»n"}. {"ejabberd SOCKS5 Bytestreams module","Môdun SOCKS5 Bytestreams Bản quyá»n"}. {"ejabberd vCard module","Môdun ejabberd vCard Bản quyá»n"}. {"Email","Email"}. {"Enable logging","Cho phép ghi nhật ký"}. {"End User Session","Kết Thúc Phiên Giao Dịch Ngưá»i Sá»­ Dụng"}. {"Enter list of {Module, [Options]}","Nhập danh sách {Môđun, [Các Tùy Chá»n]}"}. {"Enter nickname you want to register","Nhập bí danh bạn muốn đăng ký"}. {"Enter path to backup file","Nhập đưá»ng dẫn đến tập tin sao lưu dá»± phòng"}. {"Enter path to jabberd14 spool dir","Nhập đưá»ng dẫn đến thư mục spool jabberd14"}. {"Enter path to jabberd14 spool file","Nhập đưá»ng dẫn đến tập tin spool jabberd14"}. {"Enter path to text file","Nhập đưá»ng dẫn đến tập tin văn bản"}. {"Erlang Jabber Server","Erlang Jabber Server Bản quyá»n"}. {"Family Name","Há»"}. {"February","Tháng Hai"}. {"Fill in fields to search for any matching Jabber User","Ä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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Ä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)"}. {"Friday","Thứ Sáu"}. {"From ~s","Nhận từ ~s"}. {"From","Từ"}. {"Full Name","Tên Äầy Äá»§"}. {"Get Number of Online Users","Nhận Số Ngưá»i Sá»­ Dụng Trá»±c Tuyến"}. {"Get Number of Registered Users","Nhận Số Ngưá»i Sá»­ Dụng Äã Äăng Ký"}. {"Get User Last Login Time","Nhận Thá»i Gian Äăng Nhập Cuối Cùng Cá»§a Ngưá»i Sá»­ Dụng"}. {"Get User Password","Nhận Mật Khẩu Ngưá»i Sá»­ Dụng"}. {"Get User Statistics","Nhận Thông Tin Thống Kê Ngưá»i Sá»­ Dụng"}. {"Group ","Nhóm "}. {"Groups","Nhóm"}. {"has been banned","đã bị cấm"}. {"has been kicked","đã bị đẩy ra khá»i"}. {" has set the subject to: "," đã đặt chá»§ đỠthành: "}. {"Host","Máy chá»§"}. {"Import Directory","Nhập Thư Mục"}. {"Import File","Nhập Tập Tin"}. {"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"}. {"joins the room","tham gia phòng này"}. {"July","Tháng Bảy"}. {"June","Tháng Sáu"}. {"Last Activity","Hoạt Äá»™ng Cuối Cùng"}. {"Last login","Äăng nhập lần cuối"}. {"Last month","Tháng trước"}. {"Last year","Năm trước"}. {"leaves the room","rá»i khá»i phòng này"}. {"Listened Ports at ","Cổng Liên Lạc tại"}. {"Listened Ports","Cổng Kết Nối"}. {"List of modules to start","Danh sách các môđun khởi động"}. {"Low level update script","Lệnh cập nhật mức độ thấp"}. {"Make participants list public","Tạo danh sách ngưá»i tham dá»± công khai"}. {"Make room members-only","Tạo phòng chỉ cho phép tư cách thành viên tham gia"}. {"Make room password protected","Tạo phòng được bảo vệ bằng mật khẩu"}. {"Make room persistent","Tạo phòng bá»n vững"}. {"Make room public searchable","Tạo phòng có thể tìm kiếm công khai"}. {"March","Tháng Ba"}. {"Maximum Number of Occupants","Số Lượng Ngưá»i Tham Dá»± Tối Äa"}. {"Max # of items to persist","Số mục tối Ä‘a để lưu trữ"}. {"Max payload size in bytes","Kích thước dung lượng byte tối Ä‘a"}. {"May","Tháng Năm"}. {"Members:","Thành viên:"}. {"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"}. {"Monday","Thứ Hai"}. {"Name:","Tên:"}. {"Name","Tên"}. {"Never","Không bao giá»"}. {"Nickname","Bí danh"}. {"Nickname Registration at ","Äăng Ký Bí Danh tại"}. {"Nickname ~s does not exist in the room","Bí danh ~s không tồn tại trong phòng này"}. {"No body provided for announce message","Không có ná»™i dung trong thư thông báo"}. {"No Data","Không Dữ Liệu"}. {"Node ID","ID Nút"}. {"Node not found","Nút không tìm thấy"}. {"Nodes","Nút"}. {"No limit","Không giá»›i hạn"}. {"None","Không có"}. {"No resource provided","Không có nguồn lá»±c cung cấp"}. {"Notify subscribers when items are removed from the node","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"}. {"Notify subscribers when the node configuration changes","Thông báo cho ngưá»i đăng ký khi nào cấu hình nút thay đổi"}. {"Notify subscribers when the node is deleted","Thông báo cho ngưá»i đăng ký khi nào nút bị xóa bá»"}. {"November","Tháng Mưá»i Má»™t"}. {"Number of occupants","Số ngưá»i tham dá»±"}. {"Number of online users","Số ngưá»i sá»­ dụng trá»±c tuyến"}. {"Number of registered users","Số ngưá»i sá»­ dụng đã đăng ký"}. {"October","Tháng Mưá»i"}. {"Offline Messages:","Thư Ngoại Tuyến:"}. {"Offline Messages","Thư Ngoại Tuyến"}. {"OK","OK"}. {"Online","Trá»±c tuyến"}. {"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"}. {"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"}. {"Password Verification","Kiểm Tra Mật Khẩu"}. {"Path to Dir","ÄÆ°á»ng Dẫn đến Thư Mục"}. {"Path to File","ÄÆ°á»ng dẫn đến Tập Tin"}. {"Pending","Chá»"}. {"Period: ","Giai Ä‘oạn: "}. {"Persist items to storage","Những mục cần để lưu trữ"}. {"Ping","Ping"}. {"Pong","Pong"}. {"Port","Cổng"}. {"Present real Jabber IDs to","Jabber ID thá»±c tế hiện hành đến"}. {"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 "}. {"Remote copy","Sao chép từ xa"}. {"Remove","Gỡ bá»"}. {"Remove User","Gỡ Bá» Ngưá»i Sá»­ Dụng"}. {"Replaced by new connection","ÄÆ°á»£c thay thế bởi kết nối má»›i"}. {"Resources","Nguồn tài nguyên"}. {"Restart","Khởi động lại"}. {"Restart Service","Khởi Äá»™ng Lại Dịch Vụ"}. {"Restore Backup from File at ","Phục hồi Sao Lưu từ Tập Tin tại "}. {"Restore binary backup after next ejabberd restart (requires less memory):","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):"}. {"Restore binary backup immediately:","Khôi phục bản sao lưu dá»± phòng dạng nhị phận ngay lập tức:"}. {"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 "}. {"Roster size","Kích thước bảng phân công"}. {"RPC Call Error","Lá»—i Gá»i RPC"}. {"Running Nodes","Nút Hoạt Äá»™ng"}. {"~s access rule configuration","~s cấu hình quy tắc truy cập"}. {"Saturday","Thứ Bảy"}. {"Script check","Lệnh kiểm tra"}. {"Search Results for ","Kết Quả Tìm Kiếm cho "}. {"Search users in ","Tìm kiếm ngưá»i sá»­ dụng trong"}. {"Send announcement to all online users","Gá»­i thông báo đến tất cả ngưá»i sá»­ dụng trá»±c tuyến"}. {"Send announcement to all online users on all hosts","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á»§"}. {"Send announcement to all users","Gá»­i thông báo đến tất cả ngưá»i sá»­ dụng"}. {"Send announcement to all users on all hosts","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á»§"}. {"September","Tháng Chín"}. {"Set message of the day and send to online users","Tạo lập thư trong ngày và gá»­i đến những ngưá»i sá»­ dụng trá»±c tuyến"}. {"Set message of the day on all hosts and send to online users","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"}. {"Shared Roster Groups","Nhóm Phân Công Chia Sẻ"}. {"Show Integral Table","Hiển Thị Bảng Äầy Äá»§"}. {"Show Ordinary Table","Hiển Thị Bảng Thưá»ng"}. {"Shut Down Service","Tắt Dịch Vụ"}. {"~s invites you to the room ~s","~s má»i bạn vào phòng ~s"}. {"Specify the access model","Xác định mô hình truy cập"}. {"Specify the publisher model","Xác định mô hình nhà xuất bản"}. {"~s's Offline Messages Queue","~s's Danh Sách Chá» Thư Ngoại Tuyến"}. {"Start","Khởi động"}. {"Start Modules at ","Môđun Khởi Äá»™ng tại "}. {"Start Modules","Môđun Khởi Äá»™ng"}. {"Statistics of ~p","Thống kê vá» ~p"}. {"Statistics","Số liệu thống kê"}. {"Stop","Dừng"}. {"Stop Modules at ","Môđun Dừng tại"}. {"Stop Modules","Môđun Dừng"}. {"Stopped Nodes","Nút Dừng"}. {"Storage Type","Loại Lưu Trữ"}. {"Store binary backup:","Lưu dữ liệu sao lưu dạng nhị phân:"}. {"Store plain text backup:","Khôi phục bản sao lưu dá»± phòng thuần văn bản"}. {"Subject","Tiêu Ä‘á»"}. {"Submit","Gá»­i"}. {"Submitted","Äã gá»­i"}. {"Subscriber Address","Äịa Chỉ Ngưá»i Äăng Ký"}. {"Subscription","Äăng ký"}. {"Sunday","Chá»§ Nhật"}. {"the password is","mật khẩu là"}. {"Thursday","Thứ Năm"}. {"Time delay","Thá»i gian trì hoãn"}. {"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:"}. {"Transactions Restarted:","Giao Dịch Khởi Äá»™ng Lại:"}. {"Tuesday","Thứ Ba"}. {"Update","Cập Nhật"}. {"Update message of the day (don't send)","Cập nhật thư trong ngày (không gá»­i)"}. {"Update message of the day on all hosts (don't send)","Cập nhật thư trong ngày trên tất cả các máy chá»§ (không gá»­i)"}. {"Update plan","Kế hoạch cập nhật"}. {"Update script","Cập nhận lệnh"}. {"Uptime:","Thá»i gian tải lên:"}. {"Use of STARTTLS required","Yêu cầu sá»­ dụng STARTTLS"}. {"User Management","Quản Lý Ngưá»i Sá»­ Dụng"}. {"User","Ngưá»i sá»­ dụng"}. {"Users Last Activity","Hoạt Äá»™ng Cuối Cùng Cá»§a Ngưá»i Sá»­ Dụng"}. {"Users","Ngưá»i sá»­ dụng"}. {"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á»."}. ejabberd-16.01/priv/msgs/ja.msg0000644000232200023220000007566312645157216016712 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"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","Jabber ID を追加"}. {"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?","ã“ã® Jabber ID ã«ã€ã“ã® 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 voice requests","å‚è´è€…ã«ã‚ˆã‚‹ç™ºè¨€æ¨©ã®è¦æ±‚を許å¯"}. {"All Users","全ユーザー"}. {"Announcements","アナウンス"}. {"anyone","誰ã«ã§ã‚‚"}. {"A password is required to enter this room","ã“ã®ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã«å…¥ã‚‹ã«ã¯ãƒ‘スワードãŒå¿…è¦ã§ã™"}. {"April","4月"}. {"August","8月"}. {"Backup","ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—"}. {"Backup Management","ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—管ç†"}. {"Backup of ~p","ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—: ~p"}. {"Backup to File at ","ファイルã«ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—: "}. {"Bad format","䏿­£ãªãƒ•ォーマット"}. {"Birthday","誕生日"}. {"CAPTCHA web page","CAPTCHA ウェブページ"}. {"Change Password","パスワードを変更"}. {"Change User Password","パスワードを変更"}. {"Characters not allowed:","使用ã§ããªã„文字:"}. {"Chatroom configuration modified","ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®è¨­å®šãŒå¤‰æ›´ã•れã¾ã—ãŸ"}. {"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","åœæ­¢ã™ã‚‹ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’é¸æŠž"}. {"Choose storage type of tables","テーブルã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã‚¿ã‚¤ãƒ—ã‚’é¸æŠž"}. {"Choose whether to approve this entity's subscription.","ã“ã®ã‚¨ãƒ³ãƒˆãƒªã‚’承èªã™ã‚‹ã‹ã©ã†ã‹ã‚’é¸æŠžã—ã¦ãã ã•ã„"}. {"City","都é“府県"}. {"Commands","コマンド"}. {"Conference room does not exist","会議室ã¯å­˜åœ¨ã—ã¾ã›ã‚“"}. {"Configuration of room ~s","ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ  ~s ã®è¨­å®š"}. {"Configuration","設定"}. {"Connected Resources:","接続リソース:"}. {"Connections parameters","接続パラメーター"}. {"Country","国"}. {"CPU Time:","CPU時間:"}. {"Database","データーベース"}. {"Database Tables at ~p","データーベーステーブル: ~p"}. {"Database Tables Configuration at ","データーベーステーブル設定 "}. {"December","12月"}. {"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","イベント通知ã¨åŒæ™‚ã«ãƒšã‚¤ãƒ­ãƒ¼ãƒ‰ã‚’é…é€ã™ã‚‹"}. {"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","テキストファイルã«å‡ºåŠ›"}. {"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]}","{モジュール, [オプション]}ã®ãƒªã‚¹ãƒˆã‚’入力ã—ã¦ãã ã•ã„"}. {"Enter nickname you want to register","登録ã™ã‚‹ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã‚’入力ã—ã¦ãã ã•ã„"}. {"Enter path to backup file","ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルã®ãƒ‘スを入力ã—ã¦ãã ã•ã„"}. {"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 サーãƒãƒ¼ã«æŽ¥ç¶šå…ˆã™ã‚‹ãŸã‚ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨æ–‡å­—エンコーディングを入力ã—ã¦ãã ã•ã„。'Next' を押ã—ã¦æ¬¡ã®é …ç›®ã«é€²ã¿ã¾ã™ã€‚'Complete' を押ã™ã¨è¨­å®šãŒä¿å­˜ã•れã¾ã™ã€‚"}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","IRC サーãƒãƒ¼ã«æŽ¥ç¶šå…ˆã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼åã€æ–‡å­—エンコーディングã€ãƒãƒ¼ãƒˆã€ãƒ‘スワードを入力ã—ã¦ãã ã•ã„"}. {"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"}. {"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","項目を入力ã—ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’検索ã—ã¦ãã ã•ã„"}. {"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","差出人"}. {"Full Name","æ°å"}. {"Get Number of Online Users","オンラインユーザー数をå–å¾—"}. {"Get Number of Registered Users","登録ユーザー数をå–å¾—"}. {"Get User Last Login Time","最終ログイン時間をå–å¾—"}. {"Get User Password","パスワードをå–å¾—"}. {"Get User Statistics","ユーザー統計をå–å¾—"}. {"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","ホスト"}. {"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 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 ファイルã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’インãƒãƒ¼ãƒˆ"}. {"Improper message type","誤ã£ãŸãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚¿ã‚¤ãƒ—ã§ã™"}. {"Incorrect password","パスワードãŒé•ã„ã¾ã™"}. {"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","ã¯åå‰ã‚’変更ã—ã¾ã—ãŸ: "}. {"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 ã¯ç„¡åйã§ã™"}. {"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月"}. {"June","6月"}. {"Last Activity","活動履歴"}. {"Last login","最終ログイン"}. {"Last month","先月"}. {"Last year","去年"}. {"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 ã§ä¿è­·"}. {"Make room members-only","ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’メンãƒãƒ¼ã®ã¿ã«åˆ¶é™"}. {"Make room moderated","ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’モデレート化"}. {"Make room password protected","ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’パスワードã§ä¿è­·"}. {"Make room persistent","ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’永続化"}. {"Make room public searchable","ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’検索å¯"}. {"March","3月"}. {"Maximum Number of Occupants","最大在室者数"}. {"Max # of items to persist","ã‚¢ã‚¤ãƒ†ãƒ ã®æœ€å¤§ä¿å­˜æ•°"}. {"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","モジュール"}. {"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 ã¯ã“ã®ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã«ã„ã¾ã›ã‚“"}. {"No body provided for announce message","アナウンスメッセージã¯ã‚りã¾ã›ã‚“ã§ã—ãŸ"}. {"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","ノード設定ã«å¤‰æ›´ãŒã‚ã£ãŸæ™‚ã«è³¼èª­è€…ã¸é€šçŸ¥ã™ã‚‹"}. {"Notify subscribers when the node is deleted","ノードãŒå‰Šé™¤ã•ã‚ŒãŸæ™‚ã«è³¼èª­è€…ã¸é€šçŸ¥ã™ã‚‹"}. {"November","11月"}. {"Number of occupants","åœ¨å®¤è€…ã®æ•°"}. {"Number of online users","オンラインユーザー数"}. {"Number of registered users","登録ユーザー数"}. {"October","10月"}. {"Offline Messages:","オフラインメッセージ:"}. {"Offline Messages","オフラインメッセージ"}. {"OK","OK"}. {"Old Password:","å¤ã„パスワード:"}. {"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","モデレーターã®ã¿ãŒãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®ä»¶åを変更ã§ãã¾ã™"}. {"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 コãƒã‚¯ã‚·ãƒ§ãƒ³"}. {"Owner privileges required","ä¸»å®°è€…ã®æ¨©é™ãŒå¿…è¦ã§ã™"}. {"Packet","パケット"}. {"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 データーベースã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—を別ã«è¡Œã†å¿…è¦ãŒã‚りã¾ã™ã€‚"}. {"Please, wait for a while before sending new voice request","æ–°ã—ã„発言権ã®è¦æ±‚ã‚’é€ã‚‹ã¾ã§å°‘ã—é–“ã‚’ãŠã„ã¦ãã ã•ã„"}. {"Pong","Pong"}. {"Port","ãƒãƒ¼ãƒˆ"}. {"Port ~b","ãƒãƒ¼ãƒˆ ~b"}. {"Present real Jabber IDs to","本当㮠Jabber ID を公開"}. {"private, ","プライベートã€"}. {"Protocol","プロトコル"}. {"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:","登録ユーザー:"}. {"Registered Users","登録ユーザー"}. {"Register","登録"}. {"Registration in mod_irc for ","mod_irc ã§ã®ç™»éŒ²: "}. {"Remote copy","リモートコピー"}. {"Remove All Offline Messages","ã™ã¹ã¦ã®ã‚ªãƒ•ラインメッセージを削除"}. {"Remove User","ユーザーを削除"}. {"Remove","削除"}. {"Replaced by new connection","æ–°ã—ã„コãƒã‚¯ã‚·ãƒ§ãƒ³ã«ã‚ˆã£ã¦ç½®ãæ›ãˆã‚‰ã‚Œã¾ã—ãŸ"}. {"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:","ç›´ã¡ã«ãƒ—レーンテキストãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‹ã‚‰ãƒªã‚¹ãƒˆã‚¢:"}. {"Room Configuration","ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®è¨­å®š"}. {"Room creation is denied by service policy","サービスãƒãƒªã‚·ãƒ¼ã«ã‚ˆã£ã¦ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®ä½œæˆãŒç¦æ­¢ã•れã¦ã„ã¾ã™"}. {"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 ","æ¤œç´¢çµæžœ: "}. {"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","9月"}. {"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 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","モジュールを起動"}. {"Start","é–‹å§‹"}. {"Statistics of ~p","~p ã®çµ±è¨ˆ"}. {"Statistics","統計"}. {"Stop Modules at ","ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’åœæ­¢: "}. {"Stop Modules","ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’åœæ­¢"}. {"Stopped Nodes","åœæ­¢ãƒŽãƒ¼ãƒ‰"}. {"Stop","åœæ­¢"}. {"Storage Type","ストレージタイプ"}. {"Store binary backup:","ãƒã‚¤ãƒŠãƒªãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‚’ä¿å­˜:"}. {"Store plain text backup:","プレーンテキストãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‚’ä¿å­˜:"}. {"Subject","ä»¶å"}. {"Submitted","é€ä¿¡å®Œäº†"}. {"Submit","é€ä¿¡"}. {"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: ","アカウントã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: "}. {"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 (JabberID) 㯠username@server ã®ã‚ˆã†ãªå½¢å¼ã«ãªã‚Šã¾ã™ã€‚注æ„事項ã©ãŠã‚Šã€æ­£ã—ã項目を記入ã—ã¦ãã ã•ã„。"}. {"This page allows to unregister a Jabber account in this Jabber server.","ã“ã“ã¯ã“ã® 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","削除"}. {"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","ユーザー"}. {"User JID","ユーザー JID"}. {"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"}. ejabberd-16.01/priv/msgs/gl.msg0000644000232200023220000005304312645157216016706 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Configuración de accesos"}. {"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"}. {"Add Jabber ID","Engadir ID Jabber"}. {"Add New","Engadir novo"}. {"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?"}. {"Allow users to change the subject","Permitir aos usuarios cambiar o asunto"}. {"Allow users to query other users","Permitir aos usuarios consultar a outros usuarios"}. {"Allow users to send invites","Permitir aos usuarios enviar invitacións"}. {"Allow users to send private messages","Permitir aos usuarios enviar mensaxes privadas"}. {"Allow visitors to change nickname","Permitir aos visitantes cambiarse o alcume"}. {"Allow visitors to send status text in presence updates","Permitir aos visitantes enviar texto de estado nas actualizacións depresenza"}. {"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"}. {"Backup Management","Xestión de copia de seguridade"}. {"Backup to File at ","Copia de seguridade de arquivos en "}. {"Bad format","Mal formato"}. {"Birthday","Aniversario"}. {"Change Password","Cambiar contrasinal"}. {"Change User Password","Cambiar contrasinal de usuario"}. {"Chatroom configuration modified","Configuración de la sala modificada"}. {"Chatrooms","Salas de charla"}. {"Choose a username and password to register with this server","Escolle un nome de usuario e contrasinal para rexistrarche neste servidor"}. {"Choose modules to stop","Selecciona módulos a deter"}. {"Choose storage type of tables","Selecciona tipo de almacenamento das táboas"}. {"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:"}. {"Connections parameters","Parámetros de conexiones"}. {"Country","País"}. {"CPU Time:","Tempo consumido de CPU:"}. {"Database","Base de datos"}. {"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 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"}. {"Delete User","Borrar usuario"}. {"Deliver event notifications","Entregar notificacións de eventos"}. {"Deliver payloads with event notifications","Enviar payloads xunto coas notificacións de eventos"}. {"Description:","Descrición:"}. {"Disc only copy","Copia en disco soamente"}. {"Displayed Groups:","Mostrar grupos:"}. {"Dump Backup to Text File at ","Exporta copia de seguridade a ficheiro de texto en "}. {"Dump to Text File","Exportar a ficheiro de texto"}. {"Edit Properties","Editar propiedades"}. {"ejabberd IRC module","Módulo de IRC para ejabberd"}. {"ejabberd MUC module","Módulo de MUC para ejabberd"}. {"ejabberd Publish-Subscribe module","Módulo de Publicar-Subscribir de ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","Módulo vCard para ejabberd"}. {"ejabberd Web Admin","Ejabberd Administrador Web"}. {"Elements","Elementos"}. {"Email","Email"}. {"Enable logging","Gardar históricos"}. {"Encoding for server ~b","Codificación de servidor ~b"}. {"End User Session","Pechar sesión de usuario"}. {"Enter list of {Module, [Options]}","Introduce lista de {Módulo, [Opcións]}"}. {"Enter nickname you want to register","Introduce o alcume que queiras rexistrar"}. {"Enter path to backup file","Introduce ruta ao ficheiro de copia de seguridade"}. {"Enter path to jabberd14 spool dir","Introduce a ruta ao directorio de jabberd14 spools"}. {"Enter path to jabberd14 spool file","Introduce ruta ao ficheiro jabberd14 spool"}. {"Enter path to text file","Introduce ruta ao ficheiro de texto"}. {"Enter the text you see","Introduza o texto que ves"}. {"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.","Introduce o nome de usuario e codificaciones de carácteres que queiras usar ao conectar nos servidores de IRC. Presione 'Siguiente' para obtener más campos para rellenar Presione 'completo' para guardar axustes."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Introduza o nome de usuario, codificaciones de carácter, portos e contrasinal que pretende utilizar a conectar a servidores de IRC"}. {"Erlang Jabber Server","Servidor Jabber en Erlang"}. {"Error","Erro"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Exemplo: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS (XEP-0227):"}. {"Family Name","Apelido"}. {"February","Febreiro"}. {"Fill in fields to search for any matching Jabber User","Rechea campos para buscar usuarios Jabber que concuerden"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Enche o formulario para buscar usuarios Jabber. Engade * ao final dun campo para buscar subcadenas."}. {"Friday","Venres"}. {"From","De"}. {"From ~s","De ~s"}. {"Full Name","Nome completo"}. {"Get Number of Online Users","Ver número de usuarios conectados"}. {"Get Number of Registered Users","Ver número de usuarios rexistrados"}. {"Get User Last Login Time","Ver data da última conexión de usuario"}. {"Get User Password","Ver contrasinal de usuario"}. {"Get User Statistics","Ver estatísticas de usuario"}. {"Group ","Grupo "}. {"Groups","Grupos"}. {"has been banned","foi bloqueado"}. {"has been kicked because of an affiliation change","foi expulsado debido a un cambio de afiliación"}. {"has been kicked because of a system shutdown","foi expulsado por mor dun sistema de peche"}. {"has been kicked because the room has been changed to members-only","foi expulsado, porque a sala cambiouse a só-membros"}. {"has been kicked","foi expulsado"}. {" has set the subject to: "," puxo o asunto: "}. {"Host","Host"}. {"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 quere especificar codificaciones de caracteres diferentes, contrasinal ou servidor IRC rechea esta lista con valores no formato '{\"servidor irc\", \"codificación\", \"porto\", \"contrasinal\"}'. Este servizo utiliza por defecto a codificación \"~s\", porto ~p, sen contrasinal."}. {"Import Directory","Importar directorio"}. {"Import File","Importar ficheiro"}. {"Import user data from jabberd14 spool file:","Importar usuario de fichero spool de jabberd14:"}. {"Import User from File at ","Importa usuario desde ficheiro en "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importar usuarios desde un fichero PIEFXIS"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","Canle de IRC (non poñer o primeiro #)"}. {"IRC server","Servidor IRC"}. {"IRC settings","IRC axustes"}. {"IRC Transport","Transporte IRC"}. {"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"}. {"Join IRC channel","Entrar en canle IRC"}. {"joins the room","entra en la sala"}. {"Join the IRC channel here.","Únete á canle de IRC aquí."}. {"Join the IRC channel in this Jabber ID: ~s","Únete á canle de IRC con este IDE de Jabber: ~s"}. {"July","Xullo"}. {"June","Xuño"}. {"Last Activity","Última actividade"}. {"Last login","Última conexión"}. {"Last month","Último mes"}. {"Last year","Último ano"}. {"leaves the room","sae da sala"}. {"Listened Ports at ","Portos de escoita en "}. {"Listened Ports","Portos de escoita"}. {"List of modules to start","Lista de módulos a iniciar"}. {"Low level update script","Script de actualización a baixo nivel"}. {"Make participants list public","A lista de participantes é pública"}. {"Make room CAPTCHA protected","Protexer a sala con CAPTCHA"}. {"Make room members-only","Sala só para membros"}. {"Make room moderated","Facer sala moderada"}. {"Make room password protected","Protexer a sala con contrasinal"}. {"Make room persistent","Sala permanente"}. {"Make room public searchable","Sala publicamente visible"}. {"March","Marzo"}. {"Maximum Number of Occupants","Número máximo de ocupantes"}. {"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"}. {"Modules","Módulos"}. {"Monday","Luns"}. {"Name:","Nome:"}. {"Name","Nome"}. {"Never","Nunca"}. {"Nickname","Alcume"}. {"Nickname Registration at ","Rexistro do alcume en "}. {"Nickname ~s does not exist in the room","O alcume ~s non existe na sala"}. {"No body provided for announce message","Non se proporcionou corpo de mensaxe para o anuncio"}. {"No Data","Sen datos"}. {"Node ID","Nodo IDE"}. {"Node not found","Nodo non atopado"}. {"Nodes","Nodos"}. {"No limit","Sen límite"}. {"None","Ningún"}. {"No resource provided","Non se proporcionou recurso"}. {"Not Found","Non atopado"}. {"Notify subscribers when items are removed from the node","Notificar subscriptores cando os elementos bórranse do nodo"}. {"Notify subscribers when the node configuration changes","Notificar subscriptores cando cambia a configuración do nodo"}. {"Notify subscribers when the node is deleted","Notificar subscriptores cando o nodo bórrase"}. {"November","Novembro"}. {"Number of occupants","Número de ocupantes"}. {"Number of online users","Número de usuarios conectados"}. {"Number of registered users","Número de usuarios rexistrados"}. {"October","Outubro"}. {"Offline Messages","Mensaxes diferidas"}. {"Offline Messages:","Mensaxes sen conexión:"}. {"OK","Aceptar"}. {"Online","Conectado"}. {"Online Users:","Usuarios conectados:"}. {"Online Users","Usuarios conectados"}. {"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"}. {"Owner privileges required","Requírense privilexios de propietario da sala"}. {"Packet","Paquete"}. {"Password ~b","Contrasinal ~b"}. {"Password:","Contrasinal:"}. {"Password","Contrasinal"}. {"Password Verification","Verificación da contrasinal"}. {"Path to Dir","Ruta ao directorio"}. {"Path to File","Ruta ao ficheiro"}. {"Pending","Pendente"}. {"Period: ","Periodo: "}. {"Persist items to storage","Persistir elementos ao 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 conta que estas opcións só farán copia de seguridade da base de datos 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."}. {"Pong","Pong"}. {"Port ~b","Porto ~b"}. {"Port","Porto"}. {"Present real Jabber IDs to","Os Jabber ID reais poden velos"}. {"private, ","privado"}. {"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"}. {"Remote copy","Copia remota"}. {"Remove All Offline Messages","Borrar Todas as Mensaxes Sen conexión"}. {"Remove","Borrar"}. {"Remove User","Eliminar usuario"}. {"Replaced by new connection","Substituído por unha nova conexión"}. {"Resources","Recursos"}. {"Restart","Reiniciar"}. {"Restart Service","Reiniciar o servizo"}. {"Restore Backup from File at ","Restaura copia de seguridade desde o ficheiro en "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Restaurar copia de seguridade binaria no seguinte reinicio de ejabberd (require menos memoria que se instantánea):"}. {"Restore binary backup immediately:","Restaurar inmediatamente copia de seguridade binaria:"}. {"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"}. {"Roster groups allowed to subscribe","Lista de grupos autorizados a subscribir"}. {"Roster","Lista de contactos"}. {"Roster of ","Lista de contactos de "}. {"Roster size","Tamaño da lista de contactos"}. {"RPC Call Error","Erro na chamada RPC"}. {"Running Nodes","Nodos funcionando"}. {"~s access rule configuration","Configuración das Regra de Acceso ~s"}. {"Saturday","Sábado"}. {"Script check","Comprobación de script"}. {"Search Results for ","Buscar resultados por "}. {"Search users in ","Buscar usuarios en "}. {"Send announcement to all online users","Enviar anuncio a todos los usuarios conectados"}. {"Send announcement to all online users on all hosts","Enviar anuncio a todos os usuarios conectados en todos os dominios"}. {"Send announcement to all users","Enviar anuncio a todos os usuarios"}. {"Send announcement to all users on all hosts","Enviar anuncio a todos os usuarios en todos os dominios"}. {"September","Setembro"}. {"Server ~b","Servidor ~b"}. {"Set message of the day and send to online users","Pór mensaxe do dia e enviar a todos os usuarios conectados"}. {"Set message of the day on all hosts and send to online users","Pór mensaxe do día en todos os dominios e enviar aos usuarios conectados"}. {"Shared Roster Groups","Grupos Compartidos"}. {"Show Integral Table","Mostrar Táboa Integral"}. {"Show Ordinary Table","Mostrar Táboa Ordinaria"}. {"Shut Down Service","Deter o servizo"}. {"~s invites you to the room ~s","~s invítache á sala ~s"}. {"Specify the access model","Especifica o modelo de acceso"}. {"Specify the publisher model","Especificar o modelo do publicante"}. {"~s's Offline Messages Queue","Cola de mensaxes diferidas de ~s"}. {"Start","Iniciar"}. {"Start Modules at ","Iniciar módulos en "}. {"Start Modules","Iniciar módulos"}. {"Statistics","Estatísticas"}. {"Statistics of ~p","Estatísticas de ~p"}. {"Stop","Deter"}. {"Stop Modules at ","Deter módulos en "}. {"Stop Modules","Detener módulos"}. {"Stopped Nodes","Nodos detidos"}. {"Storage Type","Tipo de almacenamiento"}. {"Store binary backup:","Gardar copia de seguridade binaria:"}. {"Store plain text backup:","Gardar copia de seguridade en texto plano:"}. {"Subject","Asunto"}. {"Submit","Enviar"}. {"Submitted","Enviado"}. {"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 é"}. {"Thursday","Xoves"}. {"Time","Data"}. {"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:"}. {"Transactions Restarted:","Transaccións reiniciadas:"}. {"Tuesday","Martes"}. {"Unauthorized","Non autorizado"}. {"Update","Actualizar"}. {"Update message of the day (don't send)","Actualizar mensaxe do dia, pero non envialo"}. {"Update message of the day on all hosts (don't send)","Actualizar a mensaxe do día en todos os dominos (pero non envialo)"}. {"Update plan","Plan de actualización"}. {"Update script","Script de actualización"}. {"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"}. ejabberd-16.01/priv/msgs/el.po0000644000232200023220000017760712645157216016551 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: el\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2012-04-18 12:50-0000\n" "Last-Translator: James Iakovos Mandelis \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Greek (ελληνικά)\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Απαιτείται χÏήση STARTTLS " #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Δεν Ï€ÏομηθεÏτικε πόÏος" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Αντικαταστάθικε από νέα σÏνδεση" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "ΠληκτÏολογήστε το κείμενο που βλέπετε" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Τα μηνÏματά σας Ï€Ïως ~s είναι αποκλεισμένα. Για αποδεσμεÏση, επισκεφθείτε ~s" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Εάν δεν βλέπετε την εικόνα CAPTCHA εδώ, επισκεφθείτε την ιστοσελίδα." #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Ιστοσελίδα CAPTCHA " #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Το CAPTCHA είναι έγκυÏο." #: 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 "ΧÏήστης" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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 "ejabberd Web Admin" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "ΔιαχείÏιση" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "ΑκατέÏγαστο" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Κανόνες ΠÏόσβασης" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s διαμόÏφωση κανόνα Ï€Ïόσβασης" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "εικονικοί κεντÏικοί υπολογιστές" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "ΧÏήστες" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Συνδεμένοι χÏήστες" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Τελευταία ΔÏαστηÏιότητα ΧÏήστη" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "ΠεÏίοδος: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "ΠεÏασμένο μήνα" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "ΠέÏυσι" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Όλες οι δÏαστηÏιότητες" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Δείτε Κοινό Πίνακα" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Δείτε ΟλοκληÏωτικό Πίνακα" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Στατιστικές" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Δεν Î’Ïέθηκε" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Κόμβος δεν βÏέθηκε" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "ΠÏοσθήκη νέου" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "ΚεντÏικός Υπολογιστής" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "ΕγγεγÏαμμένοι ΧÏήστες" #: 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:1459 msgid "Offline Messages" msgstr "ΧωÏίς ΣÏνδεση ΜηνÏματα" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Τελευταία ΔÏαστηÏιότητα" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Ποτέ" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Συνδεδεμένο" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "ΕγγεγÏαμμένοι ΧÏήστες:" #: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 #: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Online ΧÏήστες:" #: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "ΕξεÏχόμενες S2S Συνδέσεις:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" 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 msgid "None" msgstr "Κανένα" #: 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:1673 #, fuzzy msgid "User ~s" msgstr "ΧÏήστης" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Συνδεδεμένοι ΠόÏοι:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Κωδικός Ï€Ïόσβασης:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "ΑφαίÏεση χÏήστη" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Κανένα στοιχείο" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Κόμβοι" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "ΕνεÏγοί Κόμβοι" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Σταματημένοι Κόμβοι" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Κόμβος" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Βάση δεδομένων" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Αποθήκευση ΑντιγÏάφου Ασφαλείας" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "ΠαÏακολουθοÏμενες ΘÏÏες" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "ΕνημέÏωση" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Επανεκκίνηση" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Σταμάτημα" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Σφάλμα RPC Κλήσης" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Πίνακες βάσης δεδομένων στο " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Όνομα" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "ΤÏπος Αποθήκευσης" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Στοιχεία" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Μνήμη" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Σφάλμα" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "ΑντιγÏάφο Ασφαλείας του " #: 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 "" "ΠαÏακαλώ σημειώστε ότι οι επιλογές αυτές θα αποθήκευσουν ΑντιγÏάφο Ασφαλείας " "μόνο της ενσωματωμένης βάσης δεδομένων Mnesia. Εάν χÏησιμοποιείτε το module " "ODBC, θα Ï€Ïέπει επίσης να κάνετε χωÏιστά ΑντιγÏάφο Ασφαλείας της SQL βάση " "δεδομένων σας ." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "ΑποθηκεÏση Î´Ï…Î±Î´Î¹ÎºÎ¿Ï Î±Î½Ï„Î¹Î³Ïάφου ασφαλείας:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "ΕπαναφοÏά Î´Ï…Î±Î´Î¹ÎºÎ¿Ï Î±Î½Ï„Î¹Î³Ïάφου ασφαλείας αμέσως:" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "ΕπαναφοÏά Î´Ï…Î±Î´Î¹ÎºÎ¿Ï Î±Î½Ï„Î¹Î³Ïάφου ασφαλείας μετά την επόμενη επανεκκίνηση του " "ejabberd (απαιτεί λιγότεÏη μνήμη):" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "ΑποθηκεÏση αντιγÏάφου ασφαλείας σε αÏχείο κειμένου:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "ΕπαναφοÏά αντιγÏάφου ασφαλείας από αÏχείο κειμένου αμέσως:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Εισαγωγή δεδομένων χÏηστών από ένα αÏχείο PIEFXIS (XEP-0227):" #: 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:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Εξαγωγή δεδομένων των χÏηστών κεντÏÎ¹ÎºÎ¿Ï Ï…Ï€Î¿Î»Î¿Î³Î¹ÏƒÏ„Î® σε PIEFXIS αÏχεία " "(XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Εισαγωγή δεδομένων χÏήστη από το αÏχείο σειÏάς jabberd14:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Εισαγωγή δεδομένων χÏηστών από κατάλογο αÏχείων σειÏάς jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "ΠαÏακολουθοÏμενες ΘÏÏες στο " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Modules στο " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Στατιστικές του ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Uptime:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "ÎÏα CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "ΠαÏαδοθείς συναλλαγές:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Αποτυχημένες συναλλαγές:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Επανειλημμένες συναλλαγές:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "ΚαταγÏαμμένες συναλλαγές:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "ΕνημέÏωση" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Σχέδιο ενημέÏωσης" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "ΤÏοποποιημένα modules" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "ΠÏογÏάμα ενημέÏωσης" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "ΠÏογÏάμα ενημέÏωσης Ï‡Î±Î¼Î·Î»Î¿Ï ÎµÏ€Î¯Ï€ÎµÎ´Î¿Ï… " #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Script ελέγχου" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "ΘÏÏα" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "ΠÏωτόκολλο" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Module" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Επιλογές" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Εκκίνηση" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Εντολές" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Πινγκ" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Πονγκ" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "ΠÏαγματικά να διαγÏάψετε το μήνυμα της ημέÏας;" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Θέμα" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "ΠεÏιεχόμενο μηνυμάτως" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Δεν Ï€ÏομηθεÏτικε πεÏιεχόμενο ανακοινώσης" #: mod_announce.erl:662 msgid "Announcements" msgstr "Ανακοινώσεις" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Αποστολή ανακοίνωσης σε όλους τους χÏήστες" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "" "Αποστολή ανακοίνωσης σε όλους τους χÏήστες σε όλους τους κεντÏικοÏÏ‚ " "υπολογιστές" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Αποστολή ανακοίνωσης σε όλους τους συνδεδεμένους χÏήστες" #: 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:672 msgid "Set message of the day and send to online users" msgstr "ΟÏίστε μήνυμα ημέÏας και αποστολή στους συνδεδεμένους χÏήστες" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "ΟÏίστε μήνυμα ημέÏας και άμεση αποστολή στους συνδεδεμένους χÏήστες σε όλους " "τους κεντÏικοÏÏ‚ υπολογιστές" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "ΕνημέÏωση μηνÏματως ημέÏας (χωÏίς άμεση αποστολή)" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "" "ΕνημέÏωση μηνÏματως ημέÏας σε όλους τους κεντÏικοÏÏ‚ υπολογιστές (χωÏίς άμεση " "αποστολή)" #: mod_announce.erl:680 msgid "Delete message of the day" msgstr "ΔιαγÏάψτε το μήνυμα της ημέÏας" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "ΔιαγÏάψτε το μήνυμα της ημέÏας σε όλους τους κεντÏικοÏÏ‚ υπολογιστές" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "ΔιαμόÏφωση" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Εκκίνηση Modules" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "ΠαÏσηModules" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "ΕπαναφοÏά ΑντιγÏάφου Ασφαλείας" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Αποθήκευση σε αÏχείο κειμένου" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Εισαγωγή αÏχείων" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Εισαγωγή κατάλογου αÏχείων" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Επανεκκίνηση ΥπηÏεσίας" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Κλείσιμο ΥπηÏεσίας" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "ΔιαγÏαφή ΧÏήστη" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "ΤεÏματισμός ΣυνεδÏίας ΧÏήστη" #: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 #: mod_configure.erl:1473 msgid "Get User Password" msgstr "Έκθεση ÎšÏ‰Î´Î¹ÎºÎ¿Ï Î Ïόσβασης ΧÏήστη" #: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Αλλαγή ÎšÏ‰Î´Î¹ÎºÎ¿Ï Î Ïόσβασης ΧÏήστη" #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Έκθεση Τελευταίας ÎÏας ΣÏνδεσης ΧÏήστη" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Έκθεση Στατιστικών ΧÏήστη" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Έκθεση αÏÎ¹Î¸Î¼Î¿Ï ÎµÎ³Î³ÎµÎ³Ïαμμένων χÏηστών" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Έκθεση αÏÎ¹Î¸Î¼Î¿Ï ÏƒÏ…Î½Î´ÎµÎ´ÎµÎ¼Î­Î½Ï‰Î½ χÏηστών" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "ΔιαχείÏιση χÏηστών" #: mod_configure.erl:525 msgid "All Users" msgstr "Όλοι οι χÏήστες" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "ΕξεÏχόμενες S2S Συνδέσεις" #: mod_configure.erl:615 msgid "Backup Management" msgstr "ΔιαχείÏιση ΑντιγÏάφου Ασφαλείας" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Εισαγωγή ΧÏηστών από αÏχεία σειÏάς jabberd14" #: mod_configure.erl:762 msgid "To ~s" msgstr "ΠÏÏŽÏ‚ ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Από ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "ΔιαμόÏφωση Πίνακων βάσης δεδομένων στο " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Επιλέξτε Ï„Ïπο αποθήκευσης των πινάκων" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "ΑντίγÏαφο μόνο σε δίσκο" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "ΑντίγÏαφο μόνο σε RAM καί δίσκο" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "ΑντίγÏαφο σε RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "ΑπομεμακÏυσμένο αντίγÏαφο" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "ΠαÏση Modules στο " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Επιλέξτε modules για να σταματήσουν" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Εκκίνηση Modules στο " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Εισάγετε κατάλογο των (Module, [Επιλογές])" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Λίστα των Module για Εκκίνηση" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Αποθήκευση ΑντιγÏάφου Ασφαλείας σε ΑÏχείο στο " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Εισάγετε τοποθεσία αÏχείου αντιγÏάφου ασφαλείας" #: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Τοποθεσία ΑÏχείου" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "ΕπαναφοÏά ΑντιγÏάφου Ασφαλείας από αÏχείο στο " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Αποθήκευση ΑντιγÏάφου Ασφαλείας σε αÏχείο κειμένου στο " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Εισάγετε Τοποθεσία ΑÏχείου Κειμένου" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Εισαγωγή χÏηστών από αÏχείο στο " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Εισάγετε τοποθεσία αÏχείου σειÏάς jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Εισαγωγή χÏηστών από κατάλογο αÏχείων στο " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Εισάγετε κατάλογο αÏχείων σειÏάς jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Τοποθεσία κατάλογου αÏχείων" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "ΧÏόνος καθυστέÏησης" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "ΔιαχείÏιση στις Λίστες Ελέγχου ΠÏόσβασης" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Λίστες Ελέγχου ΠÏόσβασης" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "ΔιαμόÏφωση ΠÏόσβασης" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Ταυτότητα Jabber" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Επαλήθευση ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "ΑÏιθμός εγγεγÏαμμένων χÏηστών" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "ΑÏιθμός συνδεδεμένων χÏηστών" #: mod_configure.erl:1936 msgid "Last login" msgstr "Τελευταία σÏνδεση" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Μέγεθος Καταλόγου Επαφών" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "ΔιευθÏνσεις IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "ΠόÏοι" #: mod_configure.erl:2095 msgid "Administration of " msgstr "ΔιαχείÏιση του" #: mod_configure.erl:2100 msgid "Action on user" msgstr "EνέÏγεια για το χÏήστη" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "ΕπεξεÏγασία ιδιοτήτων" #: 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_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:220 mod_muc.erl:467 msgid "Access denied by service policy" msgstr "ΆÏνηση Ï€Ïόσβασης, λόγω τακτικής παÏοχής υπηÏεσιών" #: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Διαβιβάσεις" #: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC module" #: 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:653 msgid "Registration in mod_irc for " msgstr "ΕγγÏαφή στο mod_irc για " #: 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:667 msgid "IRC Username" msgstr "IRC Όνομα χÏήστη" #: 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." msgstr "" "Εάν θέλετε να καθοÏίσετε διαφοÏετικές θÏÏες, κωδικοÏÏ‚ Ï€Ïόσβασης, " "κωδικοποιήσεις για IRC διακομιστές, εισάγετε πληÏοφοÏίες στη μοÏφή '{\"irc " "διακομιστής\", \"κωδικοποιήσεις\", θÏÏα, \"κωδικός Ï€Ïόσβασης\"}'. " "ΠÏοεπιλεγμενα αυτή η υπηÏεσία χÏησιμοποιεί \"~s\" κωδικοποιήση, θÏÏα ~p, " "κενό κωδικό Ï€Ïόσβασης." #: 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 "" "ΠαÏάδειγμα: [{\"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 "ΠαÏάμετÏοι Συνδέσης" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Είσοδος στο IRC κανάλι" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC κανάλι (μην τεθεί το Ï€Ïώτο #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Διακομιστής IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Είσοδος στο κανάλι IRC εδώ." #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Είσοδος στο κανάλι IRC αυτής της Jabber Ταυτότητας: ~s" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC Ρυθμίσεις" #: 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 "" "ΠληκτÏολογήστε το όνομα χÏήστη και κωδικοποιήσεις που θέλετε να " "χÏησιμοποιήσετε για τη σÏνδεση με διακομιστές IRC. Πατήστε 'Next' για να " "πάÏετε πεÏισσότεÏα πεδία να συμπληÏώσετε. Πατήστε 'Complete' για να " "αποθηκεÏσετε Ïυθμίσεις." #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC όνομα χÏήστη" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Κωδικός Ï€Ïόσβασης ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "ΘÏÏα ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Κωδικοποίηση για διακομιστή ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Διακομιστής ~b" #: 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 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:941 msgid "Nickname Registration at " msgstr "ΕγγÏαφή με Ψευδώνυμο στο " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Ψευδώνυμο" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Αίθουσες σÏνεδÏιασης" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "εγκαταλείπει την αίθουσα" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "ΕγγεγÏαμμένοι ΧÏήστες" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "ΔιαμόÏφωση ΑίθουσaÏ‚ σÏνεδÏιασης Ï„Ïοποποιηθηκε" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "συνδέετε στην αίθουσα" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "εγκαταλείπει την αίθουσα" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "έχει απαγοÏευθεί" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "Έχει αποβληθεί λόγω αλλαγής υπαγωγής" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "αποβλήθηκε επειδή η αίθουσα αλλάξε γιά μέλη μόνο" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "αποβλήθηκε λόγω τεÏÎ¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï ÏƒÏ…ÏƒÏ„Î®Î¼Î±Ï„Î¿Ï‚" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "είναι τώÏα γνωστή ως" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " έχει θέσει το θέμα σε: " #: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Η αίθουσα σÏνεδÏιασης δημιουÏγήθηκε" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Η αίθουσα σÏνεδÏιασης διαγÏάφηκε" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Η αίθουσα σÏνεδÏιασης έχει ξεκινήσει" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Η αίθουσα σÏνεδÏιασης έχει σταματήσει" #: mod_muc_log.erl:503 msgid "Monday" msgstr "ΔευτέÏα" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "ΤÏίτη" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "ΤετάÏτη" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Πέμπτη" #: mod_muc_log.erl:507 msgid "Friday" msgstr "ΠαÏασκευή" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Σάββατο" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "ΚυÏιακή" #: mod_muc_log.erl:513 msgid "January" msgstr "ΙανουάÏιος" #: mod_muc_log.erl:514 msgid "February" msgstr "ΦεβÏουάÏιος" #: mod_muc_log.erl:515 msgid "March" msgstr "ΜάÏτιος" #: mod_muc_log.erl:516 msgid "April" msgstr "ΑπÏίλιος" #: mod_muc_log.erl:517 msgid "May" msgstr "Μάιος" #: mod_muc_log.erl:518 msgid "June" msgstr "ΙοÏνιος" #: mod_muc_log.erl:519 msgid "July" msgstr "ΙοÏλιος" #: mod_muc_log.erl:520 msgid "August" msgstr "ΑÏγουστος" #: mod_muc_log.erl:521 msgid "September" msgstr "ΣεπτέμβÏιος" #: mod_muc_log.erl:522 msgid "October" msgstr "ΟκτώβÏιος" #: mod_muc_log.erl:523 msgid "November" msgstr "ÎοέμβÏιος" #: mod_muc_log.erl:524 msgid "December" msgstr "ΔεκέμβÏιος" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "ΔιαμόÏφωση Αίθουσας σÏνεδÏιασης" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Συμετεχόντες Αίθουσας σÏνεδÏιασης" #: 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:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Μόνο οι συντονιστές μποÏοÏν να αλλάξουν το θέμα αυτής της αίθουσας" #: 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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Ψευδώνυμο ~s δεν υπάÏχει σε αυτή την αίθουσα" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "ΆκυÏη υπαγωγή: ~s" #: 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 "AπαιτοÏνται Ï€Ïονόμια ιδιοκτήτη" #: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "ΔιαμόÏφωση Αίθουσας σÏνεδÏιασης ~s" #: mod_muc_room.erl:3359 msgid "Room title" msgstr "Τίτλος Αίθουσας " #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "ΠεÏιγÏαφή Αίθουσας" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Κάντε αίθουσα μόνιμη" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Κάντε την δημόσια αναζήτηση δυνατή για αυτή την αίθουσα" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Κάντε κοινό τον κατάλογο συμμετεχόντων" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Κάντε την αίθουσα Ï€ÏοστατεÏομενη με κωδικό Ï€Ïόσβασης" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Μέγιστος αÏιθμός συμετεχόντων" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "ΧωÏίς ÏŒÏιο" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "ΠαÏοÏσιαση Ï€Ïαγματικών ταυτοτήτων Jabber σε" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "συντονιστές μόνο" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "οποιοσδήποτε" #: 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:3516 msgid "Make room moderated" msgstr "Κάντε την αίθουσα εποπτεÏονομενη" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "ΠÏοεπιλογη χÏήστων ως συμμετέχοντες" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "ΕπιτÏέψετε στους χÏήστες να αλλάζουν το θέμα" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "ΕπιτÏέψετε στους χÏήστες να αποστέλλουν ιδιωτικά μηνÏματα" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "ΕπιτÏέψετε στους χÏήστες να αποστέλλουν ιδιωτικά μηνÏματα σε" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "κανείς" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "ΕπιτÏέπστε στους χÏήστες να εÏωτοÏν άλλους χÏήστες" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "ΕπιτÏέψετε στους χÏήστες να αποστέλλουν Ï€Ïοσκλήσεις" #: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "ΕπιτÏέψτε στους επισκέπτες να αποστέλλουν κατάσταση στις ενημεÏώσεις " "παÏουσίας" #: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "ΕπιτÏέψετε στους επισκέπτες να αλλάζου ψευδώνυμο" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "ΕπιτÏέψτε στους επισκέπτες να στέλνουν αιτήματα φωνής" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Ελάχιστο χÏονικό διάστημα Î¼ÎµÏ„Î±Î¾Ï Î±Î¹Ï„Î·Î¼Î¬Ï„Ï‰Î½ φωνής (σε δευτεÏόλεπτα)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Κάντε την αίθουσα CAPTCHA Ï€ÏοστατεÏονομενη" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "ΕξαίÏεση από τις ταυτότητες Jabber, ή CAPTCHA Ï€Ïόκληση" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "ΕνεÏγοποίηση καταγÏαφής" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "ΧÏειάζεστε ένα x:data ικανό πελάτη για να Ïυθμίσετε την αίθουσα " #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "ΑÏιθμός συμετεχόντων" #: mod_muc_room.erl:4260 msgid "private, " msgstr "ιδιωτικό," #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Αίτημα φωνής" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Είτε εγκÏίνετε ή αποÏÏίψτε το αίτημα φωνής." #: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID ΧÏήστη" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "ΠαÏαχώÏηση φωνής σε αυτό το άτομο;" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s σας Ï€Ïοσκαλεί στην αίθουσα ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "ο κωδικός Ï€Ïόσβασης είναι" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "ΧÏόνος" #: mod_offline.erl:812 msgid "From" msgstr "Από" #: mod_offline.erl:813 msgid "To" msgstr "ΠÏÏŽÏ‚" #: mod_offline.erl:814 msgid "Packet" msgstr "Πακέτο" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "ΧωÏίς ΣÏνδεση ΜηνÏματα:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "ΑφαίÏεση Όλων των ΧωÏίς ΣÏνδεση ΜηνÏματων" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Δημοσίευση-ΕγγÏαφή" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd module Δημοσίευσης-ΕγγÏαφής" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Αίτηση συνδÏομητή Δημοσίευσης-ΕγγÏαφής" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Επιλέξτε αν θα εγκÏίθεί η εγγÏαφή αυτής της οντότητας." #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Ταυτότητα Κόμβου" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "ΔιεÏθυνση ΣυνδÏομητή" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" "ΕπιτÏέπετε σε αυτή την Jabber Ταυτότητα να εγγÏαφεί σε αυτό τον κόμβο " "Δημοσίευσης-ΕγγÏαφής;" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Κοινοποιήσεις με την παÏάδοση φοÏτίων" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Κοινοποιήσεις παÏάδοσης" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Ειδοποιηση στους συνδÏομητές όταν αλλάζει η διαμόÏφωση κόμβου" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Ειδοποιηση στους συνδÏομητές όταν ο κόμβος διαγÏάφεται" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Ειδοποιηση στους συνδÏομητές όταν αφαίÏοÏντε στοιχεία από τον κόμβο" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Μονιμη αποθήκευση στοιχείων" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Ένα φιλικό όνομα για τον κόμβο" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Μέγιστος αÏιθμός μόνιμων στοιχείων" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Εάν επιτÏέποντε συνδÏομές" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "ΚαθοÏίστε το μοντέλο Ï€Ïόσβασης" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Ομάδες Καταλόγου Επαφών μποÏοÏν να εγγÏαφοÏν" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "ΚαθοÏίστε το μοντέλο εκδότη" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "ΔιαγÏαφή όλων των στοιχείων όταν ο σχετικός εκδότης αποσυνδέεται" #: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "ΚαθοÏίστε τον Ï„Ïπο μηνÏματος συμβάντος" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Μέγιστο μέγεθος φοÏτίου σε bytes" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Πότε να αποσταλθεί το τελευταίο στοιχείο που δημοσιεÏθηκε" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "ΠαÏάδωση κοινοποιήσεων μόνο σε διαθέσιμους χÏήστες" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Οι συλλογές με την οποία είναι ένας κόμβος συνδέεται" #: 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: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 λογαÏιασμός σας δημιουÏγήθηκε με επιτυχία." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "ΥπήÏξε ένα σφάλμα κατά τη δημιουÏγία του λογαÏιασμοÏ:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Ο Jabber λογαÏιασμός σας διαγÏάφηκε με επιτυχία." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "ΥπήÏξε ένα σφάλμα κατά τη διαγÏαφή του λογαÏιασμοÏ:" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Ο κωδικός Ï€Ïόσβασης του Jabber λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ±Ï‚ έχει αλλάξει επιτυχώς." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "ΥπήÏξε ένα σφάλμα κατά την αλλαγή του ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης:" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "ΕγγÏαφή λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "ΚαταχωÏήστε έναν λογαÏιασμό Jabber" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "ΚαταÏγήστε την εγγÏαφή ενός λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Jabber" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "Αυτή η σελίδα σας επιτÏέπει να δημιουÏγήσετε ένα λογαÏιασμό Jabber σε αυτόν " "το διακομιστή Jabber. JID σας (Jabber Identifier) θα είναι της μοÏφής: " "όνομα_χÏήστη@διακομιστής_Jabber. ΠαÏακαλώ διαβάστε Ï€Ïοσεκτικά τις οδηγίες " "για να συμπληÏώσετε σωστά τα πεδία." #: 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 "" "ΑνεξαÏτήτως με πεζά ή κεφαλαία: 'μιαλεξη' είναι το ίδιο με 'ΜιαΛέξη' και " "'Μιαλέξη'." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "ΧαÏακτήÏες δεν επιτÏέπονται:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Διακομιστής:" #: 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:249 msgid "You can later change your password using a Jabber client." msgstr "" "ΜποÏείτε αÏγότεÏα να αλλάξετε τον κωδικό Ï€Ïόσβασής σας χÏησιμοποιώντας έναν " "πελάτη 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 "" "ΜεÏικοί πελάτες Jabber μποÏεί να αποθηκεÏσουν τον κωδικό Ï€Ïόσβασής σας στον " "υπολογιστή σας. ΧÏησιμοποιήστε αυτό το χαÏακτηÏιστικό μόνο εάν εμπιστεÏεστε " "την ασφάλεια του υπολογιστή σας." #: 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 "" "ΑπομνημονεÏστε τον κωδικό Ï€Ïόσβασής σας, ή γÏάψετε τον σε ένα χαÏτί που είχε " "τοποθετηθεί σε ασφαλές μέÏος. Στο Jabber δεν υπάÏχει αυτοματοποιημένος " "Ï„Ïόπος για να ανακτήσετε τον κωδικό σας αν τον ξεχάσετε." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Επαλήθευση ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης:" #: mod_register_web.erl:269 msgid "Register" msgstr "ΚαταχωÏήστε" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Παλαιός κωδικός Ï€Ïόσβασης:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Îέος κωδικός Ï€Ïόσβασης:" #: 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:480 msgid "Unregister" msgstr "ΚαταÏγήση εγγÏαφής" #: mod_roster.erl:1436 msgid "Subscription" msgstr "ΣυνδÏομή" #: mod_roster.erl:1437 msgid "Pending" msgstr "ΕκκÏεμεί" #: mod_roster.erl:1438 msgid "Groups" msgstr "Ομάδες" #: mod_roster.erl:1476 msgid "Validate" msgstr "ΕπαληθεÏστε" #: mod_roster.erl:1485 msgid "Remove" msgstr "ΑφαίÏεστε" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Καταλόγος Επαφών τοÏ" #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "ΠÏοσθήκη Jabber Ταυτότητας" #: mod_roster.erl:1622 msgid "Roster" msgstr "Καταλόγος Επαφών" #: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 #: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Κοινές Ομάδες Καταλόγων Επαφών" #: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Όνομα:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "ΠεÏιγÏαφή:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Μέλη:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Εμφανίσμενες Ομάδες:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Ομάδα" #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Διακομιστής" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Γενέθλια" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Πόλη" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "ΧώÏα" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Επώνυμο" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Ονοματεπώνυμο" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "ΠατÏώνυμο" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Όνομα ΟÏγανισμοÏ" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Μονάδα ΟÏγανισμοÏ" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Αναζήτηση χÏηστών στο" #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard Αναζήτηση χÏηστών" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard module" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Αποτελέσματα αναζήτησης για " #: mod_vcard_ldap.erl:502 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 "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Αυτός ο συμμετέχων αποβλήθηκε από την αίθουσα, επειδή έστειλε ένα μήνυμα " #~ "σφάλματος" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Αυτός ο συμμετέχων αποβλήθηκε από την αίθουσα, επειδή έστειλε ένα μήνυμα " #~ "σφάλματος σε άλλον συμμετέχων" #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Αυτός ο συμμετέχων αποβλήθηκε από την αίθουσα, επειδή έστειλε σφάλμα " #~ "παÏουσίας " #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Το CAPTCHA είναι έγκυÏο." ejabberd-16.01/priv/msgs/vi.po0000644000232200023220000014601712645157216016556 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "Last-Translator: EQHO Communications (Thailand) Ltd. - http://www.eqho.com\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Vietnamese (tiếng việt)\n" #: 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:604 msgid "No resource provided" msgstr "Không có nguồn lá»±c cung cấp" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "ÄÆ°á»£c thay thế bởi kết nối má»›i" #: 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: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: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:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Không bao giá»" #: 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" #: 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 #, fuzzy msgid "ejabberd Web Admin" msgstr "Giao diện Web ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Quản trị" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Thô" #: 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: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:913 msgid "~s access rule configuration" msgstr "~s cấu hình quy tắc truy cập" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Máy Chá»§ Ảo" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Ngưá»i sá»­ dụng" #: 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:971 msgid "Users Last Activity" msgstr "Hoạt Äá»™ng Cuối Cùng Cá»§a Ngưá»i Sá»­ Dụng" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Giai Ä‘oạn: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Tháng trước" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Năm trước" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Tất cả hoạt động" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Hiển Thị Bảng Thưá»ng" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Hiển Thị Bảng Äầy Äá»§" #: 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:1014 #, fuzzy msgid "Not Found" msgstr "Nút không tìm thấy" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nút không tìm thấy" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Thêm Má»›i" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Máy chá»§" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Ngưá»i Sá»­ Dụng Äã Äăng Ký" #: 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:1459 msgid "Offline Messages" msgstr "Thư Ngoại Tuyến" #: 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:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Không bao giá»" #: 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:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Ngưá»i Sá»­ Dụng Äã Äăng Ký:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Kết Nối 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: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: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:1673 #, fuzzy msgid "User ~s" msgstr "Ngưá»i sá»­ dụng " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Tài Nguyên ÄÆ°á»£c Kết Nối:" #: 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:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Gỡ Bá» Ngưá»i Sá»­ Dụng" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Không Dữ Liệu" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nút" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nút Hoạt Äá»™ng" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nút Dừng" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nút " #: 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:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sao lưu dá»± phòng" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Cổng Kết Nối" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Cập Nhật" #: 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:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Dừng" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Môđun" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Lá»—i Gá»i RPC" #: 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:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Tên" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Loại Lưu Trữ" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Bá»™ Nhá»›" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Sao lưu dá»± phòng vá»" #: 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 " "separately." msgstr "" "Lưu ý rằng những tùy chá»n này sẽ chỉ được sao lưu cÆ¡ sở dữ liệu bên trong " "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:1969 msgid "Store binary backup:" msgstr "Lưu dữ liệu sao lưu dạng nhị phân:" #: 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: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: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: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: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:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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: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:2115 msgid "Listened Ports at " msgstr "Cổng Liên Lạc tại" #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Môđun tại " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Thống kê vá» ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Thá»i gian tải lên:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Thá»i Gian CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Giao Dịch ÄÆ°á»£c Cam Kết:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Giao Dịch Há»§y Bá»:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Giao Dịch Khởi Äá»™ng Lại:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Giao Dịch ÄÆ°á»£c Ghi Nhận:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Cập Nhật " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Kế hoạch cập nhật" #: ejabberd_web_admin.erl:2255 #, fuzzy msgid "Modified modules" msgstr "Môđun cập nhật" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Cập nhận lệnh" #: 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:2258 msgid "Script check" msgstr "Lệnh kiểm tra" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Cổng" #: ejabberd_web_admin.erl:2439 #, fuzzy msgid "Protocol" msgstr "Cổng" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Môđun" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Tùy chá»n" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Khởi động" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Lệnh" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: 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:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Tiêu Ä‘á»" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Thân thư" #: 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:662 msgid "Announcements" msgstr "Thông báo" #: 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: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: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: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: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: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: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: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:680 msgid "Delete message of the day" msgstr "Xóa thư trong ngày" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Cấu hình" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Môđun Khởi Äá»™ng" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Môđun Dừng" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Khôi phục" #: 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:168 mod_configure.erl:663 msgid "Import File" msgstr "Nhập Tập Tin" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Nhập Thư Mục" #: 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:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Tắt Dịch Vụ" #: 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: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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Thay Äổi Mật Khẩu Ngưá»i Sá»­ Dụng" #: 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: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: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: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:320 mod_configure.erl:523 msgid "User Management" msgstr "Quản Lý Ngưá»i Sá»­ Dụng" #: mod_configure.erl:525 msgid "All Users" msgstr "Tất Cả Ngưá»i Sá»­ Dụng" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Kết Nối Bên Ngoài s2s" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Quản lý Sao Lưu Dá»± Phòng" #: 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:762 msgid "To ~s" msgstr "Gá»­i đến ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Nhận từ ~s" #: 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:1008 msgid "Choose storage type of tables" msgstr "Chá»n loại bảng lưu trữ" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Chỉ sao chép vào đĩa" #: 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:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Sao chép vào RAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Sao chép từ xa" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Môđun Dừng tại" #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Chá»n môđun để dừng" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Môđun Khởi Äá»™ng tại " #: 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:1080 msgid "List of modules to start" msgstr "Danh sách các môđun khởi động" #: 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: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: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:1115 msgid "Restore Backup from File at " msgstr "Phục hồi Sao Lưu từ Tập Tin tại " #: 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:1141 msgid "Enter path to text file" msgstr "Nhập đưá»ng dẫn đến tập tin văn bản" #: 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:1162 msgid "Enter path to jabberd14 spool file" msgstr "Nhập đưá»ng dẫn đến tập tin spool jabberd14" #: 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:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Nhập đưá»ng dẫn đến thư mục spool jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "ÄÆ°á»ng Dẫn đến Thư Mục" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Thá»i gian trì hoãn" #: 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:1321 msgid "Access control lists" msgstr "Danh sách kiểm soát truy cập" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Cấu Hình Truy Cập" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Kiểm Tra Mật Khẩu" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Số ngưá»i sá»­ dụng đã đăng ký" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Số ngưá»i sá»­ dụng trá»±c tuyến" #: mod_configure.erl:1936 msgid "Last login" msgstr "Äăng nhập lần cuối" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Kích thước bảng phân công" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Äịa chỉ IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Nguồn tài nguyên" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Quản trị vá» " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Hành động đối vá»›i ngưá»i sá»­ dụng" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Chỉnh Sá»­a Thuá»™c Tính" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "Môdun ejabberd IRC Bản quyá»n" #: 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:653 msgid "Registration in mod_irc for " msgstr "Äăng ký trong mod_irc cho " #: mod_irc.erl:659 #, fuzzy msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" 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:667 msgid "IRC Username" msgstr "Tên truy cập 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 "" "Nếu bạn muốn xác định các cách thức mã hóa khác nhau cho các máy chá»§ IRC, " "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:704 #, fuzzy msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." msgstr "" "Ví dụ: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", " "\"iso8859-1\"}]" #: mod_irc.erl:713 msgid "Connections parameters" msgstr "" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" #: mod_irc.erl:903 #, fuzzy msgid "IRC server" msgstr "Tên truy cập IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "" #: 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 "" "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:1060 #, fuzzy msgid "IRC username" msgstr "Tên truy cập IRC" #: mod_irc.erl:1126 #, fuzzy msgid "Password ~b" msgstr "Mật Khẩu" #: mod_irc.erl:1137 #, fuzzy msgid "Port ~b" msgstr "Cổng" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "" #: 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: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:941 msgid "Nickname Registration at " msgstr "Äăng Ký Bí Danh tại" #: 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: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: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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Phòng trò chuyện" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "rá»i khá»i phòng này" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Ngưá»i Sá»­ Dụng Äã Äăng Ký" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: 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:410 msgid "joins the room" msgstr "tham gia phòng này" #: 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:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "đã bị cấm" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "bây giỠđược biết như" #: 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:493 #, fuzzy msgid "Chatroom is created" msgstr "Phòng trò chuyện" #: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "Phòng trò chuyện" #: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "Phòng trò chuyện" #: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "Phòng trò chuyện" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Thứ Hai" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Thứ Ba" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Thứ Tư" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Thứ Năm" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Thứ Sáu" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Thứ Bảy" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Chá»§ Nhật" #: mod_muc_log.erl:513 msgid "January" msgstr "Tháng Má»™t" #: mod_muc_log.erl:514 msgid "February" msgstr "Tháng Hai" #: mod_muc_log.erl:515 msgid "March" msgstr "Tháng Ba" #: mod_muc_log.erl:516 msgid "April" msgstr "Tháng Tư" #: mod_muc_log.erl:517 msgid "May" msgstr "Tháng Năm" #: mod_muc_log.erl:518 msgid "June" msgstr "Tháng Sáu" #: mod_muc_log.erl:519 msgid "July" msgstr "Tháng Bảy" #: mod_muc_log.erl:520 msgid "August" msgstr "Tháng Tám" #: mod_muc_log.erl:521 msgid "September" msgstr "Tháng Chín" #: mod_muc_log.erl:522 msgid "October" msgstr "Tháng Mưá»i" #: mod_muc_log.erl:523 msgid "November" msgstr "Tháng Mưá»i Má»™t" #: mod_muc_log.erl:524 msgid "December" msgstr "Tháng Mưá»i Hai" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Cấu Hình Phòng" #: mod_muc_log.erl:932 #, fuzzy msgid "Room Occupants" msgstr "Số ngưá»i tham dá»±" #: 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 " "room" 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: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: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: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:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Tư cách không hợp lệ: ~s" #: mod_muc_room.erl:2846 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 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:3359 msgid "Room title" msgstr "Tên phòng" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "Miêu tả:" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Tạo phòng bá»n vững" #: 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:3378 msgid "Make participants list public" msgstr "Tạo danh sách ngưá»i tham dá»± công khai" #: 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:3394 msgid "Maximum Number of Occupants" msgstr "Số Lượng Ngưá»i Tham Dá»± Tối Äa" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Không giá»›i hạn" #: 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:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "nhà Ä‘iá»u phối duy nhất" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "bất kỳ ai" #: 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:3516 #, fuzzy msgid "Make room moderated" msgstr "Tạo phòng bá»n vững" #: 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: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: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: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:3551 msgid "nobody" msgstr "" #: 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: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: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:3586 #, fuzzy msgid "Allow visitors to change nickname" msgstr "Cho phép ngưá»i sá»­ dụng thay đổi chá»§ Ä‘á»" #: 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:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: 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:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Cho phép ghi nhật ký" #: 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:4190 msgid "Number of occupants" msgstr "Số ngưá»i tham dá»±" #: mod_muc_room.erl:4260 msgid "private, " msgstr "riêng," #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Ngưá»i sá»­ dụng " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: 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:4507 msgid "the password is" msgstr "mật khẩu là" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "Thá»i Gian" #: mod_offline.erl:812 msgid "From" msgstr "Từ" #: mod_offline.erl:813 msgid "To" msgstr "Äến" #: mod_offline.erl:814 msgid "Packet" msgstr "Gói thông tin" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Thư Ngoại Tuyến:" #: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "Thư Ngoại Tuyến" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Môdun SOCKS5 Bytestreams Bản quyá»n" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Xuất Bản-Äăng Ký" #: 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: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: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:1559 msgid "Node ID" msgstr "ID Nút" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Äịa Chỉ Ngưá»i Äăng Ký" #: 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: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:3747 msgid "Deliver event notifications" msgstr "ÄÆ°a ra các thông báo sá»± kiện" #: 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: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: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:3755 msgid "Persist items to storage" msgstr "Những mục cần để lưu trữ" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Số mục tối Ä‘a để lưu trữ" #: 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:3763 msgid "Specify the access model" msgstr "Xác định mô hình truy cập" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Xác định mô hình nhà xuất bản" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" #: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "Xác định mô hình truy cập" #: 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: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: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:3779 msgid "The collections with which a node is affiliated" msgstr "" #: 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: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 "" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "" #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "" #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" #: mod_register_web.erl:214 msgid "" "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." msgstr "" #: 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" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "" #: 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:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" #: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" #: 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 "" #: 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:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Kiểm Tra Mật Khẩu" #: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Bảng phân công" #: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Mật Khẩu:" #: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Mật Khẩu:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" #: mod_register_web.erl:480 msgid "Unregister" msgstr "" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Äăng ký" #: mod_roster.erl:1437 msgid "Pending" msgstr "Chá»" #: mod_roster.erl:1438 msgid "Groups" msgstr "Nhóm" #: mod_roster.erl:1476 msgid "Validate" msgstr "Xác nhận hợp lệ" #: mod_roster.erl:1485 msgid "Remove" msgstr "Gỡ bá»" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Bảng phân công cá»§a " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Thêm Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Bảng phân công" #: 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:1232 msgid "Name:" msgstr "Tên:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Miêu tả:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Thành viên:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Nhóm được hiển thị:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Nhóm " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server Bản quyá»n" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Ngày sinh" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Thành phố" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Quốc gia" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Há»" #: 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 "" "Ä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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Tên Äầy Äá»§" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Há» Äệm" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Tên Tổ Chức" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Bá»™ Phận" #: 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: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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Tìm Kiếm Ngưá»i Sá»­ Dụng vCard" #: 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:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Kết Quả Tìm Kiếm cho " #: 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 "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 "Encodings" #~ msgstr "Mã hóa" #~ msgid "(Raw)" #~ msgstr "(Thô)" #~ msgid "Specified nickname is already registered" #~ msgstr "Bí danh xác định đã đăng ký rồi" #~ msgid "Size" #~ msgstr "Kích thước" #~ msgid "Roster groups that may subscribe (if access model is roster)" #~ msgstr "" #~ "Các nhóm phân công có thể đăng ký (nếu mô hình truy cập là dạng phân công)" ejabberd-16.01/priv/msgs/it.msg0000644000232200023220000006646712645157216016736 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Configurazione dell'accesso"}. {"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"}. {"Add Jabber ID","Aggiungere un Jabber ID (Jabber ID)"}. {"Add New","Aggiungere nuovo"}. {"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?"}. {"Allow users to change the subject","Consentire agli utenti di cambiare l'oggetto"}. {"Allow users to query other users","Consentire agli utenti query verso altri utenti"}. {"Allow users to send invites","Consentire agli utenti l'invio di inviti"}. {"Allow users to send private messages","Consentire agli utenti l'invio di messaggi privati"}. {"Allow visitors to change nickname","Consentire ai visitatori di cambiare il nickname"}. {"Allow visitors to send private messages to","Consentire agli ospiti l'invio di messaggi privati a"}. {"Allow visitors to send status text in presence updates","Consentire ai visitatori l'invio di testo sullo stato in aggiornamenti sulla presenza"}. {"Allow visitors to send voice requests","Consentire agli ospiti l'invio di richieste di parola"}. {"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"}. {"Backup","Salvare"}. {"Backup to File at ","Salvataggio sul file "}. {"Bad format","Formato non valido"}. {"Birthday","Compleanno"}. {"CAPTCHA web page","Pagina web CAPTCHA"}. {"Change Password","Modificare la password"}. {"Change User Password","Cambiare la password dell'utente"}. {"Characters not allowed:","Caratteri non consentiti:"}. {"Chatroom configuration modified","Configurazione della stanza modificata"}. {"Chatroom is created","La stanza è creata"}. {"Chatroom is destroyed","La stanza è eliminata"}. {"Chatroom is started","La stanza è avviata"}. {"Chatroom is stopped","La stanza è arrestata"}. {"Chatrooms","Stanze"}. {"Choose a username and password to register with this server","Scegliere un nome utente e una password per la registrazione con questo server"}. {"Choose modules to stop","Selezionare i moduli da arrestare"}. {"Choose storage type of tables","Selezionare una modalità di conservazione delle tabelle"}. {"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:"}. {"Connections parameters","Parametri delle connessioni"}. {"Country","Paese"}. {"CPU Time:","Tempo CPU:"}. {"Database","Database"}. {"Database Tables Configuration at ","Configurazione delle tabelle del database su "}. {"December","Dicembre"}. {"Default users as participants","Definire per default gli utenti come partecipanti"}. {"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"}. {"Delete User","Eliminare l'utente"}. {"Deliver event notifications","Inviare notifiche degli eventi"}. {"Deliver payloads with event notifications","Inviare il contenuto del messaggio con la notifica dell'evento"}. {"Description:","Descrizione:"}. {"Disc only copy","Copia su disco soltanto"}. {"Displayed Groups:","Gruppi visualizzati:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Non comunicare la tua password a nessuno, neppure agli amministratori del server Jabber."}. {"Dump Backup to Text File at ","Trascrivere il salvataggio sul file di testo "}. {"Dump to Text File","Trascrivere su file di testo"}. {"Edit Properties","Modificare le proprietà"}. {"Either approve or decline the voice request.","Approva oppure respingi la richiesta di parola."}. {"ejabberd IRC module","Modulo IRC per ejabberd"}. {"ejabberd MUC module","Modulo MUC per ejabberd"}. {"ejabberd Publish-Subscribe module","Modulo Pubblicazione/Iscrizione (PubSub) per ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","Modulo SOCKS5 Bytestreams per ejabberd"}. {"ejabberd vCard module","Modulo vCard per ejabberd"}. {"ejabberd Web Admin","Amministrazione web ejabberd"}. {"Elements","Elementi"}. {"Email","E-mail"}. {"Enable logging","Abilitare i log"}. {"Encoding for server ~b","Codifica per il server ~b"}. {"End User Session","Terminare la sessione dell'utente"}. {"Enter list of {Module, [Options]}","Immettere un elenco di {Modulo, [Opzioni]}"}. {"Enter nickname you want to register","Immettere il nickname che si vuole registrare"}. {"Enter path to backup file","Immettere il percorso del file di salvataggio"}. {"Enter path to jabberd14 spool dir","Immettere il percorso della directory di spool di jabberd14"}. {"Enter path to jabberd14 spool file","Immettere il percorso del file di spool di jabberd14"}. {"Enter path to text file","Immettere il percorso del file di testo"}. {"Enter the text you see","Immettere il testo visibile"}. {"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.","Immettere il nome utente e le codifiche che si desidera utilizzare per la connessione ai server IRC. Premere \"Avanti\" per vedere i successivi campi da compilare. Premere \"Fatto\" per salvare le impostazioni."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Immettere il nome utente, le codifiche, le porte e le password che si desidera utilizzare per la connessione ai server IRC"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"Error","Errore"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Esempio: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"segreto\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.serverdiprova.net\", \"utf-8\"}]."}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Riempire il modulo per la ricerca di utenti Jabber corrispondenti ai criteri (Aggiungere * alla fine del campo per la ricerca di una sottostringa"}. {"Friday","Venerdì"}. {"From","Da"}. {"From ~s","Da ~s"}. {"Full Name","Nome completo"}. {"Get Number of Online Users","Ottenere il numero di utenti online"}. {"Get Number of Registered Users","Ottenere il numero di utenti registrati"}. {"Get User Last Login Time","Ottenere la data di ultimo accesso dell'utente"}. {"Get User Password","Ottenere la password dell'utente"}. {"Get User Statistics","Ottenere le statistiche dell'utente"}. {"Grant voice to this person?","Dare parola a questa persona?"}. {"Group ","Gruppo "}. {"Groups","Gruppi"}. {"has been banned","è stata/o bandita/o"}. {"has been kicked because of an affiliation change","è stato espulso a causa di un cambiamento di appartenenza"}. {"has been kicked because of a system shutdown","è stato espulso a causa dello spegnimento del sistema"}. {"has been kicked because the room has been changed to members-only","è stato espulso per la limitazione della stanza ai soli membri"}. {"has been kicked","è stata/o espulsa/o"}. {" has set the subject to: "," ha modificato l'oggetto in: "}. {"Host","Host"}. {"If you don't see the CAPTCHA image here, visit the web page.","Se qui non vedi l'immagine CAPTCHA, visita la pagina web."}. {"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 si vogliono specificare differenti porte, password, codifiche per i server IRC, si riempia questo elenco con valori nel formato '{\"server IRC\", \"codifica\", porta, \"password\"}'. Per default questo servizio utilizza la codifica \"~s\", la porta ~p, la password vuota."}. {"Import Directory","Importare una directory"}. {"Import File","Importare un file"}. {"Import user data from jabberd14 spool file:","Importare i dati utente da file di spool di jabberd14:"}. {"Import User from File at ","Importare un utente dal file "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importare i dati utenti da un file PIEFXIS (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","Canale IRC (senza il # iniziale)"}. {"IRC server","Server IRC"}. {"IRC settings","Impostazioni IRC"}. {"IRC Transport","Transport IRC"}. {"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"}. {"January","Gennaio"}. {"Join IRC channel","Entra nel canale IRC"}. {"joins the room","entra nella stanza"}. {"Join the IRC channel here.","Entra nel canale IRC qui."}. {"Join the IRC channel in this Jabber ID: ~s","Entra nel canale IRC in questo ID Jabber: ~s"}. {"July","Luglio"}. {"June","Giugno"}. {"Last Activity","Ultima attività"}. {"Last login","Ultimo accesso"}. {"Last month","Ultimo mese"}. {"Last year","Ultimo anno"}. {"leaves the room","esce dalla stanza"}. {"Listened Ports at ","Porte in ascolto su "}. {"Listened Ports","Porte in ascolto"}. {"List of modules to start","Elenco dei moduli da avviare"}. {"Low level update script","Script di aggiornamento di basso livello"}. {"Make participants list public","Rendere pubblica la lista dei partecipanti"}. {"Make room CAPTCHA protected","Rendere la stanza protetta da CAPTCHA"}. {"Make room members-only","Rendere la stanza riservata ai membri"}. {"Make room moderated","Rendere la stanza moderata"}. {"Make room password protected","Rendere la stanza protetta da password"}. {"Make room persistent","Rendere la stanza persistente"}. {"Make room public searchable","Rendere la sala visibile al pubblico"}. {"March","Marzo"}. {"Maximum Number of Occupants","Numero massimo di occupanti"}. {"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"}. {"Modules","Moduli"}. {"Monday","Lunedì"}. {"Name:","Nome:"}. {"Name","Nome"}. {"Never","Mai"}. {"New Password:","Nuova password:"}. {"Nickname","Nickname"}. {"Nickname Registration at ","Registrazione di un nickname su "}. {"Nickname ~s does not exist in the room","Il nickname ~s non esiste nella stanza"}. {"nobody","nessuno"}. {"No body provided for announce message","Nessun corpo fornito per il messaggio di annuncio"}. {"No Data","Nessuna informazione"}. {"Node ID","ID del nodo"}. {"Node not found","Nodo non trovato"}. {"Nodes","Nodi"}. {"No limit","Nessun limite"}. {"None","Nessuno"}. {"No resource provided","Nessuna risorsa fornita"}. {"Not Found","Non trovato"}. {"Notify subscribers when items are removed from the node","Notificare gli iscritti quando sono eliminati degli elementi dal nodo"}. {"Notify subscribers when the node configuration changes","Notificare gli iscritti quando la configurazione del nodo cambia"}. {"Notify subscribers when the node is deleted","Notificare gli iscritti quando il nodo è cancellato"}. {"November","Novembre"}. {"Number of occupants","Numero di presenti"}. {"Number of online users","Numero di utenti online"}. {"Number of registered users","Numero di utenti registrati"}. {"October","Ottobre"}. {"Offline Messages:","Messaggi offline:"}. {"Offline Messages","Messaggi offline"}. {"OK","OK"}. {"Old Password:","Vecchia password:"}. {"Online","Online"}. {"Online Users:","Utenti connessi:"}. {"Online Users","Utenti online"}. {"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"}. {"Owner privileges required","Necessari i privilegi di proprietario"}. {"Packet","Pacchetto"}. {"Password ~b","Password ~b"}. {"Password:","Password:"}. {"Password","Password"}. {"Password Verification:","Verifica della password:"}. {"Password Verification","Verifica della password"}. {"Path to Dir","Percorso della directory"}. {"Path to File","Percorso del file"}. {"Pending","Pendente"}. {"Period: ","Periodo:"}. {"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"}. {"Present real Jabber IDs to","Rendere visibile il Jabber ID reale a"}. {"private, ","privato, "}. {"Protocol","Protocollo"}. {"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"}. {"Register","Registra"}. {"Registration in mod_irc for ","Registrazione in mod_irc per "}. {"Remote copy","Copia remota"}. {"Remove All Offline Messages","Eliminare tutti i messaggi offline"}. {"Remove","Eliminare"}. {"Remove User","Eliminare l'utente"}. {"Replaced by new connection","Sostituito da una nuova connessione"}. {"Resources","Risorse"}. {"Restart","Riavviare"}. {"Restart Service","Riavviare il servizio"}. {"Restore Backup from File at ","Recuperare il salvataggio dal file "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Recuperare un salvataggio binario dopo il prossimo riavvio di ejabberd (necessita di meno memoria):"}. {"Restore binary backup immediately:","Recuperare un salvataggio binario adesso:"}. {"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"}. {"Roster groups allowed to subscribe","Gruppi roster abilitati alla registrazione"}. {"Roster","Lista dei contatti"}. {"Roster of ","Lista dei contatti di "}. {"Roster size","Dimensione della lista dei contatti"}. {"RPC Call Error","Errore di chiamata RPC"}. {"Running Nodes","Nodi attivi"}. {"~s access rule configuration","Configurazione delle regole di accesso per ~s"}. {"Saturday","Sabato"}. {"Script check","Verifica dello script"}. {"Search Results for ","Risultati della ricerca per "}. {"Search users in ","Cercare utenti in "}. {"Send announcement to all online users","Inviare l'annuncio a tutti gli utenti online"}. {"Send announcement to all online users on all hosts","Inviare l'annuncio a tutti gli utenti online su tutti gli host"}. {"Send announcement to all users","Inviare l'annuncio a tutti gli utenti"}. {"Send announcement to all users on all hosts","Inviare l'annuncio a tutti gli utenti su tutti gli host"}. {"September","Settembre"}. {"Server ~b","Server ~b"}. {"Server:","Server:"}. {"Set message of the day and send to online users","Impostare il messaggio del giorno (MOTD) ed inviarlo agli utenti online"}. {"Set message of the day on all hosts and send to online users","Impostare il messaggio del giorno (MOTD) su tutti gli host e inviarlo agli utenti online"}. {"Shared Roster Groups","Gruppi di liste di contatti comuni"}. {"Show Integral Table","Mostrare la tabella integrale"}. {"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 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"}. {"~s's Offline Messages Queue","Coda di ~s messaggi offline"}. {"Start","Avviare"}. {"Start Modules at ","Avviare moduli su "}. {"Start Modules","Avviare moduli"}. {"Statistics of ~p","Statistiche di ~p"}. {"Statistics","Statistiche"}. {"Stop","Arrestare"}. {"Stop Modules","Arrestare moduli"}. {"Stop Modules at ","Arrestare moduli su "}. {"Stopped Nodes","Nodi arrestati"}. {"Storage Type","Tipo di conservazione"}. {"Store binary backup:","Conservare un salvataggio binario:"}. {"Store plain text backup:","Conservare un salvataggio come semplice testo:"}. {"Subject","Oggetto"}. {"Submit","Inviare"}. {"Submitted","Inviato"}. {"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: "}. {"There was an error deleting the account: ","Si è verificato un errore nella cancellazione dell'account: "}. {"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."}. {"Thursday","Giovedì"}. {"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"}. {"Update","Aggiornare"}. {"Update message of the day (don't send)","Aggiornare il messaggio del giorno (MOTD) (non inviarlo)"}. {"Update message of the day on all hosts (don't send)","Aggiornare il messaggio del giorno (MOTD) su tutti gli host (non inviarlo)"}. {"Update plan","Piano di aggiornamento"}. {"Update script","Script di aggiornamento"}. {"Uptime:","Tempo dall'avvio:"}. {"Use of STARTTLS required","Utilizzo di STARTTLS obbligatorio"}. {"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"}. ejabberd-16.01/priv/msgs/sv.po0000644000232200023220000014002512645157216016561 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "Last-Translator: Gustaf Alströmer\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Swedish (svenska)\n" "X-Additional-Translator: Thore Alstromer\n" "X-Additional-Translator: Heysan\n" "X-Additional-Translator: Magnus Henoch\n" "X-Additional-Translator: Jonas Ã…dahl\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Du mÃ¥ste använda STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Ingen resurs angiven" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Ersatt av ny anslutning" #: 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: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: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: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:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Din CAPTCHA är godkänd." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" msgstr "Server ~b" #: 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" #: 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 "Ej auktoriserad" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administration" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Ra" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Ã…tkomstregler" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Ã…tkomstregelkonfiguration för ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuella servrar" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Användare" #: 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:971 msgid "Users Last Activity" msgstr "Användarens senaste aktivitet" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Period: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Senaste mÃ¥naden" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Senaste Ã¥ret" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "All aktivitet" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Visa normal tabell" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Visa kumulativ tabell" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistik" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Noden finns inte" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Noden finns inte" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Lägg till ny" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Server" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrerade användare" #: 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:1459 msgid "Offline Messages" msgstr "Offline meddelanden" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Senast aktivitet" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Aldrig" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Ansluten" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrerade användare" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "UtgÃ¥ende s2s anslutning" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "UtgÃ¥ende s2s anslutning" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Användare " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Anslutna resurser:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Lösenord:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Ta bort användare" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Ingen data" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Noder" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Körande noder" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Stannade noder" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nod " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databas" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Säkerhetskopiera" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Lyssnarport" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Uppdatera" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Omstart" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stoppa" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduler" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC Uppringningserror" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Databas tabell pa" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Namn" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Lagringstyp" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elements" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Minne" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Fel" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Backup av" #: 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 "" "Kom ihÃ¥g att dessa inställningar endast tar backup pa builtin Mnesias " "databas. Om du använder ODBC modul sÃ¥ mÃ¥ste du ta backup pÃ¥ SQLs databas " "enskilt" #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Lagra den binära backupen" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Ã¥terställ den binära backupen omedelbart" #: 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:1999 msgid "Store plain text backup:" msgstr "Lagra textbackup" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Ã¥terställ textbackup omedelbart" #: 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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importera användare frÃ¥n jabberd14 Spool directory:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Lyssnande portar pÃ¥ " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduler pÃ¥" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistik pÃ¥ ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tid upp" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU tid" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaktioner kommittade" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaktioner borttagna" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaktioner omstartade" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaktioner loggade " #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Uppdatera" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Uppdateringsplan" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Uppdaterade moduler" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Uppdatera skript" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Uppdaterade laglevel skript" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Skript kollat" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocol" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Parametrar" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Starta" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Kommandon" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Verkligen ta bort dagens meddelanden?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Ämne" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Meddelande kropp" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Ingen kropp behövs för dessa meddelanden" #: mod_announce.erl:662 msgid "Announcements" msgstr "Meddelanden" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Sänd meddelanden till alla användare" #: 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:668 msgid "Send announcement to all online users" msgstr "Sänd meddelanden till alla inloggade användare" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Uppdatera dagens status meddelande (skicka inte)" #: 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:680 msgid "Delete message of the day" msgstr "Ta bort dagens meddelande" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Konfiguration" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Starta moduler" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Stanna moduler" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Ã…terställ" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Dumpa till textfil" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importera fil" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importera katalog" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Starta om servicen" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Stäng ner servicen" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Ta bort användare" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Avsluta användarsession" #: 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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Andra användarlösenord" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Hämta användarstatistik" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Hämta antal registrerade användare" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Hämta antal inloggade användare" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Användarmanagement" #: mod_configure.erl:525 msgid "All Users" msgstr "Alla användare" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Utgaende s2s anslutning" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Hantera säkerhetskopior" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importera användare frÃ¥n jabberd14 Spool filer" #: mod_configure.erl:762 msgid "To ~s" msgstr "Till ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "FrÃ¥n ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Databastabellers konfiguration" #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Välj lagringstyp för tabeller" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Endast diskkopia" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM- och diskkopia" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM-kopia" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Sparas inte lokalt" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Stoppa moduler pÃ¥ " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Välj vilka moduler som skall stoppas" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Starta moduler pÃ¥ " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Skriv in en lista av {Module, [Options]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista av moduler som skall startas" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Säkerhetskopiera till fil pÃ¥ " #: 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: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:1115 msgid "Restore Backup from File at " msgstr "Ã…terställ säkerhetskopia frÃ¥n fil pÃ¥ " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Dumpa säkerhetskopia till textfil pÃ¥ " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Skriv in sökväg till textfil" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importera användare frÃ¥n fil pÃ¥ " #: 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:1177 msgid "Import Users from Dir at " msgstr "Importera användare frÃ¥n katalog pÃ¥ " #: 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:1184 msgid "Path to Dir" msgstr "Sökväg till katalog" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Tidsförsening" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfiguera ACL" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "ACL" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Ã…tkomstkonfiguration" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Lösenordsverifikation" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Antal registrerade användare" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Antal inloggade användare" #: mod_configure.erl:1936 msgid "Last login" msgstr "Senaste login" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Roster storlek" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresser" #: mod_configure.erl:1967 msgid "Resources" msgstr "Resurser" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Administration av " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Handling mot användare" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Redigera egenskaper" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC-modul" #: 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:653 msgid "Registration in mod_irc for " msgstr "mod_irc-registrering för " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" "Skriv in användarnamn och textkodning du vill använda för att ansluta till " "IRC-servrar" #: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC-användarnamn" #: 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." msgstr "" "Om du vill specifiera textkodning för IRC-servrar, fyll i listan med värden " "i formatet '{\"irc server\", \"encoding\", port, \"password\"}'. Som " "standard används \"~s\", port ~p, no password." #: 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 "" "Exempel: [{\"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 "Uppkopplingsparametrar" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Lägg till IRC kanal" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanal (skriv inte första #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC-användarnamn" #: 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: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:1046 msgid "IRC settings" msgstr "IRC Inställningar" #: 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 "" "Skriv in användarnamn och textkodning du vill använda för att ansluta till " "IRC-servrar" #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC-användarnamn" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Lösenord ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Encoding för server ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registrera smeknamn pÃ¥ " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Smeknamn" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Chattrum" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "lämnar rummet" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Registrerade användare" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Chattrum konfiguration modifierad" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "joinar rummet" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "lämnar rummet" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "har blivit bannad" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "har blivit kickad p.g.a en systemnerstängning" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "är känd som" #: 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:493 #, fuzzy msgid "Chatroom is created" msgstr "Chattrum" #: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "Chattrum" #: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "Chattrum" #: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "Chattrum" #: mod_muc_log.erl:503 msgid "Monday" msgstr "MÃ¥ndag" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Tisdag" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Onsdag" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Torsdag" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Fredag" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Lördag" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Söndag" #: mod_muc_log.erl:513 msgid "January" msgstr "Januari" #: mod_muc_log.erl:514 msgid "February" msgstr "Februari" #: mod_muc_log.erl:515 msgid "March" msgstr "Mars" #: mod_muc_log.erl:516 msgid "April" msgstr "April" #: mod_muc_log.erl:517 msgid "May" msgstr "Maj" #: mod_muc_log.erl:518 msgid "June" msgstr "Juni" #: mod_muc_log.erl:519 msgid "July" msgstr "Juli" #: mod_muc_log.erl:520 msgid "August" msgstr "Augusti" #: mod_muc_log.erl:521 msgid "September" msgstr "September" #: mod_muc_log.erl:522 msgid "October" msgstr "Oktober" #: mod_muc_log.erl:523 msgid "November" msgstr "November" #: mod_muc_log.erl:524 msgid "December" msgstr "December" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Rumkonfiguration" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Antal besökare" #: 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" msgstr "" "Endast moderatorer och deltagare har tillÃ¥telse att ändra ämnet i det här " "rummet" #: 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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Smeknamnet ~s existerar inte i det här rummet" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Ogiltlig rang: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ogiltlig roll: ~s" #: 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:3359 msgid "Room title" msgstr "Rumstitel" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "Beskrivning:" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Gör rummet permanent" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Gör rummet publikt sökbart" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Gör deltagarlistan publik" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Gör losenorden i rummet publika" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maximalt antal av användare" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Ingen gräns" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Nuvarande äkta Jabber IDs till" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "endast moderatorer" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "Vemsomhelst" #: 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:3516 msgid "Make room moderated" msgstr "Gör rummet modererat" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Gör om användare till deltagare" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "TillÃ¥t användare att byta ämne" #: 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:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "TillÃ¥t användare att skicka privata meddelanden" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "" #: 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:3579 msgid "Allow users to send invites" msgstr "TillÃ¥t användare att skicka inbjudningar" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "TillÃ¥t gäster att kunna ändra smeknamn" #: 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:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: mod_muc_room.erl:3599 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Gör losenorden i rummet publika" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Möjliggör login" #: 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:4190 msgid "Number of occupants" msgstr "Antal besökare" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privat, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Användare " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: 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:4507 msgid "the password is" msgstr "Lösenordet är" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "Tid" #: mod_offline.erl:812 msgid "From" msgstr "FrÃ¥n" #: mod_offline.erl:813 msgid "To" msgstr "Till" #: mod_offline.erl:814 msgid "Packet" msgstr "Paket" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline meddelanden:" #: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "Offline meddelanden" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestrem modul" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publikprenumeration" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd publikprenumerations modul" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Pubsub prenumerationsforfrÃ¥gan" #: 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:1559 msgid "Node ID" msgstr "Node ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Prenumerationsadress" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Skicka innehÃ¥ll tillsammans med notifikationer" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Skicka eventnotifikation" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Meddela prenumeranter när nodens konfiguration ändras" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Meddela prenumeranter när noden tas bort" #: 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:3755 msgid "Persist items to storage" msgstr "Spara dataposter permanent" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Ett vänligt namn for noden" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Högsta antal dataposter som sparas" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "TillÃ¥ta prenumerationer?" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Specificera accessmodellen" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Rostergrupper tillÃ¥ts att prenumerera" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Ange publiceringsmodell" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" #: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "Specificera accessmodellen" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Högsta innehÃ¥llsstorlek i bytes" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "När att skicka senast publicerade ämne" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Skicka notifikationer bara till uppkopplade användare" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" #: 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: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 "" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "" #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "" #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" #: mod_register_web.erl:214 msgid "" "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." msgstr "" #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "IRC-användarnamn" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "" #: 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:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" #: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" #: 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 "" #: 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:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Lösenordsverifikation" #: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Kontaktlista" #: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Lösenord:" #: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Lösenord:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" #: mod_register_web.erl:480 msgid "Unregister" msgstr "" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Prenumeration" #: mod_roster.erl:1437 msgid "Pending" msgstr "Ännu inte godkända" #: mod_roster.erl:1438 msgid "Groups" msgstr "Grupper" #: mod_roster.erl:1476 msgid "Validate" msgstr "Validera" #: mod_roster.erl:1485 msgid "Remove" msgstr "Ta bort" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontaktlista för " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Lägg till Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "Kontaktlista" #: 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:1232 msgid "Name:" msgstr "Namn:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Beskrivning:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Medlemmar:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Visade grupper:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupp " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Födelsedag" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Stad" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Land" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Efternamn" #: 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 "" "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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Fullständigt namn" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Mellannamn" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organisationsnamn" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Organisationsenhet" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Sök efter användare pÃ¥ " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard användare sök" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard-modul" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Sökresultat för" #: 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 "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 "" #~ "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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Deltagaren har blivit kickad frÃ¥n rummet p.g.a att han skickade ett " #~ "errormeddelande till en annan deltagare" #~ 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" #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Din CAPTCHA är godkänd." ejabberd-16.01/priv/msgs/wa.msg0000644000232200023220000004315512645157216016716 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Apontiaedje des accès"}. {"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"}. {"Add Jabber ID","Radjouter èn ID Jabber"}. {"Add New","Radjouter"}. {"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?"}. {"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 status text in presence updates","Permete ki les viziteus evoyexhe des tecse d' estat dins leus messaedjes di prezince"}. {"All Users","Tos les uzeus"}. {"Announcements","Anonces"}. {"anyone","tot l' minme kî"}. {"April","avri"}. {"August","awousse"}. {"Backup","Copeye di sÃ¥vrité"}. {"Backup Management","Manaedjaedje des copeyes di sÃ¥vrité"}. {"Backup to File at ","Fé ene copeye di sÃ¥vrité dins on fitchî so "}. {"Bad format","Mwais fôrmat"}. {"Birthday","Date d' askepiaedje"}. {"Change Password","Candjî l' sicret"}. {"Change User Password","Candjî l' sicret d' l' uzeu"}. {"Chatroom configuration modified","L' apontiaedje del sÃ¥le di berdelaedje a candjî"}. {"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"}. {"Choose storage type of tables","Tchoezi l' sôre di wÃ¥rdaedje po les tÃ¥ves"}. {"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"}. {"CPU Time:","Tins CPU:"}. {"Database","BÃ¥ze di dnêyes"}. {"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 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"}. {"Delete User","Disfacer èn uzeu"}. {"Deliver event notifications","Evoyî des notifiaedjes d' evenmints"}. {"Deliver payloads with event notifications","Evoyî l' contnou avou les notifiaedjes d' evenmints"}. {"Description:","Discrijhaedje:"}. {"Disc only copy","Copeye seulmint sol deure plake"}. {"Displayed Groups:","Groupes hÃ¥ynés:"}. {"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"}. {"ejabberd IRC module","Module IRC po ejabberd"}. {"ejabberd MUC module","Module MUC (sÃ¥les di berdelaedje) po 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"}. {"Email","Emile"}. {"Enable logging","Mete en alaedje li djournÃ¥"}. {"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"}. {"Enter path to backup file","Dinez l' tchimin viè l' fitchî copeye di sÃ¥vrité"}. {"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"}. {"Erlang Jabber Server","Sierveu Jabber Erlang"}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","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"}. {"Friday","vénrdi"}. {"From","Di"}. {"From ~s","Dispoy ~s"}. {"Full Name","No etir"}. {"Get Number of Online Users","Riçure li nombe d' uzeus raloyîs"}. {"Get Number of Registered Users","Riçure li nombe d' uzeus edjîstrés"}. {"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"}. {"Group ","Groupe "}. {"Groups","Groupes"}. {"has been banned","a stî bani"}. {"has been kicked","a stî pité evoye"}. {"has been kicked because of an affiliation change","a stî pité evoye cÃ¥ze d' on candjmint d' afiyaedje"}. {"has been kicked because of a system shutdown","a stî pité evoye cÃ¥ze d' èn arestaedje do sistinme"}. {"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"}. {"Import Directory","Sititchî d' on ridant"}. {"Import File","Sititchî d' on fitchî"}. {"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î"}. {"joins the room","arive sol sÃ¥le"}. {"July","djulete"}. {"June","djun"}. {"Last Activity","Dierinne activité"}. {"Last login","Dierin elodjaedje"}. {"Last month","Dierin moes"}. {"Last year","Dierinne anêye"}. {"leaves the room","cwite li sÃ¥le"}. {"Listened Ports at ","Pôrts drovous so "}. {"Listened Ports","Pôrts drovous"}. {"List of modules to start","Djivêye di modules a-z enonder"}. {"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 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"}. {"Make room persistent","Rinde li sÃ¥le permaninte"}. {"Make room public searchable","Rinde li sÃ¥le di berdelaedje cwerÃ¥ve publicmint"}. {"March","mÃ¥ss"}. {"Maximum Number of Occupants","Nombe macsimom di prezints"}. {"Max # of items to persist","Nombe macsimoms di cayets permanints"}. {"Max payload size in bytes","Contnou macsimom en octets"}. {"May","may"}. {"Members:","Mimbes:"}. {"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"}. {"Monday","londi"}. {"Name","No"}. {"Name:","Pitit no:"}. {"Never","MÃ¥y"}. {"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"}. {"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é"}. {"Nodes","Nuks"}. {"No limit","Pont d' limite"}. {"None","Nole"}. {"No resource provided","Nole rissoûce di dnêye"}. {"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é"}. {"November","nôvimbe"}. {"Number of occupants","Nombe di prezints"}. {"Number of online users","Nombe d' uzeus raloyîs"}. {"Number of registered users","Nombe d' uzeus edjîstrés"}. {"October","octôbe"}. {"Offline Messages:","Messaedjes ki ratindèt:"}. {"Offline Messages","Messaedjes ki ratindèt"}. {"OK","'l est bon"}. {"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 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"}. {"Owner privileges required","I fÃ¥t des priviledjes di prôpietaire"}. {"Packet","Paket"}. {"Password:","Sicret:"}. {"Password","Sicret"}. {"Password Verification","Acertinaedje do scret"}. {"Path to Dir","Tchimin viè l' ridant"}. {"Path to File","Tchimin viè l' fitchî"}. {"Pending","Ratindant"}. {"Period: ","Termene:"}. {"Persist items to storage","Cayets permanints a wÃ¥rder"}. {"Ping","Ping"}. {"Pong","Pong"}. {"Port","Pôrt"}. {"Present real Jabber IDs to","Mostrer les vraiys Jabber IDs a"}. {"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 "}. {"Remote copy","Copeye Ã¥ lon"}. {"Remove","Oister"}. {"Remove User","Disfacer l' uzeu"}. {"Replaced by new connection","Replaecî pa on novea raloyaedje"}. {"Resources","Rissoûces"}. {"Restart","Renonder"}. {"Restart Service","Renonder siervice"}. {"Restore Backup from File at ","Rapexhî dispoy li fitchî copeye di sÃ¥vrité so "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Rapexhî l' copeye di sÃ¥vrité binaire après l' renondaedje ki vént d' ejabberd (çoula prind moens d' memwere del fé insi):"}. {"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î"}. {"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"}. {"Roster of ","Djivêye des soçons da "}. {"Roster size","Grandeu del djivêye des soçons"}. {"RPC Call Error","Aroke di houcaedje RPC"}. {"Running Nodes","Nuks en alaedje"}. {"~s access rule configuration","Apontiaedje des rîles d' accès a ~s"}. {"Saturday","semdi"}. {"Script check","Acertinaedje do scripe"}. {"Search Results for ","Rizultats do cweraedje po "}. {"Search users in ","Cweri des uzeus dins "}. {"Send announcement to all online users","Evoyî l' anonce a tos les uzeus raloyîs"}. {"Send announcement to all online users on all hosts","Evoyî l' anonce a tos les uzeus raloyîs so tos les lodjoes"}. {"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"}. {"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"}. {"Show Integral Table","Mostrer totÃ¥"}. {"Show Ordinary Table","Mostrer crexhince"}. {"Shut Down Service","Arester siervice"}. {"~s invites you to the room ~s","~s vos preye sol sÃ¥le ~s"}. {"Specify the access model","Sipecifyî l' modele d' accès"}. {"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"}. {"Start Modules at ","Renonder les modules so "}. {"Start Modules","Enonder des modules"}. {"Statistics of ~p","Sitatistikes di ~p"}. {"Statistics","Sitatistikes"}. {"Stop","Arester"}. {"Stop Modules","Arester des modules"}. {"Stop Modules at ","Arester les modules so "}. {"Stopped Nodes","Nuks essoctés"}. {"Storage Type","Sôre di wÃ¥rdaedje"}. {"Store binary backup:","Copeye di sÃ¥vrité binaire:"}. {"Store plain text backup:","Copeye di sÃ¥vrité tecse:"}. {"Subject","Sudjet"}. {"Submit","Evoyî"}. {"Submitted","Candjmints evoyîs"}. {"Subscriber Address","Adresse di l' abouné"}. {"Subscription","Abounmimnt"}. {"Sunday","dimegne"}. {"the password is","li scret est"}. {"Thursday","djudi"}. {"Time","Date"}. {"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Ã¥:"}. {"Transactions Restarted:","Transaccions renondêyes:"}. {"Tuesday","mÃ¥rdi"}. {"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 script","Sicripe di metaedje a djoû"}. {"Uptime:","Tins dispoy l' enondaedje:"}. {"Use of STARTTLS required","L' eployaedje di STARTTL est oblidjî"}. {"User Management","Manaedjaedje des uzeus"}. {"Users Last Activity","Dierinne activité des uzeus"}. {"Users","Uzeus"}. {"User","Uzeu"}. {"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."}. ejabberd-16.01/priv/msgs/el.msg0000644000232200023220000011601412645157216016702 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","ΔιαμόÏφωση ΠÏόσβασης"}. {"Access Control List Configuration","ΔιαχείÏιση στις Λίστες Ελέγχου ΠÏόσβασης"}. {"Access control lists","Λίστες Ελέγχου ΠÏόσβασης"}. {"Access Control Lists","Λίστες Ελέγχου ΠÏόσβασης"}. {"Access denied by service policy","ΆÏνηση Ï€Ïόσβασης, λόγω τακτικής παÏοχής υπηÏεσιών"}. {"Access rules","Κανόνες ΠÏόσβασης"}. {"Access Rules","Κανόνες ΠÏόσβασης"}. {"Action on user","EνέÏγεια για το χÏήστη"}. {"Add Jabber ID","ΠÏοσθήκη Jabber Ταυτότητας"}. {"Add New","ΠÏοσθήκη νέου"}. {"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 Ταυτότητα να εγγÏαφεί σε αυτό τον κόμβο Δημοσίευσης-ΕγγÏαφής;"}. {"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 voice requests","ΕπιτÏέψτε στους επισκέπτες να στέλνουν αιτήματα φωνής"}. {"All Users","Όλοι οι χÏήστες"}. {"Announcements","Ανακοινώσεις"}. {"anyone","οποιοσδήποτε"}. {"A password is required to enter this room","Απαιτείται κωδικός Ï€Ïόσβασης για είσοδο σε αυτή την αίθουσα"}. {"April","ΑπÏίλιος"}. {"August","ΑÏγουστος"}. {"Backup Management","ΔιαχείÏιση ΑντιγÏάφου Ασφαλείας"}. {"Backup to File at ","Αποθήκευση ΑντιγÏάφου Ασφαλείας σε ΑÏχείο στο "}. {"Backup","Αποθήκευση ΑντιγÏάφου Ασφαλείας"}. {"Bad format","Ακατάλληλη μοÏφή"}. {"Birthday","Γενέθλια"}. {"CAPTCHA web page","Ιστοσελίδα CAPTCHA "}. {"Change Password","Αλλαγή κωδικοÏ"}. {"Change User Password","Αλλαγή ÎšÏ‰Î´Î¹ÎºÎ¿Ï Î Ïόσβασης ΧÏήστη"}. {"Characters not allowed:","ΧαÏακτήÏες δεν επιτÏέπονται:"}. {"Chatroom configuration modified","ΔιαμόÏφωση ΑίθουσaÏ‚ σÏνεδÏιασης Ï„Ïοποποιηθηκε"}. {"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","Επιλέξτε modules για να σταματήσουν"}. {"Choose storage type of tables","Επιλέξτε Ï„Ïπο αποθήκευσης των πινάκων"}. {"Choose whether to approve this entity's subscription.","Επιλέξτε αν θα εγκÏίθεί η εγγÏαφή αυτής της οντότητας."}. {"City","Πόλη"}. {"Commands","Εντολές"}. {"Conference room does not exist","Αίθουσα σÏνεδÏιασης δεν υπάÏχει"}. {"Configuration of room ~s","ΔιαμόÏφωση Αίθουσας σÏνεδÏιασης ~s"}. {"Configuration","ΔιαμόÏφωση"}. {"Connected Resources:","Συνδεδεμένοι ΠόÏοι:"}. {"Connections parameters","ΠαÏάμετÏοι Συνδέσης"}. {"Country","ΧώÏα"}. {"CPU Time:","ÎÏα CPU:"}. {"Database Tables Configuration at ","ΔιαμόÏφωση Πίνακων βάσης δεδομένων στο "}. {"Database","Βάση δεδομένων"}. {"December","ΔεκέμβÏιος"}. {"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","Κοινοποιήσεις με την παÏάδοση φοÏτίων"}. {"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","Αποθήκευση σε αÏχείο κειμένου"}. {"Edit Properties","ΕπεξεÏγασία ιδιοτήτων"}. {"Either approve or decline the voice request.","Είτε εγκÏίνετε ή αποÏÏίψτε το αίτημα φωνής."}. {"ejabberd IRC module","ejabberd IRC module"}. {"ejabberd MUC module","ejabberd MUC module"}. {"ejabberd Publish-Subscribe module","ejabberd module Δημοσίευσης-ΕγγÏαφής"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","ejabberd vCard module"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Στοιχεία"}. {"Email","Email"}. {"Enable logging","ΕνεÏγοποίηση καταγÏαφής"}. {"Encoding for server ~b","Κωδικοποίηση για διακομιστή ~b"}. {"End User Session","ΤεÏματισμός ΣυνεδÏίας ΧÏήστη"}. {"Enter list of {Module, [Options]}","Εισάγετε κατάλογο των (Module, [Επιλογές])"}. {"Enter nickname you want to register","ΠληκτÏολογήστε το ψευδώνυμο που θέλετε να εγγÏαφείτε"}. {"Enter path to backup file","Εισάγετε τοποθεσία αÏχείου αντιγÏάφου ασφαλείας"}. {"Enter path to jabberd14 spool dir","Εισάγετε κατάλογο αÏχείων σειÏάς jabberd14"}. {"Enter path to jabberd14 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. Πατήστε 'Next' για να πάÏετε πεÏισσότεÏα πεδία να συμπληÏώσετε. Πατήστε 'Complete' για να αποθηκεÏσετε Ïυθμίσεις."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Εισάγετε το όνομα χÏήστη, κωδικοποιήσεις, τις θÏÏες και τους κωδικοÏÏ‚ Ï€Ïόσβασης που θέλετε να χÏησιμοποιήσετε για σÏνδεση με IRC διακομιστή"}. {"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, ή 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 χÏήστη"}. {"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","Από"}. {"Full Name","Ονοματεπώνυμο"}. {"Get Number of Online Users","Έκθεση αÏÎ¹Î¸Î¼Î¿Ï ÏƒÏ…Î½Î´ÎµÎ´ÎµÎ¼Î­Î½Ï‰Î½ χÏηστών"}. {"Get Number of Registered Users","Έκθεση αÏÎ¹Î¸Î¼Î¿Ï ÎµÎ³Î³ÎµÎ³Ïαμμένων χÏηστών"}. {"Get User Last Login Time","Έκθεση Τελευταίας ÎÏας ΣÏνδεσης ΧÏήστη"}. {"Get User Password","Έκθεση ÎšÏ‰Î´Î¹ÎºÎ¿Ï Î Ïόσβασης ΧÏήστη"}. {"Get User Statistics","Έκθεση Στατιστικών ΧÏήστη"}. {"Grant voice to this person?","ΠαÏαχώÏηση φωνής σε αυτό το άτομο;"}. {"Groups","Ομάδες"}. {"Group ","Ομάδα"}. {"has been banned","έχει απαγοÏευθεί"}. {"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 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 διακομιστής\", \"κωδικοποιήσεις\", θÏÏα, \"κωδικός Ï€Ïόσβασης\"}'. ΠÏοεπιλεγμενα αυτή η υπηÏεσία χÏησιμοποιεί \"~s\" κωδικοποιήση, θÏÏα ~p, κενό κωδικό Ï€Ïόσβασης."}. {"Import Directory","Εισαγωγή κατάλογου αÏχείων"}. {"Import File","Εισαγωγή αÏχείων"}. {"Import user data from jabberd14 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:","Εισαγωγή δεδομένων χÏηστών από κατάλογο αÏχείων σειÏάς 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"}. {"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","είναι τώÏα γνωστή ως"}. {"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"}. {"January","ΙανουάÏιος"}. {"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"}. {"July","ΙοÏλιος"}. {"June","ΙοÏνιος"}. {"Last Activity","Τελευταία ΔÏαστηÏιότητα"}. {"Last login","Τελευταία σÏνδεση"}. {"Last month","ΠεÏασμένο μήνα"}. {"Last year","ΠέÏυσι"}. {"leaves the room","εγκαταλείπει την αίθουσα"}. {"Listened Ports at ","ΠαÏακολουθοÏμενες ΘÏÏες στο "}. {"Listened Ports","ΠαÏακολουθοÏμενες ΘÏÏες"}. {"List of modules to start","Λίστα των Module για Εκκίνηση"}. {"Low level update script","ΠÏογÏάμα ενημέÏωσης Ï‡Î±Î¼Î·Î»Î¿Ï ÎµÏ€Î¯Ï€ÎµÎ´Î¿Ï… "}. {"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","Μέγιστο μέγεθος φοÏτίου σε 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"}. {"Modules","Modules"}. {"Monday","ΔευτέÏα"}. {"Name:","Όνομα:"}. {"Name","Όνομα"}. {"Never","Ποτέ"}. {"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","Ταυτότητα Κόμβου"}. {"Node not found","Κόμβος δεν βÏέθηκε"}. {"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","Ειδοποιηση στους συνδÏομητές όταν ο κόμβος διαγÏάφεται"}. {"November","ÎοέμβÏιος"}. {"Number of occupants","ΑÏιθμός συμετεχόντων"}. {"Number of online users","ΑÏιθμός συνδεδεμένων χÏηστών"}. {"Number of registered users","ΑÏιθμός εγγεγÏαμμένων χÏηστών"}. {"October","ΟκτώβÏιος"}. {"Offline Messages:","ΧωÏίς ΣÏνδεση ΜηνÏματα:"}. {"Offline Messages","ΧωÏίς ΣÏνδεση ΜηνÏματα"}. {"OK","Όλλα Καλά"}. {"Old Password:","Παλαιός κωδικός Ï€Ïόσβασης:"}. {"Online Users:","Online ΧÏήστες:"}. {"Online Users","Συνδεμένοι χÏήστες"}. {"Online","Συνδεδεμένο"}. {"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 Συνδέσεις"}. {"Owner privileges required","AπαιτοÏνται Ï€Ïονόμια ιδιοκτήτη"}. {"Packet","Πακέτο"}. {"Password ~b","Κωδικός Ï€Ïόσβασης ~b"}. {"Password Verification:","Επαλήθευση ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης:"}. {"Password Verification","Επαλήθευση ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης"}. {"Password","Κωδικός ΠÏόσβασης"}. {"Password:","Κωδικός Ï€Ïόσβασης:"}. {"Path to Dir","Τοποθεσία κατάλογου αÏχείων"}. {"Path to File","Τοποθεσία ΑÏχείου"}. {"Pending","ΕκκÏεμεί"}. {"Period: ","ΠεÏίοδος: "}. {"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","ΘÏÏα"}. {"Present real Jabber IDs to","ΠαÏοÏσιαση Ï€Ïαγματικών ταυτοτήτων Jabber σε"}. {"private, ","ιδιωτικό,"}. {"Protocol","ΠÏωτόκολλο"}. {"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","ΕγγεγÏαμμένοι ΧÏήστες"}. {"Register","ΚαταχωÏήστε"}. {"Registration in mod_irc for ","ΕγγÏαφή στο mod_irc για "}. {"Remote copy","ΑπομεμακÏυσμένο αντίγÏαφο"}. {"Remove All Offline Messages","ΑφαίÏεση Όλων των ΧωÏίς ΣÏνδεση ΜηνÏματων"}. {"Remove User","ΑφαίÏεση χÏήστη"}. {"Remove","ΑφαίÏεστε"}. {"Replaced by new connection","Αντικαταστάθικε από νέα σÏνδεση"}. {"Resources","ΠόÏοι"}. {"Restart Service","Επανεκκίνηση ΥπηÏεσίας"}. {"Restart","Επανεκκίνηση"}. {"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 creation is denied by service policy","ΆÏνηση δημιουÏγίας αίθουσας , λόγω τακτικής παÏοχής υπηÏεσιών"}. {"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","Script ελέγχου"}. {"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","Αποστολή ανακοίνωσης σε όλους τους χÏήστες"}. {"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","ΟÏίστε μήνυμα ημέÏας και άμεση αποστολή στους συνδεδεμένους χÏήστες σε όλους τους κεντÏικοÏÏ‚ υπολογιστές"}. {"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 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 ","Εκκίνηση Modules στο "}. {"Start Modules","Εκκίνηση Modules"}. {"Start","Εκκίνηση"}. {"Statistics of ~p","Στατιστικές του ~p"}. {"Statistics","Στατιστικές"}. {"Stop Modules at ","ΠαÏση Modules στο "}. {"Stop Modules","ΠαÏσηModules"}. {"Stopped Nodes","Σταματημένοι Κόμβοι"}. {"Stop","Σταμάτημα"}. {"Storage Type","ΤÏπος Αποθήκευσης"}. {"Store binary backup:","ΑποθηκεÏση Î´Ï…Î±Î´Î¹ÎºÎ¿Ï Î±Î½Ï„Î¹Î³Ïάφου ασφαλείας:"}. {"Store plain text backup:","ΑποθηκεÏση αντιγÏάφου ασφαλείας σε αÏχείο κειμένου:"}. {"Subject","Θέμα"}. {"Submitted","Υποβλήθηκε"}. {"Submit","Υποβοβολή"}. {"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: ","ΥπήÏξε ένα σφάλμα κατά την αλλαγή του ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης:"}. {"There was an error creating the account: ","ΥπήÏξε ένα σφάλμα κατά τη δημιουÏγία του λογαÏιασμοÏ:"}. {"There was an error deleting the account: ","ΥπήÏξε ένα σφάλμα κατά τη διαγÏαφή του λογαÏιασμοÏ:"}. {"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."}. {"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","ΚαταÏγήση εγγÏαφής"}. {"Update message of the day (don't send)","ΕνημέÏωση μηνÏματως ημέÏας (χωÏίς άμεση αποστολή)"}. {"Update message of the day on all hosts (don't send)","ΕνημέÏωση μηνÏματως ημέÏας σε όλους τους κεντÏικοÏÏ‚ υπολογιστές (χωÏίς άμεση αποστολή)"}. {"Update plan","Σχέδιο ενημέÏωσης"}. {"Update script","ΠÏογÏάμα ενημέÏωσης"}. {"Update","ΕνημέÏωση"}. {"Uptime:","Uptime:"}. {"Use of STARTTLS required","Απαιτείται χÏήση STARTTLS "}. {"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"}. ejabberd-16.01/priv/msgs/it.po0000644000232200023220000014742612645157216016561 0ustar debalancedebalance# Luca Brivio , 2012. msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "PO-Revision-Date: 2012-04-24 16:48+0200\n" "Last-Translator: Luca Brivio \n" "Language-Team: Italian \n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Italian (italiano)\n" "X-Additional-Translator: Gabriele Stilli \n" "X-Additional-Translator: Smart2128\n" "X-Generator: Lokalize 1.2\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Utilizzo di STARTTLS obbligatorio" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nessuna risorsa fornita" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Sostituito da una nuova connessione" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Immettere il testo visibile" #: 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: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:227 msgid "CAPTCHA web page" msgstr "Pagina web CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Il CAPTCHA è valido." #: 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" #: ejabberd_oauth.erl:256 #, fuzzy msgid "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 #: mod_muc_room.erl:3383 mod_register.erl:275 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" msgstr "Non autorizzato" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Amministrazione web ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Amministrazione" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Grezzo" #: 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: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:913 msgid "~s access rule configuration" msgstr "Configurazione delle regole di accesso per ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Host Virtuali" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Utenti" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Utenti online" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Ultima attività degli utenti" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periodo:" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Ultimo mese" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Ultimo anno" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Tutta l'attività" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrare la tabella normale" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrare la tabella integrale" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiche" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Non trovato" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo non trovato" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Aggiungere nuovo" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Utenti registrati" #: 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:1459 msgid "Offline Messages" msgstr "Messaggi offline" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Ultima attività" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Mai" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Online" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Utenti registrati:" #: 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:1556 msgid "Outgoing s2s Connections:" msgstr "Connessioni s2s in uscita:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" msgstr "Connessioni s2s in uscita:" #: 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: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:1673 #, fuzzy msgid "User ~s" msgstr "Utente " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Risorse connesse:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Password:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminare l'utente" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Nessuna informazione" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodi" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodi attivi" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodi arrestati" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nodo " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Salvare" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Porte in ascolto" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aggiornare" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Riavviare" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Arrestare" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduli" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Errore di chiamata RPC" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabelle del database su " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo di conservazione" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementi" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memoria" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Errore" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Salvataggio di " #: 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 "" "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." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Conservare un salvataggio binario:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Recuperare un salvataggio binario adesso:" #: 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:1999 msgid "Store plain text backup:" msgstr "Conservare un salvataggio come semplice testo:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Recuperare un salvataggio come semplice testo adesso:" #: 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: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: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:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: 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:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importare i dati utenti da directory di spool di jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Porte in ascolto su " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduli su " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistiche di ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tempo dall'avvio:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tempo CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transazioni avvenute:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transazioni abortite:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transazioni riavviate:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transazioni con log:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Aggiornare " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Piano di aggiornamento" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Moduli modificati" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script di aggiornamento" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script di aggiornamento di basso livello" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Verifica dello script" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Porta" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocollo" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modulo" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opzioni" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Avviare" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandi" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Si conferma l'eliminazione del messaggio del giorno (MOTD)?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Oggetto" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Corpo del messaggio" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Nessun corpo fornito per il messaggio di annuncio" #: mod_announce.erl:662 msgid "Announcements" msgstr "Annunci" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Inviare l'annuncio a tutti gli utenti" #: 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:668 msgid "Send announcement to all online users" msgstr "Inviare l'annuncio a tutti gli utenti online" #: 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: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: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:676 msgid "Update message of the day (don't send)" msgstr "Aggiornare il messaggio del giorno (MOTD) (non inviarlo)" #: 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:680 msgid "Delete message of the day" msgstr "Eliminare il messaggio del giorno (MOTD)" #: 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:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "Configurazione" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Avviare moduli" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Arrestare moduli" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Recuperare" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Trascrivere su file di testo" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importare un file" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importare una directory" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Riavviare il servizio" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Terminare il servizio" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Eliminare l'utente" #: 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: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:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Cambiare la password dell'utente" #: 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:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Ottenere le statistiche dell'utente" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Ottenere il numero di utenti registrati" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Ottenere il numero di utenti online" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gestione degli utenti" #: mod_configure.erl:525 msgid "All Users" msgstr "Tutti gli utenti" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Connessioni s2s in uscita" #: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestione dei salvataggi" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importare utenti da file di spool di jabberd14" #: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Da ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configurazione delle tabelle del database su " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selezionare una modalità di conservazione delle tabelle" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copia su disco soltanto" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copia in memoria (RAM) e su disco" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copia in memoria (RAM)" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copia remota" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Arrestare moduli su " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selezionare i moduli da arrestare" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Avviare moduli su " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Immettere un elenco di {Modulo, [Opzioni]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Elenco dei moduli da avviare" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Salvataggio sul file " #: 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:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "Percorso del file" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Recuperare il salvataggio dal file " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Trascrivere il salvataggio sul file di testo " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Immettere il percorso del file di testo" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importare un utente dal file " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Immettere il percorso del file di spool di jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importare utenti dalla directory " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Immettere il percorso della directory di spool di jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Percorso della directory" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Ritardo" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configurazione dei diritti di accesso (ACL)" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "Diritti di accesso (ACL)" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configurazione dell'accesso" #: mod_configure.erl:1356 msgid "Access rules" 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: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)" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verifica della password" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Numero di utenti registrati" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "Numero di utenti online" #: mod_configure.erl:1936 msgid "Last login" msgstr "Ultimo accesso" #: mod_configure.erl:1963 msgid "Roster size" msgstr "Dimensione della lista dei contatti" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "Indirizzi IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "Risorse" #: mod_configure.erl:2095 msgid "Administration of " msgstr "Amministrazione di " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Azione sull'utente" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Modificare le proprietà" #: 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_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: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:476 msgid "ejabberd IRC module" msgstr "Modulo IRC per ejabberd" #: 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:653 msgid "Registration in mod_irc for " msgstr "Registrazione in mod_irc per " #: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" 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:667 msgid "IRC Username" msgstr "Nome utente IRC" #: 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." msgstr "" "Se si vogliono specificare differenti porte, password, codifiche per i " "server IRC, si riempia questo elenco con valori nel formato '{\"server IRC" "\", \"codifica\", porta, \"password\"}'. Per default questo servizio " "utilizza la codifica \"~s\", la porta ~p, la password vuota." #: 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 "" "Esempio: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"segreto\"}, {\"vendetta." "fef.net\", \"iso8859-1\", 7000}, {\"irc.serverdiprova.net\", \"utf-8\"}]." #: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parametri delle connessioni" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Entra nel canale IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canale IRC (senza il # iniziale)" #: mod_irc.erl:903 msgid "IRC server" msgstr "Server IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Entra nel canale IRC qui." #: 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:1046 msgid "IRC settings" msgstr "Impostazioni IRC" #: 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 "" "Immettere il nome utente e le codifiche che si desidera utilizzare per la " "connessione ai server IRC. Premere \"Avanti\" per vedere i successivi campi " "da compilare. Premere \"Fatto\" per salvare le impostazioni." #: mod_irc.erl:1060 msgid "IRC username" msgstr "Nome utente IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Password ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Porta ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codifica per il server ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" #: 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: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:941 msgid "Nickname Registration at " msgstr "Registrazione di un nickname su " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "Nickname" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Stanze" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "esce dalla stanza" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Utenti registrati" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Configurazione della stanza modificata" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "entra nella stanza" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "esce dalla stanza" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "è stata/o bandita/o" #: 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: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:445 msgid "has been kicked because of a system shutdown" msgstr "è stato espulso a causa dello spegnimento del sistema" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "è ora conosciuta/o come" #: 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:493 msgid "Chatroom is created" msgstr "La stanza è creata" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "La stanza è eliminata" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "La stanza è avviata" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "La stanza è arrestata" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Lunedì" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Martedì" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Mercoledì" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Giovedì" #: mod_muc_log.erl:507 msgid "Friday" msgstr "Venerdì" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sabato" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "Domenica" #: mod_muc_log.erl:513 msgid "January" msgstr "Gennaio" #: mod_muc_log.erl:514 msgid "February" msgstr "Febbraio" #: mod_muc_log.erl:515 msgid "March" msgstr "Marzo" #: mod_muc_log.erl:516 msgid "April" msgstr "Aprile" #: mod_muc_log.erl:517 msgid "May" msgstr "Maggio" #: mod_muc_log.erl:518 msgid "June" msgstr "Giugno" #: mod_muc_log.erl:519 msgid "July" msgstr "Luglio" #: mod_muc_log.erl:520 msgid "August" msgstr "Agosto" #: mod_muc_log.erl:521 msgid "September" msgstr "Settembre" #: mod_muc_log.erl:522 msgid "October" msgstr "Ottobre" #: mod_muc_log.erl:523 msgid "November" msgstr "Novembre" #: mod_muc_log.erl:524 msgid "December" msgstr "Dicembre" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configurazione della stanza" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Presenti nella stanza" #: 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" msgstr "" "La modifica dell'oggetto di questa stanza è consentita soltanto ai " "moderatori e ai partecipanti" #: 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: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:2772 msgid "Nickname ~s does not exist in the room" msgstr "Il nickname ~s non esiste nella stanza" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Affiliazione non valida: ~s" #: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ruolo non valido: ~s" #: 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:3359 msgid "Room title" msgstr "Titolo della stanza" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descrizione della stanza" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Rendere la stanza persistente" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Rendere la sala visibile al pubblico" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Rendere pubblica la lista dei partecipanti" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Rendere la stanza protetta da password" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Numero massimo di occupanti" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Nessun limite" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Rendere visibile il Jabber ID reale a" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderatori soltanto" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "tutti" #: 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:3516 msgid "Make room moderated" msgstr "Rendere la stanza moderata" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Definire per default gli utenti come partecipanti" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Consentire agli utenti di cambiare l'oggetto" #: 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:3533 msgid "Allow visitors to send private messages to" msgstr "Consentire agli ospiti l'invio di messaggi privati a" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "nessuno" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Consentire agli utenti query verso altri utenti" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Consentire agli utenti l'invio di inviti" #: 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:3586 msgid "Allow visitors to change nickname" msgstr "Consentire ai visitatori di cambiare il nickname" #: 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:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervallo minimo fra due richieste di parola (in secondi)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Rendere la stanza protetta da CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Escludi degli ID Jabber dal passaggio CAPTCHA" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Abilitare i log" #: 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:4190 msgid "Number of occupants" msgstr "Numero di presenti" #: mod_muc_room.erl:4260 msgid "private, " msgstr "privato, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Richiesta di parola" #: 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:4349 msgid "User JID" msgstr "JID utente" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Dare parola a questa persona?" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s ti invita nella stanza ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "la password è" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "Ora" #: mod_offline.erl:812 msgid "From" msgstr "Da" #: mod_offline.erl:813 msgid "To" msgstr "A" #: mod_offline.erl:814 msgid "Packet" msgstr "Pacchetto" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Messaggi offline:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Eliminare tutti i messaggi offline" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Modulo SOCKS5 Bytestreams per ejabberd" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Pubblicazione-Iscrizione" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Modulo Pubblicazione/Iscrizione (PubSub) per ejabberd" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Richiesta di iscrizione per PubSub" #: 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:1559 msgid "Node ID" msgstr "ID del nodo" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Indirizzo dell'iscritta/o" #: 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:3745 msgid "Deliver payloads with event notifications" msgstr "Inviare il contenuto del messaggio con la notifica dell'evento" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Inviare notifiche degli eventi" #: 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:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificare gli iscritti quando il nodo è cancellato" #: 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:3755 msgid "Persist items to storage" msgstr "Conservazione persistente degli elementi" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nome comodo per il nodo" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Numero massimo di elementi da conservare persistentemente" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Consentire iscrizioni?" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Specificare il modello di accesso" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Gruppi roster abilitati alla registrazione" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Definire il modello di pubblicazione" #: 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:3771 msgid "Specify the event message type" msgstr "Specificare il tipo di messaggio di evento" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Dimensione massima del contenuto del messaggio in byte" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Quando inviare l'ultimo elemento pubblicato" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Inviare le notifiche solamente agli utenti disponibili" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Le collezioni a cui è affiliato un nodo" #: 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: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." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Si è verificato un errore nella creazione dell'account: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "La cancellazione del tuo account Jabber è andata a buon fine." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Si è verificato un errore nella cancellazione dell'account: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Il cambio di password del tuo account Jabber è andato a buon fine." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Si è verificato un errore nel cambio di password: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Registrazione account Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Registra un account Jabber" #: 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" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "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." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nome utente:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" "Non fa differenza fra minuscolo e maiuscolo: macbeth, MacBeth e Macbeth si " "equivalgono." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Caratteri non consentiti:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Non comunicare la tua password a nessuno, neppure agli amministratori del " "server Jabber." #: 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: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 "" "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: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 "" "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." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verifica della password:" #: mod_register_web.erl:269 msgid "Register" msgstr "Registra" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Vecchia password:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Nuova password:" #: 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:480 msgid "Unregister" msgstr "Elimina" #: mod_roster.erl:1436 msgid "Subscription" msgstr "Iscrizione" #: mod_roster.erl:1437 msgid "Pending" msgstr "Pendente" #: mod_roster.erl:1438 msgid "Groups" msgstr "Gruppi" #: mod_roster.erl:1476 msgid "Validate" msgstr "Validare" #: mod_roster.erl:1485 msgid "Remove" msgstr "Eliminare" #: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista dei contatti di " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Aggiungere un Jabber ID (Jabber ID)" #: mod_roster.erl:1622 msgid "Roster" msgstr "Lista dei contatti" #: 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:1232 msgid "Name:" msgstr "Nome:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descrizione:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membri:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Gruppi visualizzati:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Gruppo " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Compleanno" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Città" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Paese" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-mail" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Cognome" #: 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 "" "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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nome completo" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Altro nome" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nome dell'organizzazione" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unità dell'organizzazione" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Cercare utenti in " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Ricerca di utenti per vCard" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Modulo vCard per ejabberd" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Risultati della ricerca per " #: 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 "Outgoing s2s Servers:" #~ msgstr "Server s2s in uscita" #~ msgid "Delete" #~ msgstr "Eliminare" #~ msgid "This room is not anonymous" #~ msgstr "Questa stanza non è anonima" #~ 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 "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Partecipante espulso dalla stanza perché ha inviato un messaggio non " #~ "valido a un altro partecipante" #~ 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" #, fuzzy #~ msgid "CAPTCHA test failed" #~ msgstr "Il CAPTCHA è valido." ejabberd-16.01/priv/msgs/tr.msg0000644000232200023220000006574012645157216016740 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","EriÅŸim Ayarları"}. {"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"}. {"Add Jabber ID","Jabber ID'si Ekle"}. {"Add New","Yeni Ekle"}. {"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?"}. {"Allow users to change the subject","Kullanıcıların konu deÄŸiÅŸtirmesine izin ver"}. {"Allow users to query other users","Kullanıcıların diÄŸer kullanıcıları sorgulamalarına izin ver"}. {"Allow users to send invites","Kullanıcıların davetiye göndermelerine izin ver"}. {"Allow users to send private messages","Kullanıcıların özel mesaj göndermelerine izin ver"}. {"Allow visitors to change nickname","Ziyaretçilerin takma isim deÄŸiÅŸtirmelerine izin ver"}. {"Allow visitors to send private messages to","Ziyaretçilerin özel mesaj göndermelerine izin ver"}. {"Allow visitors to send status text in presence updates","Ziyaretçilerin varlık (presence) güncellemelerinde durum metni göndermelerine izin ver"}. {"Allow visitors to send voice requests","Ziyaretçilerin ses isteÄŸine göndermelerine izin ver"}. {"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"}. {"Backup to File at ","Dosyaya Yedekle : "}. {"Backup","Yedekle"}. {"Bad format","Kötü biçem"}. {"Birthday","DoÄŸumgünü"}. {"CAPTCHA web page","CAPTCHA web sayfası"}. {"Change Password","Parola DeÄŸiÅŸtir"}. {"Change User Password","Kullanıcı Parolasını DeÄŸiÅŸtir"}. {"Characters not allowed:","İzin verilmeyen karakterler:"}. {"Chatroom configuration modified","Sohbet odası ayarı deÄŸiÅŸtirildi"}. {"Chatroom is created","Sohbet odası oluÅŸturuldu"}. {"Chatroom is destroyed","Sohbet odası kaldırıldı"}. {"Chatroom is started","Sohbet odası baÅŸlatıldı"}. {"Chatroom is stopped","Sohbet odası durduruldu"}. {"Chatrooms","Sohbet Odaları"}. {"Choose a username and password to register with this server","Bu sunucuya kayıt olmak için bir kullanıcı ismi ve parola seçiniz"}. {"Choose modules to stop","Durdurulacak modülleri seçiniz"}. {"Choose storage type of tables","Tabloların veri depolama tipini seçiniz"}. {"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:"}. {"Connections parameters","BaÄŸlantı parametreleri"}. {"Country","Ülke"}. {"CPU Time:","İşlemci Zamanı:"}. {"Database Tables Configuration at ","Veritabanı Tablo Ayarları : "}. {"Database","Veritabanı"}. {"December","Aralık"}. {"Default users as participants","Kullanıcılar öntanımlı olarak katılımcı olsun"}. {"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 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"}. {"Description:","Tanım:"}. {"Disc only copy","Sadece disk kopyala"}. {"Displayed Groups:","Gösterilen Gruplar:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Parolanızı kimseye söylemeyin, Jabber sunucusunun yöneticilerine bile."}. {"Dump Backup to Text File at ","Metin Dosyasına Döküm Alarak Yedekle : "}. {"Dump to Text File","Metin Dosyasına Döküm Al"}. {"Edit Properties","Özellikleri Düzenle"}. {"Either approve or decline the voice request.","Ses isteÄŸini kabul edin ya da reddedin"}. {"ejabberd IRC module","ejabberd IRC modülü"}. {"ejabberd MUC module","ejabberd MUC modülü"}. {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modülü"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modülü"}. {"ejabberd vCard module","ejabberd vCard modülü"}. {"ejabberd Web Admin","ejabberd Web Yöneticisi"}. {"Elements","Elementler"}. {"Email","E-posta"}. {"Enable logging","Kayıt tutma özelliÄŸini aç"}. {"Encoding for server ~b","Sunucu için kodlama ~b"}. {"End User Session","Kullanıcı Oturumunu Kapat"}. {"Enter list of {Module, [Options]}","{Module, [Options]} listesi giriniz"}. {"Enter nickname you want to register","Kaydettirmek istediÄŸiniz takma ismi giriniz"}. {"Enter path to backup file","Yedek dosyasının yolunu giriniz"}. {"Enter path to jabberd14 spool dir","jabberd14 spool dosyası için yol giriniz"}. {"Enter path to jabberd14 spool file","jabberd14 spool dosyası için yol giriniz"}. {"Enter path to text file","Metin dosyasının yolunu giriniz"}. {"Enter the text you see","Gördüğünüz metni giriniz"}. {"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 sunuculara baÄŸlanmak için kullanmak istediÄŸiniz kullanıcı isimleri ve kodlamaları giriniz. 'İleri' tuÅŸuna basınca karşınıza dolduracak daha fazla alan çıkacak. 'Tamamla' tuÅŸuna basarak ayarları kaydedin."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","IRC sunuculara baÄŸlanmak için kullanmak istediÄŸiniz kullanıcı ismi, kodlamalar, kapılar (portlar) ve parolaları giriniz"}. {"Erlang Jabber Server","Erlang Jabber Sunucusu"}. {"Error","Hata"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Örnek: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"gizli\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}], {\"irc.sometestserver.net\", \"utf-8\"}]"}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","EÅŸleÅŸen jabber kullanıcılarını aramak için formu doldurunuz (Alt dizgi eÅŸlemek için alanın sonuna * ekleyin)"}. {"Friday","Cuma"}. {"From","Kimden"}. {"From ~s","Kimden ~s"}. {"Full Name","Tam İsim"}. {"Get Number of Online Users","BaÄŸlı Kullanıcı Sayısını Al"}. {"Get Number of Registered Users","Kayıtlı Kullanıcı Sayısını Al"}. {"Get User Last Login Time","Kullanıcı Son GiriÅŸ Zamanınlarını Al"}. {"Get User Password","Kullanıcı Parolasını Al"}. {"Get User Statistics","Kullanıcı İstatistiklerini Al"}. {"Grant voice to this person?","Bu kiÅŸiye ses verelim mi?"}. {"Group ","Group "}. {"Groups","Gruplar"}. {"has been banned","odaya girmesi yasaklandı"}. {"has been kicked because of an affiliation change","iliÅŸki deÄŸiÅŸikliÄŸinden dolayı atıldı"}. {"has been kicked because of a system shutdown","sistem kapandığından dolayı atıldı"}. {"has been kicked because the room has been changed to members-only","oda üyelere-özel hale getirildiÄŸinden dolayı atıldı"}. {"has been kicked","odadan atıldı"}. {" has set the subject to: "," konuyu deÄŸiÅŸtirdi: "}. {"Host","Sunucu"}. {"If you don't see the CAPTCHA image here, visit the web page.","EÄŸer burada CAPTCHA resmini göremiyorsanız, web sayfasını ziyaret edin."}. {"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 sunucuları için farklı kapılar (portlar), parolalar, kodlamalar belirtmek istiyorsanız, '{\"irc sunucusu\", \"kodlama\",\"kapı\",\"parola\"}' biçeminde deÄŸerlerle bu listeyi doldurunuz. Öntanımlı olarak bu servis \"~s\" kodlamasını, ~p \"kapısını\", \"boÅŸ\" parolasını kullanıyor."}. {"Import Directory","Dizini İçe Aktar"}. {"Import File","Dosyayı İçe Aktar"}. {"Import user data from jabberd14 spool file:","Jabberd 1.4 Spool Dosyalarından Kullanıcıları İçe Aktar:"}. {"Import User from File at ","Dosyadan Kullanıcıları İçe Aktar : "}. {"Import users data from a PIEFXIS file (XEP-0227):","Kullanıcıları bir PIEFXIS dosyasından (XEP-0227) içe aktar:"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","IRC kanalı (ilk # iÅŸaretini koymayın)"}. {"IRC server","IRC sunucusu"}. {"IRC settings","IRC ayarları"}. {"IRC Transport","IRC Nakli (Transport)"}. {"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"}. {"January","Ocak"}. {"Join IRC channel","IRC kanalına katıl"}. {"joins the room","odaya katıldı"}. {"Join the IRC channel here.","Buradaki IRC kanalına katıl."}. {"Join the IRC channel in this Jabber ID: ~s","IRC kanalına bu Jabber ID'si ile katıl: ~s"}. {"July","Temmuz"}. {"June","Haziran"}. {"Last Activity","Son Aktivite"}. {"Last login","Son giriÅŸ"}. {"Last month","Geçen ay"}. {"Last year","Geçen yıl"}. {"leaves the room","odadan ayrıldı"}. {"Listened Ports at ","Dinlenen Kapılar (Portlar) : "}. {"Listened Ports","Dinlenen Kapılar (Portlar)"}. {"List of modules to start","BaÅŸlatılacak modüllerin listesi"}. {"Low level update script","Düşük seviye güncelleme betiÄŸi"}. {"Make participants list public","Katılımcı listesini herkese açık hale getir"}. {"Make room CAPTCHA protected","Odayı insan doÄŸrulaması (captcha) korumalı hale getir"}. {"Make room members-only","Odayı sadece üyelere açık hale getir"}. {"Make room moderated","Odayı moderasyonlu hale getir"}. {"Make room password protected","Odayı parola korumalı hale getir"}. {"Make room persistent","Odayı kalıcı hale getir"}. {"Make room public searchable","Odayı herkes tarafından aranabilir hale getir"}. {"March","Mart"}. {"Maximum Number of Occupants","Odada En Fazla Bulunabilecek KiÅŸi Sayısı"}. {"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"}. {"Modules","Modüller"}. {"Monday","Pazartesi"}. {"Name:","İsim:"}. {"Name","İsim"}. {"Never","Asla"}. {"New Password:","Yeni Parola:"}. {"Nickname Registration at ","Takma İsim Kaydı : "}. {"Nickname ~s does not exist in the room","~s takma ismi odada yok"}. {"Nickname","Takma isim"}. {"nobody","hiç kimse"}. {"No body provided for announce message","Duyuru mesajının gövdesi yok"}. {"No Data","Veri Yok"}. {"Node ID","Düğüm ID"}. {"Node not found","Düğüm bulunamadı"}. {"Nodes","Düğümler"}. {"No limit","Sınırsız"}. {"None","Hiçbiri"}. {"No resource provided","Hiç kaynak saÄŸlanmadı"}. {"Not Found","Bulunamadı"}. {"Notify subscribers when items are removed from the node","Düğümden öğeler kaldırıldığında üyeleri uyar"}. {"Notify subscribers when the node configuration changes","Düğüm ayarları deÄŸiÅŸtiÄŸinde üyeleri uyar"}. {"Notify subscribers when the node is deleted","Bir düğüm silindiÄŸinde üyeleri uyar"}. {"November","Kasım"}. {"Number of occupants","Oda sakini sayısı"}. {"Number of online users","BaÄŸlı kullanıcı sayısı"}. {"Number of registered users","Kayıtlı kullanıcı sayısı"}. {"October","Ekim"}. {"Offline Messages:","Çevirim-dışı Mesajlar:"}. {"Offline Messages","Çevirim-dışı Mesajlar"}. {"OK","Tamam"}. {"Old Password:","Eski Parola:"}. {"Online","BaÄŸlı"}. {"Online Users:","BaÄŸlı Kullanıcılar:"}. {"Online Users","BaÄŸlı Kullanıcılar"}. {"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ı"}. {"Owner privileges required","Sahip yetkileri gerekli"}. {"Packet","Paket"}. {"Password ~b","Parola ~b"}. {"Password:","Parola:"}. {"Password","Parola"}. {"Password Verification:","Parola DoÄŸrulaması:"}. {"Password Verification","Parola DoÄŸrulaması"}. {"Path to Dir","Dizinin Yolu"}. {"Path to File","Dosyanın Yolu"}. {"Pending","Sıra Bekleyen"}. {"Period: ","Periyot:"}. {"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)"}. {"Present real Jabber IDs to","Gerçek Jabber ID'lerini göster :"}. {"private, ","özel"}. {"Protocol","Protokol"}. {"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"}. {"Register","Kayıt Ol"}. {"Registration in mod_irc for ","mod_irc'ye kayıt : "}. {"Remote copy","Uzak kopyala"}. {"Remove All Offline Messages","Tüm Çevirim-dışı Mesajları Kaldır"}. {"Remove","Kaldır"}. {"Remove User","Kullanıcıyı Kaldır"}. {"Replaced by new connection","Eski baÄŸlantı yenisi ile deÄŸiÅŸtirildi"}. {"Resources","Kaynaklar"}. {"Restart Service","Servisi Tekrar BaÅŸlat"}. {"Restart","Tekrar BaÅŸlat"}. {"Restore Backup from File at ","Dosyadaki Yedekten Geri Al : "}. {"Restore binary backup after next ejabberd restart (requires less memory):","ejabberd'nin bir sonraki tekrar baÅŸlatılışında ikili yedekten geri al (daha az bellek gerektirir)"}. {"Restore binary backup immediately:","Hemen ikili yedekten geri al:"}. {"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ığı"}. {"Roster groups allowed to subscribe","Üye olunmasına izin verilen kontak listesi grupları"}. {"Roster","Kontak Listesi"}. {"Roster of ","Kontak Listesi : "}. {"Roster size","İsim listesi boyutu"}. {"RPC Call Error","RPC ÇaÄŸrı Hatası"}. {"Running Nodes","Çalışan Düğümler"}. {"~s access rule configuration","~s eriÅŸim kuralları ayarları"}. {"Saturday","Cumartesi"}. {"Script check","Betik kontrolü"}. {"Search Results for ","Arama sonuçları : "}. {"Search users in ","Kullanıcılarda arama yap : "}. {"Send announcement to all online users","Duyuruyu tüm baÄŸlı kullanıcılara yolla"}. {"Send announcement to all online users on all hosts","Duyuruyu tüm sunuculardaki tüm baÄŸlı kullanıcılara yolla"}. {"Send announcement to all users","Duyuruyu tüm kullanıcılara yolla"}. {"Send announcement to all users on all hosts","Tüm sunuculardaki tüm kullanıcılara duyuru yolla"}. {"September","Eylül"}. {"Server ~b","Sunucu ~b"}. {"Server:","Sunucu:"}. {"Set message of the day and send to online users","Günün mesajını belirle"}. {"Set message of the day on all hosts and send to online users","Tüm sunucularda günün mesajını belirle ve baÄŸlı tüm kullanıcılara gönder"}. {"Shared Roster Groups","Paylaşımlı Kontak Listesi Grupları"}. {"Show Integral Table","Önemli Tabloyu Göster"}. {"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 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"}. {"~s's Offline Messages Queue","~s Kullanıcısının Mesaj KuyruÄŸu"}. {"Start","BaÅŸlat"}. {"Start Modules at ","Modülleri BaÅŸlat : "}. {"Start Modules","Modülleri BaÅŸlat"}. {"Statistics","İstatistikler"}. {"Statistics of ~p","~p istatistikleri"}. {"Stop","Durdur"}. {"Stop Modules at ","Modülleri Durdur : "}. {"Stop Modules","Modülleri Durdur"}. {"Stopped Nodes","DurdurulmuÅŸ Düğümler"}. {"Storage Type","Depolama Tipi"}. {"Store binary backup:","İkili yedeÄŸi sakla:"}. {"Store plain text backup:","Düz metin yedeÄŸi sakla:"}. {"Subject","Konu"}. {"Submit","Gönder"}. {"Submitted","Gönderilenler"}. {"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:"}. {"There was an error deleting the account: ","Hesabın silinmesi sırasında bir hata oluÅŸtu:"}. {"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."}. {"Thursday","PerÅŸembe"}. {"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"}. {"Update","GÜncelle"}. {"Update message of the day (don't send)","Günün mesajını güncelle (gönderme)"}. {"Update message of the day on all hosts (don't send)","Tüm sunuculardaki günün mesajını güncelle (gönderme)"}. {"Update plan","Planı güncelle"}. {"Update script","BetiÄŸi Güncelle"}. {"Uptime:","Hizmet Süresi:"}. {"Use of STARTTLS required","STARTTLS kullanımı gereklidir"}. {"User JID","Kullanıcı JID"}. {"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."}. ejabberd-16.01/priv/msgs/th.po0000644000232200023220000017251612645157216016556 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "Last-Translator: EQHO Communications (Thailand) Ltd. - http://www.eqho.com\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Thai (ภาษาไทย)\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "ต้องใช้ STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "ไม่ได้ระบุข้อมูล" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "à¹à¸—นที่ด้วยà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•่อใหม่" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 #, fuzzy msgid "Enter the text you see" msgstr "ป้อนพาธของไฟล์ข้อความ" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" #: 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 "ผู้ใช้" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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 #, fuzzy msgid "ejabberd Web Admin" msgstr "เว็บอินเทอร์เฟซของ ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "à¸à¸²à¸£à¸”ูà¹à¸¥" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "ข้อมูลดิบ" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "à¸à¸Žà¸à¸²à¸£à¹€à¸‚้าถึง" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าà¸à¸Žà¸à¸²à¸£à¹€à¸‚้าถึง" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "โฮสต์เสมือน" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "ผู้ใช้" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "ผู้ใช้ออนไลน์" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸¥à¹ˆà¸²à¸ªà¸¸à¸”ของผู้ใช้" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "ระยะเวลา:" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "เดือนที่à¹à¸¥à¹‰à¸§" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "ปีที่à¹à¸¥à¹‰à¸§" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸—ั้งหมด" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "à¹à¸ªà¸”งตารางทั่วไป" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "à¹à¸ªà¸”งตารางรวม" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "สถิติ" #: ejabberd_web_admin.erl:1014 #, fuzzy msgid "Not Found" msgstr "ไม่พบโหนด" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "ไม่พบโหนด" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "เพิ่มผู้ใช้ใหม่" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "โฮสต์" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "ผู้ใช้ที่ลงทะเบียน" #: 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:1459 msgid "Offline Messages" msgstr "ข้อความออฟไลน์" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸¥à¹ˆà¸²à¸ªà¸¸à¸”" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "ไม่เคย" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "ออนไลน์" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "ผู้ใช้ที่ลงทะเบียน:" #: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 #: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "ผู้ใช้ออนไลน์:" #: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•่อ s2s ขาออà¸:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" 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 msgid "None" msgstr "ไม่มี" #: 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:1673 #, fuzzy msgid "User ~s" msgstr "ผู้ใช้" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "ทรัพยาà¸à¸£à¸—ี่เชื่อมต่อ:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "รหัสผ่าน:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "ลบผู้ใช้" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "ไม่มีข้อมูล" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "โหนด" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "โหนดที่ทำงาน" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "โหนดที่หยุด" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "โหนด " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "à¸à¸²à¸™à¸‚้อมูล" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "à¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูล " #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "พอร์ทฟัง" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "อัพเดต" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "เริ่มต้นใหม่" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "หยุด" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "โมดูล" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "ข้อผิดพลาดจาà¸à¸à¸²à¸£à¹€à¸£à¸µà¸¢à¸à¹ƒà¸Šà¹‰ RPC" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "ตารางà¸à¸²à¸™à¸‚้อมูลที่" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "ชื่อ" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "ชนิดที่เà¸à¹‡à¸šà¸‚้อมูล" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "หน่วยความจำ" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "à¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูล" #: 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 " "separately." msgstr "" "โปรดทราบว่าตัวเลือà¸à¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¸ˆà¸°à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูลในà¸à¸²à¸™à¸‚้อมูล builtin Mnesia เท่านั้น หาà¸à¸„ุณใช้โมดูล " "ODBC คุณต้องสำรองข้อมูลของà¸à¸²à¸™à¸‚้อมูล SQL à¹à¸¢à¸à¸•่างหาà¸à¸”้วย" #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "จัดเà¸à¹‡à¸šà¸‚้อมูลสำรองà¹à¸šà¸šà¹„บนารี:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "คืนค่าข้อมูลสำรองà¹à¸šà¸šà¹„บนารีโดยทันที:" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "คืนค่าข้อมูลสำรองà¹à¸šà¸šà¹„บนารีหลังจาà¸à¸—ี่ ejabberd ถัดไปเริ่มà¸à¸²à¸£à¸—ำงานใหม่ (ใช้หน่วยความจำน้อยลง):" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "จัดเà¸à¹‡à¸šà¸‚้อมูลสำรองที่เป็นข้อความธรรมดา:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "คืนค่าข้อมูลสำรองที่เป็นข้อความธรรมดาโดยทันที:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: ejabberd_web_admin.erl:2076 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "อิมพอร์ตผู้ใช้จาà¸à¹„ฟล์เà¸à¹‡à¸šà¸žà¸±à¸à¸‚้อมูล jabberd14" #: ejabberd_web_admin.erl:2087 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "อิมพอร์ตผู้ใช้จาà¸à¹„ฟล์เà¸à¹‡à¸šà¸žà¸±à¸à¸‚้อมูล jabberd14" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "พอร์ทฟังที่" #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "โมดูลที่ " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "สถิติของ ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "เวลาà¸à¸²à¸£à¸—ำงานต่อเนื่อง:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "เวลาà¸à¸²à¸£à¸—ำงานของ CPU:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "ทรานà¹à¸‹à¸à¸Šà¸±à¸™à¸—ี่ได้รับมอบหมาย:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "ทรานà¹à¸‹à¸à¸Šà¸±à¸™à¸—ี่ถูà¸à¸¢à¸à¹€à¸¥à¸´à¸:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "ทรานà¹à¸‹à¸à¸Šà¸±à¸™à¸—ี่เริ่มทำงานใหม่อีà¸à¸„รั้ง:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "ทรานà¹à¸‹à¸à¸Šà¸±à¸™à¸—ี่บันทึà¸:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "อัพเดต " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "à¹à¸œà¸™à¸à¸²à¸£à¸­à¸±à¸žà¹€à¸”ต" #: ejabberd_web_admin.erl:2255 #, fuzzy msgid "Modified modules" msgstr "โมดูลที่อัพเดต" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "อัพเดตสคริปต์" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "อัพเดตสคริปต์ระดับต่ำ" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "ตรวจสอบคริปต์" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "พอร์ท" #: ejabberd_web_admin.erl:2439 #, fuzzy msgid "Protocol" msgstr "พอร์ท" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "โมดูล" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "ตัวเลือà¸" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "เริ่ม" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "คำสั่ง" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸²à¸•้องà¸à¸²à¸£à¸¥à¸šà¸‚้อความของวันหรือไม่" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "หัวเรื่อง" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "เนื้อหาของข้อความ" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "ไม่ได้ป้อนเนื้อหาสำหรับข้อความที่ประà¸à¸²à¸¨" #: mod_announce.erl:662 msgid "Announcements" msgstr "ประà¸à¸²à¸¨" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "ส่งประà¸à¸²à¸¨à¸–ึงผู้ใช้ทั้งหมด" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "ส่งประà¸à¸²à¸¨à¸–ึงผู้ใช้ทั้งหมดบนโฮสต์ทั้งหมด" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "ส่งประà¸à¸²à¸¨à¸–ึงผู้ใช้ออนไลน์ทั้งหมด" #: 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:672 msgid "Set message of the day and send to online users" msgstr "ตั้งค่าข้อความของวันà¹à¸¥à¸°à¸ªà¹ˆà¸‡à¸–ึงผู้ใช้ออนไลน์" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "ตั้งค่าข้อความของวันบนโฮสต์ทั้งหมดà¹à¸¥à¸°à¸ªà¹ˆà¸‡à¸–ึงผู้ใช้ออนไลน์" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "อัพเดตข้อความของวัน (ไม่ต้องส่ง)" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "อัพเดตข้อความของวันบนโฮสต์ทั้งหมด (ไม่ต้องส่ง) " #: mod_announce.erl:680 msgid "Delete message of the day" msgstr "ลบข้อความของวัน" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "ลบข้อความของวันบนโฮสต์ทั้งหมด" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่า" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "เริ่มโมดูล" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "หยุดโมดูล" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "à¸à¸²à¸£à¸„ืนค่า" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "ถ่ายโอนข้อมูลไปยังไฟล์ข้อความ" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "อิมพอร์ตไฟล์" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "อิมพอร์ตไดเร็à¸à¸—อรี" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "เริ่มต้นà¸à¸²à¸£à¸šà¸£à¸´à¸à¸²à¸£à¹ƒà¸«à¸¡à¹ˆà¸­à¸µà¸à¸„รั้ง" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "ปิดà¸à¸²à¸£à¸šà¸£à¸´à¸à¸²à¸£" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "ลบผู้ใช้" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "สิ้นสุดเซสชันของผู้ใช้" #: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 #: mod_configure.erl:1473 msgid "Get User Password" msgstr "ขอรับรหัสผ่านของผู้ใช้" #: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "เปลี่ยนรหัสผ่านของผู้ใช้" #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "à¹à¸ªà¸”งเวลาเข้าสู่ระบบครั้งล่าสุดของผู้ใช้" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "à¹à¸ªà¸”งสถิติของผู้ใช้" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "à¹à¸ªà¸”งจำนวนผู้ใช้ที่ลงทะเบียน" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "à¹à¸ªà¸”งจำนวนผู้ใช้ออนไลน์" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "à¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰" #: mod_configure.erl:525 msgid "All Users" msgstr "ผู้ใช้ทั้งหมด" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•่อ s2s ขาออà¸" #: mod_configure.erl:615 msgid "Backup Management" msgstr "à¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£à¸‚้อมูลสำรอง" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "อิมพอร์ตผู้ใช้จาà¸à¹„ฟล์เà¸à¹‡à¸šà¸žà¸±à¸à¸‚้อมูล jabberd14" #: mod_configure.erl:762 msgid "To ~s" msgstr "ถึง ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "จาภ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าตารางà¸à¸²à¸™à¸‚้อมูลที่" #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "เลือà¸à¸Šà¸™à¸´à¸”à¸à¸²à¸£à¸ˆà¸±à¸”เà¸à¹‡à¸šà¸‚องตาราง" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "คัดลอà¸à¹€à¸‰à¸žà¸²à¸°à¸”ิสà¸à¹Œ" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "คัดลอภRAM à¹à¸¥à¸°à¸”ิสà¸à¹Œ" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "คัดลอภRAM" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "คัดลอà¸à¸£à¸°à¸¢à¸°à¹„à¸à¸¥" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "หยุดโมดูลที่" #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "เลือà¸à¹‚มดูลเพื่อหยุดà¸à¸²à¸£à¸—ำงาน" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "เริ่มโมดูลที่" #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "ป้อนรายà¸à¸²à¸£à¸‚อง {โมดูล, [ตัวเลือà¸]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "รายà¸à¸²à¸£à¸‚องโมดูลที่จะเริ่มà¸à¸²à¸£à¸—ำงาน" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "สำรองไฟล์ข้อมูลที่" #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "ป้อนพาธเพื่อสำรองไฟล์ข้อมูล" #: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "พาธของไฟล์ข้อมูล" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "คืนค่าà¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูลจาà¸à¹„ฟล์ที่" #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "ถ่ายโอนà¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูลไปยังไฟล์ข้อความที่" #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "ป้อนพาธของไฟล์ข้อความ" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "อิมพอร์ตผู้ใช้จาà¸à¹„ฟล์ที่" #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "ป้อนพาธไปยังไฟล์เà¸à¹‡à¸šà¸žà¸±à¸à¸‚้อมูล jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "อิมพอร์ตผู้ใช้จาภDir ที่" #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "ป้อนพาธไปยัง jabberd14 spool dir" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "พาธไปยัง Dir" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "à¸à¸²à¸£à¸«à¸™à¹ˆà¸§à¸‡à¹€à¸§à¸¥à¸²" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่ารายà¸à¸²à¸£à¸„วบคุมà¸à¸²à¸£à¹€à¸‚้าถึง" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "รายà¸à¸²à¸£à¸„วบคุมà¸à¸²à¸£à¹€à¸‚้าถึง" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าà¸à¸²à¸£à¹€à¸‚้าถึง" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "à¸à¸²à¸£à¸•รวจสอบรหัสผ่าน" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "จำนวนผู้ใช้ที่ลงทะเบียน" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "จำนวนผู้ใช้ออนไลน์" #: mod_configure.erl:1936 msgid "Last login" msgstr "à¸à¸²à¸£à¹€à¸‚้าสู่ระบบครั้งล่าสุด" #: mod_configure.erl:1963 msgid "Roster size" msgstr "ขนาดของบัà¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "ที่อยู่ IP" #: mod_configure.erl:1967 msgid "Resources" msgstr "ทรัพยาà¸à¸£" #: mod_configure.erl:2095 msgid "Administration of " msgstr "à¸à¸²à¸£à¸”ูà¹à¸¥ " #: mod_configure.erl:2100 msgid "Action on user" msgstr "à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸à¸±à¸šà¸œà¸¹à¹‰à¹ƒà¸Šà¹‰" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "à¹à¸à¹‰à¹„ขคุณสมบัติ" #: 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_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:220 mod_muc.erl:467 msgid "Access denied by service policy" msgstr "à¸à¸²à¸£à¹€à¸‚้าถึงถูà¸à¸›à¸à¸´à¹€à¸ªà¸˜à¹‚ดยนโยบายà¸à¸²à¸£à¸šà¸£à¸´à¸à¸²à¸£" #: mod_irc.erl:439 msgid "IRC Transport" msgstr "à¸à¸²à¸£à¸ªà¹ˆà¸‡ IRC" #: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC module" #: 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:653 msgid "Registration in mod_irc for " msgstr "à¸à¸²à¸£à¸¥à¸‡à¸—ะเบียนใน mod_irc สำหรับ" #: 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:667 msgid "IRC Username" msgstr "ชื่อผู้ใช้ 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 "" "ถ้าคุณต้องà¸à¸²à¸£à¸£à¸°à¸šà¸¸à¸à¸²à¸£à¹€à¸‚้ารหัสที่ต่างà¸à¸±à¸™à¸ªà¸³à¸«à¸£à¸±à¸šà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸­à¸£à¹Œ IRC ให้à¸à¸£à¸­à¸à¸„่าโดยใช้รูปà¹à¸šà¸š '{\"irc " "server\", \"encoding\"}' ลงในรายà¸à¸²à¸£ à¸à¸²à¸£à¸šà¸£à¸´à¸à¸²à¸£à¸™à¸µà¹‰à¹ƒà¸Šà¹‰à¸à¸²à¸£à¹€à¸‚้ารหัสในรูปà¹à¸šà¸š \"~s\" " "โดยค่าดีฟอลต์ " #: 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 "" "ตัวอย่าง: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", " "\"iso8859-1\"}]." #: mod_irc.erl:713 msgid "Connections parameters" msgstr "" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" #: mod_irc.erl:903 #, fuzzy msgid "IRC server" msgstr "ชื่อผู้ใช้ IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "" #: 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 "ป้อนชื่อผู้ใช้à¹à¸¥à¸°à¸à¸²à¸£à¹€à¸‚้ารหัสที่คุณต้องà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸ªà¸³à¸«à¸£à¸±à¸šà¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•่อà¸à¸±à¸šà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸­à¸£à¹Œ IRC" #: mod_irc.erl:1060 #, fuzzy msgid "IRC username" msgstr "ชื่อผู้ใช้ IRC" #: mod_irc.erl:1126 #, fuzzy msgid "Password ~b" msgstr "รหัสผ่าน" #: mod_irc.erl:1137 #, fuzzy msgid "Port ~b" msgstr "พอร์ท" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "" #: 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 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:941 msgid "Nickname Registration at " msgstr "à¸à¸²à¸£à¸¥à¸‡à¸—ะเบียนชื่อเล่นที่ " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "ชื่อเล่น" #: 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" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "ห้องสนทนา" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "ออà¸à¸ˆà¸²à¸à¸«à¹‰à¸­à¸‡" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "ผู้ใช้ที่ลงทะเบียน" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "มีà¸à¸²à¸£à¸›à¸£à¸±à¸šà¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าของห้องสนทนา" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "เข้าห้องสนทนานี้" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "ออà¸à¸ˆà¸²à¸à¸«à¹‰à¸­à¸‡" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "ถูà¸à¸ªà¸±à¹ˆà¸‡à¸«à¹‰à¸²à¸¡" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "ซึ่งรู้จัà¸à¸à¸±à¸™à¹ƒà¸™à¸Šà¸·à¹ˆà¸­" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " ตั้งหัวข้อว่า: " #: mod_muc_log.erl:493 #, fuzzy msgid "Chatroom is created" msgstr "ห้องสนทนา" #: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "ห้องสนทนา" #: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "ห้องสนทนา" #: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "ห้องสนทนา" #: mod_muc_log.erl:503 msgid "Monday" msgstr "วันจันทร์" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "วันอังคาร" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "วันพุธ" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "วันพฤหัสบดี" #: mod_muc_log.erl:507 msgid "Friday" msgstr "วันศุà¸à¸£à¹Œ" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "วันเสาร์" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "วันอาทิตย์" #: mod_muc_log.erl:513 msgid "January" msgstr "มà¸à¸£à¸²à¸„ม" #: mod_muc_log.erl:514 msgid "February" msgstr "à¸à¸¸à¸¡à¸ à¸²à¸žà¸±à¸™à¸˜à¹Œ" #: mod_muc_log.erl:515 msgid "March" msgstr "มีนาคม" #: mod_muc_log.erl:516 msgid "April" msgstr "เมษายน" #: mod_muc_log.erl:517 msgid "May" msgstr "พฤษภาคม" #: mod_muc_log.erl:518 msgid "June" msgstr "มิถุนายน" #: mod_muc_log.erl:519 msgid "July" msgstr "à¸à¸£à¸à¸Žà¸²à¸„ม" #: mod_muc_log.erl:520 msgid "August" msgstr "สิงหาคม" #: mod_muc_log.erl:521 msgid "September" msgstr "à¸à¸±à¸™à¸¢à¸²à¸¢à¸™" #: mod_muc_log.erl:522 msgid "October" msgstr "ตุลาคม" #: mod_muc_log.erl:523 msgid "November" msgstr "พฤศจิà¸à¸²à¸¢à¸™" #: mod_muc_log.erl:524 msgid "December" msgstr "ธันวาคม" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าห้องสนทนา" #: mod_muc_log.erl:932 #, fuzzy msgid "Room Occupants" msgstr "จำนวนผู้ครอบครองห้อง" #: 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:966 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "ผู้ดูà¹à¸¥à¸à¸²à¸£à¸ªà¸™à¸—นาเท่านั้นที่ได้รับอนุà¸à¸²à¸•ให้เปลี่ยนหัวข้อในห้องนี้" #: 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:2772 msgid "Nickname ~s does not exist in the room" msgstr "ไม่มีชื่อเล่น ~s อยู่ในห้องนี้" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "à¸à¸²à¸£à¹€à¸‚้าร่วมที่ไม่ถูà¸à¸•้อง: ~s" #: 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:3348 #, fuzzy msgid "Configuration of room ~s" msgstr "à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าสำหรับ " #: mod_muc_room.erl:3359 msgid "Room title" msgstr "ชื่อห้อง" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "รายละเอียด:" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "สร้างเป็นห้องถาวร" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "สร้างเป็นห้องที่บุคคลทั่วไปสามารถค้นหาได้" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "สร้างรายà¸à¸²à¸£à¸œà¸¹à¹‰à¹€à¸‚้าร่วมสำหรับใช้งานโดยบุคคลทั่วไป" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "สร้างห้องที่มีà¸à¸²à¸£à¸›à¹‰à¸­à¸‡à¸à¸±à¸™à¸”้วยรหัสผ่าน" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "จำนวนผู้ครอบครองห้องสูงสุด" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "ไม่จำà¸à¸±à¸”" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "à¹à¸ªà¸”ง Jabber IDs ที่ถูà¸à¸•้องà¹à¸à¹ˆ" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "สำหรับผู้ดูà¹à¸¥à¸à¸²à¸£à¸ªà¸™à¸—นาเท่านั้น" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "ทุà¸à¸„น" #: 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:3516 #, fuzzy msgid "Make room moderated" msgstr "สร้างเป็นห้องถาวร" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "ผู้ใช้เริ่มต้นเป็นผู้เข้าร่วม" #: mod_muc_room.erl:3522 #, fuzzy msgid "Allow users to change the subject" msgstr "อนุà¸à¸²à¸•ให้ผู้ใช้เปลี่ยนหัวข้อได้" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "อนุà¸à¸²à¸•ให้ผู้ใช้ส่งข้อความส่วนตัว" #: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "อนุà¸à¸²à¸•ให้ผู้ใช้ส่งข้อความส่วนตัว" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "อนุà¸à¸²à¸•ให้ผู้ใช้ถามคำถามà¸à¸±à¸šà¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸„นอื่นๆ ได้" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "อนุà¸à¸²à¸•ให้ผู้ใช้ส่งคำเชิà¸à¸–ึงà¸à¸±à¸™à¹„ด้" #: mod_muc_room.erl:3582 #, fuzzy msgid "Allow visitors to send status text in presence updates" msgstr "อนุà¸à¸²à¸•ให้ผู้ใช้ส่งข้อความส่วนตัว" #: mod_muc_room.erl:3586 #, fuzzy msgid "Allow visitors to change nickname" msgstr "อนุà¸à¸²à¸•ให้ผู้ใช้เปลี่ยนหัวข้อได้" #: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "อนุà¸à¸²à¸•ให้ผู้ใช้ส่งคำเชิà¸à¸–ึงà¸à¸±à¸™à¹„ด้" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: mod_muc_room.erl:3599 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "สร้างห้องที่มีà¸à¸²à¸£à¸›à¹‰à¸­à¸‡à¸à¸±à¸™à¸”้วยรหัสผ่าน" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "เปิดใช้งานà¸à¸²à¸£à¸šà¸±à¸™à¸—ึà¸" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อà¸à¸³à¸«à¸™à¸”ค่าห้องสนทนา " #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "จำนวนผู้ครอบครองห้อง" #: mod_muc_room.erl:4260 msgid "private, " msgstr "ส่วนตัว, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "ผู้ใช้" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s เชิà¸à¸„ุณเข้าร่วมสนทนาในห้อง ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "รหัสผ่านคือ" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "เวลา" #: mod_offline.erl:812 msgid "From" msgstr "จาà¸" #: mod_offline.erl:813 msgid "To" msgstr "ถึง" #: mod_offline.erl:814 msgid "Packet" msgstr "à¹à¸žà¹‡à¸à¹€à¸à¹‡à¸•" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "ข้อความออฟไลน์:" #: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "ข้อความออฟไลน์" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "เผยà¹à¸žà¸£à¹ˆ-สมัครเข้าใช้งาน" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe module" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "คำร้องขอของผู้สมัครเข้าใช้งาน PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "เลือà¸à¸§à¹ˆà¸²à¸ˆà¸°à¸­à¸™à¸¸à¸¡à¸±à¸•ิà¸à¸²à¸£à¸ªà¸¡à¸±à¸„รเข้าใช้งานของเอนทิตี้นี้หรือไม่" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID โหนด" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "ที่อยู่ของผู้สมัคร" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "อนุà¸à¸²à¸•ให้ Jabber ID นี้เข้าร่วมเป็นสมาชิà¸à¸‚องโหนด pubsub หรือไม่" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "ส่งส่วนของข้อมูล (payload) พร้อมà¸à¸±à¸šà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนเหตุà¸à¸²à¸£à¸“์" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "ส่งà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนเหตุà¸à¸²à¸£à¸“์" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนผู้สมัครสมาชิà¸à¹€à¸¡à¸·à¹ˆà¸­à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าโหนดเปลี่ยนà¹à¸›à¸¥à¸‡" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนผู้สมัครสมาชิà¸à¹€à¸¡à¸·à¹ˆà¸­à¹‚หนดถูà¸à¸¥à¸š" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนผู้สมัครสมาชิà¸à¹€à¸¡à¸·à¹ˆà¸­à¸£à¸²à¸¢à¸à¸²à¸£à¸–ูà¸à¸¥à¸šà¸­à¸­à¸à¸ˆà¸²à¸à¹‚หนด" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "ยืนยันรายà¸à¸²à¸£à¸—ี่จะจัดเà¸à¹‡à¸š" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "จำนวนสูงสุดของรายà¸à¸²à¸£à¸—ี่ยืนยัน" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "อนุà¸à¸²à¸•ให้เข้าร่วมเป็นสมาชิà¸à¸«à¸£à¸·à¸­à¹„ม่" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "ระบุโมเดลà¸à¸²à¸£à¹€à¸‚้าถึง" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "ระบุโมเดลผู้เผยà¹à¸žà¸£à¹ˆ" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" #: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "ระบุโมเดลà¸à¸²à¸£à¹€à¸‚้าถึง" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "ขนาดสูงสุดของส่วนของข้อมูล (payload) มีหน่วยเป็นไบต์" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "เวลาที่ส่งรายà¸à¸²à¸£à¸—ี่เผยà¹à¸žà¸£à¹ˆà¸„รั้งล่าสุด" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "ส่งà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนถึงผู้ใช้ที่สามารถติดต่อได้เท่านั้น" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" #: 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: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 "" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "" #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "" #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "" #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "" #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" #: mod_register_web.erl:214 msgid "" "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." msgstr "" #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "ชื่อผู้ใช้ IRC" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." msgstr "" #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "ไม่เคย" #: 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:249 msgid "You can later change your password using a Jabber client." msgstr "" #: 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 "" #: 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:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "à¸à¸²à¸£à¸•รวจสอบรหัสผ่าน" #: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "บัà¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­" #: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "รหัสผ่าน:" #: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "รหัสผ่าน:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" #: mod_register_web.erl:480 msgid "Unregister" msgstr "" #: mod_roster.erl:1436 msgid "Subscription" msgstr "à¸à¸²à¸£à¸ªà¸¡à¸±à¸„รสมาชิà¸" #: mod_roster.erl:1437 msgid "Pending" msgstr "ค้างอยู่" #: mod_roster.erl:1438 msgid "Groups" msgstr "à¸à¸¥à¸¸à¹ˆà¸¡" #: mod_roster.erl:1476 msgid "Validate" msgstr "ตรวจสอบ" #: mod_roster.erl:1485 msgid "Remove" msgstr "ลบ" #: mod_roster.erl:1490 msgid "Roster of " msgstr "บัà¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­à¸‚อง " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "เพิ่ม Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "บัà¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­" #: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 #: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "à¸à¸¥à¸¸à¹ˆà¸¡à¸šà¸±à¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­à¸—ี่ใช้งานร่วมà¸à¸±à¸™" #: mod_shared_roster.erl:1232 msgid "Name:" msgstr "ชื่อ:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "รายละเอียด:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "สมาชิà¸:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "à¸à¸¥à¸¸à¹ˆà¸¡à¸—ี่à¹à¸ªà¸”ง:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "à¸à¸¥à¸¸à¹ˆà¸¡" #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "วันเà¸à¸´à¸”" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "เมือง" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "ประเทศ" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "อีเมล" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "นามสà¸à¸¸à¸¥" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "ชื่อเต็ม" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "ชื่อà¸à¸¥à¸²à¸‡" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "ชื่อองค์à¸à¸£" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "หน่วยขององค์à¸à¸£" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "ค้นหาผู้ใช้ใน " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "ค้นหาผู้ใช้ vCard " #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard module" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "ผลà¸à¸²à¸£à¸„้นหาสำหรับ " #: mod_vcard_ldap.erl:502 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 "Encodings" #~ msgstr "à¸à¸²à¸£à¹€à¸‚้ารหัส" #~ msgid "(Raw)" #~ msgstr "(ข้อมูลดิบ)" #~ msgid "Specified nickname is already registered" #~ msgstr "ชื่อเล่นที่ระบุได้รับà¸à¸²à¸£à¸¥à¸‡à¹„ด้ทะเบียนà¹à¸¥à¹‰à¸§" #~ msgid "Size" #~ msgstr "ขนาด" #~ msgid "Roster groups that may subscribe (if access model is roster)" #~ msgstr "à¸à¸¥à¸¸à¹ˆà¸¡à¸šà¸±à¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­à¸—ี่อาจจะสมัครเป็นสมาชิภ(ถ้าโมเดลà¸à¸²à¸£à¹€à¸‚้าถึงคือบัà¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­)" ejabberd-16.01/priv/msgs/uk.po0000644000232200023220000017032412645157216016555 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: Konstantin Khomoutov \n" "Language-Team: \n" "Language: \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: Ruslan Rakhmanin\n" "X-Additional-Translator: Stoune\n" "X-Additional-Translator: Sergei Golovan\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Ви муÑите викориÑтовувати STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Ðе вказаний реÑурÑ" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Замінено новим з'єднаннÑм" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Введіть текÑÑ‚, що ви бачите" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Ваші Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ ~s блокуютьÑÑ. Ð”Ð»Ñ Ñ€Ð¾Ð·Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð²Ñ–Ð´Ð°Ð¹Ñ‚Ðµ ~s" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Якщо ви не бачите Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ°Ð¿Ñ‡Ñ–, перейдіть за за цією адреÑою." #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "ÐдреÑа капчі" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Перевірку капчею закінчено уÑпішно" #: 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 "КориÑтувач" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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 "Веб-Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÐдмініÑÑ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ ejabberd" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "ÐдмініÑтруваннÑ" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "необроблений формат" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Правила доÑтупу" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð° доÑтупу ~s" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "віртуальні хоÑти" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "КориÑтувачі" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Підключені кориÑтувачі" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "СтатиÑтика оÑтаннього Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Період" #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "За оÑтанній міÑÑць" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "За оÑтанній рік" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Ð’ÑÑ ÑтатиÑтика" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Показати звичайну таблицю" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Показати інтегральну таблицю" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "СтатиÑтика" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "не знайдено" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Вузол не знайдено" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Додати" #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "ХоÑÑ‚" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "ЗареєÑтровані кориÑтувачі" #: 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:1459 msgid "Offline Messages" msgstr "Офлайнові повідомленнÑ" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "ОÑтаннє підключеннÑ" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "Ðіколи" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "Підключений" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "ЗареєÑтровані кориÑтувачі:" #: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 #: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Підключені кориÑтувачі:" #: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Вихідні s2s-з'єднаннÑ:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" 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 msgid "None" msgstr "Ðемає" #: 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:1673 #, fuzzy msgid "User ~s" msgstr "КориÑтувач " #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Підключені реÑурÑи:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Пароль:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Видалити кориÑтувача" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Ðемає даних" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Вузли" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Працюючі вузли" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Зупинені вузли" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Вузол " #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "База даних" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Резервне копіюваннÑ" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Відкриті порти" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Обновити" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "ПерезапуÑтити" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Зупинити" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Модулі" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Помилка виклику RPC" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Таблиці бази даних на " #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Ðазва" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Тип таблиці" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Елементи" #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Пам'Ñть" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Помилка" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Резервне ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ " #: 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 "" "Зауважте, що Ñ†Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð°Ñ” за резервне ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ вбудованної " "бази даних Mnesia. Якщо Ви також викориÑтовуєте інше Ñховище Ð´Ð»Ñ Ð´Ð°Ð½Ð¸Ñ… " "(наприклад за допомогою Ð¼Ð¾Ð´ÑƒÐ»Ñ ODBC), то його резервне ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±Ð½Ð¾ " "робити окремо." #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Зберегти бінарну резервну копію:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "Відновити з бінарної резервної копії негайно:" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Відновити з бінарної резервної копії при наÑтупному запуÑку (потребує менше " "пам'Ñті):" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Зберегти текÑтову резервну копію:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Відновити з текÑтової резервної копії негайно:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Імпорт даних кориÑтовучів з файлу PIEFXIS (XEP-0227):" #: 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:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "ЕкÑпорт даних кориÑтувачів домена до файлу PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Імпорт кориÑтувачів з файла Ñпула jabberd14:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Імпорт кориÑтувачів з діректорії Ñпула jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Відкриті порти на " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Модулі на " #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "СтатиÑтика вузла ~p" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Ð§Ð°Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "ПроцеÑорний чаÑ:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Транзакції завершені:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Транзакції відмінені:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Транзакції перезапущені:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Транзакції запротокольовані:" #: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "ÐŸÐ¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ " #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "План поновленнÑ" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Змінені модулі" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Сценарій поновленнÑ" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Ðизькорівневий Ñценарій поновленнÑ" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Перевірка Ñценарію" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Порт" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Протокол" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Модуль" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Параметри" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "ЗапуÑтити" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Команди" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Пінг" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Понг" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "ÐаÑправді видалити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Тема" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Тіло повідомленнÑ" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Тіло Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð¼Ð°Ñ” бути непуÑтим" #: mod_announce.erl:662 msgid "Announcements" msgstr "СповіщеннÑ" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "ÐадіÑлати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñім кориÑтувачам" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "ÐадіÑлати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð´Ð¾ уÑÑ–Ñ… кориÑтувачів на уÑÑ–Ñ… хоÑтах" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "ÐадіÑлати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñім підключеним кориÑтувачам" #: 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:672 msgid "Set message of the day and send to online users" msgstr "Ð’Ñтановити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ Ñ‚Ð° надіÑлати його підключеним кориÑтувачам" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Ð’Ñтановити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ Ð½Ð° вÑÑ–Ñ… хоÑтах та надійÑлати його підключеним " "кориÑтувачам" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Оновити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ (не надÑилати)" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Оновити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ Ð½Ð° вÑÑ–Ñ… хоÑтах (не надÑилати)" #: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Видалити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Видалити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð½Ñ Ð½Ð° уÑÑ–Ñ… хоÑтах" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "КонфігураціÑ" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "ЗапуÑк модулів" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Зупинка модулів" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð· резервної копії" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "ÐšÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð² текÑтовий файл" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Імпорт з файла" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Імпорт з директорії" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "ПерезапуÑтити СервіÑ" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Вимкнути СервіÑ" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Видалити КориÑтувача" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Закінчити Ð¡ÐµÐ°Ð½Ñ ÐšÐ¾Ñ€Ð¸Ñтувача" #: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 #: mod_configure.erl:1473 msgid "Get User Password" msgstr "Отримати Пароль КориÑтувача" #: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Змінити Пароль КориÑтувача" #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Отримати Ð§Ð°Ñ ÐžÑтаннього ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ ÐšÐ¾Ñ€Ð¸Ñтувача" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Отримати СтатиÑтику по КориÑтувачу" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Отримати КількіÑть ЗареєÑтрованих КориÑтувачів" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Отримати КількіÑть Підключених КориÑтувачів" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ ÐšÐ¾Ñ€Ð¸Ñтувачами" #: mod_configure.erl:525 msgid "All Users" msgstr "Ð’ÑÑ– кориÑтувачі" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Вихідні s2s-з'єднаннÑ" #: mod_configure.erl:615 msgid "Backup Management" msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¸Ð¼ копіюваннÑм" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Імпорт кориÑтувачів зі Ñпулу jabberd14" #: mod_configure.erl:762 msgid "To ~s" msgstr "До ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "Від ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†ÑŒ бази даних на " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Оберіть тип Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†ÑŒ" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Тільки диÑк" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "ОЗП та диÑк" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "ОЗП" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "не зберігаетьÑÑ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Зупинка модулів на " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Виберіть модулі, Ñкі необхідно зупинити" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "ЗапуÑк модулів на " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Введіть перелік такого виду {Module, [Options]}" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "СпиÑок завантажуваних модулів" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Резервне ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð² файл на " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Введіть шлÑÑ… до резервного файла" #: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "ШлÑÑ… до файла" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð· резервної копії на " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "ÐšÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð² текÑтовий файл на " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Введіть шлÑÑ… до текÑтового файла" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Ð†Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача з файла на " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Введіть шлÑÑ… до файла зі Ñпула jabberd14" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Ð†Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача з директорії на " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Введіть шлÑÑ… до директорії Ñпула jabberd14" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "ШлÑÑ… до директорії" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Ð§Ð°Ñ Ð·Ð°Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÑпиÑків ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупом" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "СпиÑки ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупом" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð´Ð¾Ñтупу" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "Перевірка ПаролÑ" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "КількіÑть зареєÑтрованих кориÑтувачів" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "КількіÑть підключених кориÑтувачів" #: mod_configure.erl:1936 msgid "Last login" msgstr "ОÑтаннє підключеннÑ" #: mod_configure.erl:1963 msgid "Roster size" msgstr "КількіÑть контактів" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP адреÑи" #: mod_configure.erl:1967 msgid "Resources" msgstr "РеÑурÑи" #: mod_configure.erl:2095 msgid "Administration of " msgstr "ÐдмініÑÑ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ " #: mod_configure.erl:2100 msgid "Action on user" msgstr "Ð”Ñ–Ñ Ð½Ð°Ð´ кориÑтувачем" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Змінити параметри" #: 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_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:220 mod_muc.erl:467 msgid "Access denied by service policy" msgstr "ДоÑтуп заборонений політикою Ñлужби" #: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC ТранÑпорт" #: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC модуль" #: 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:653 msgid "Registration in mod_irc for " msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð² mod_irc Ð´Ð»Ñ " #: 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:667 msgid "IRC Username" msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача IRC" #: 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." msgstr "" "Щоб вказати різні порти, паролі та ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ€Ñ–Ð·Ð½Ð¸Ñ… Ñерверів IRC, " "заповніть ÑпиÑок значеннÑми в форматі '{\"irc server\", \"encoding\", port, " "\"password\"}'. За замовчуваннÑм Ñ†Ñ Ñлужба викориÑтовує \"~s\" кодуваннÑ, " "порт ~p, пуÑтий пароль." #: 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 "" "Приклад: [{\"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 "Параметри з'єднаннÑ" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "ПриєднатиÑÑ Ð´Ð¾ каналу IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Канал IRC (не включаючи #)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC-Ñервер" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "ПриєднатиÑÑ Ð´Ð¾ каналу IRC" #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "ПриєднатиÑÑ Ð´Ð¾ каналу IRC з Jabber ID: ~s" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "Парметри IRC" #: 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 "" "Введіть ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та кодуваннÑ, Ñкі будуть викориÑтовуватиÑÑ Ð¿Ñ€Ð¸ " "підключенні до IRC-Ñерверів ÐатиÑніть 'Далі' Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ñ… " "полів. ÐатиÑніть 'Завершити' Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ–Ð²." #: mod_irc.erl:1060 msgid "IRC username" msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача IRC" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "Пароль ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "Порт ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñервера ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "Сервер ~b" #: 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 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:941 msgid "Nickname Registration at " msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð¿Ñевдоніма на " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "ПÑевдонім" #: 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 модуль" #: 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:249 #, fuzzy msgid "Total rooms" msgstr "Кімнати" #: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "вийшов(ла) з кімнати" #: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "ЗареєÑтровані кориÑтувачі" #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸ змінилаÑÑŒ" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "увійшов(ла) в кімнату" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "вийшов(ла) з кімнати" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "заборонили вхід в кімнату" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "вигнано з кімнати внаÑлідок зміни рангу" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "вигнано з кімнати тому, що вона Ñтала тільки Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "вигнано з кімнати внаÑлідок зупинки ÑиÑтеми" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "змінив(ла) пÑевдонім на" #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " вÑтановив(ла) тему: " #: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Створено кімнату" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Знищено кімнату" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Запущено кімнату" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Зупинено кімнату" #: mod_muc_log.erl:503 msgid "Monday" msgstr "Понеділок" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Вівторок" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Середа" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "Четвер" #: mod_muc_log.erl:507 msgid "Friday" msgstr "П'ÑтницÑ" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "Субота" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "ÐеділÑ" #: mod_muc_log.erl:513 msgid "January" msgstr "ÑічнÑ" #: mod_muc_log.erl:514 msgid "February" msgstr "лютого" #: mod_muc_log.erl:515 msgid "March" msgstr "березнÑ" #: mod_muc_log.erl:516 msgid "April" msgstr "квітнÑ" #: mod_muc_log.erl:517 msgid "May" msgstr "травнÑ" #: mod_muc_log.erl:518 msgid "June" msgstr "червнÑ" #: mod_muc_log.erl:519 msgid "July" msgstr "липнÑ" #: mod_muc_log.erl:520 msgid "August" msgstr "ÑерпнÑ" #: mod_muc_log.erl:521 msgid "September" msgstr "вереÑнÑ" #: mod_muc_log.erl:522 msgid "October" msgstr "груднÑ" #: mod_muc_log.erl:523 msgid "November" msgstr "лиÑтопада" #: mod_muc_log.erl:524 msgid "December" msgstr "груднÑ" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "УчаÑники кімнати" #: 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:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Тільки модератори можуть змінювати тему в цій кімнаті" #: 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:2772 msgid "Nickname ~s does not exist in the room" msgstr "ПÑевдонім ~s в кімнаті відÑутній" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "ÐедопуÑтимий ранг: ~s" #: 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:3348 msgid "Configuration of room ~s" msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸ ~s" #: mod_muc_room.erl:3359 msgid "Room title" msgstr "Ðазва кімнати" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "ÐžÐ¿Ð¸Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Зробити кімнату поÑтійною" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Зробити кімнату видимою вÑім" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Зробити ÑпиÑок учаÑників видимим вÑім" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Зробити кімнату захищеною паролем" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "МакÑимальна кількіÑть учаÑників" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "Без обмежень" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Зробити реальні Jabber ID учаÑників видимими" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "тільки модераторам" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "вÑім учаÑникам" #: 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:3516 msgid "Make room moderated" msgstr "Зробити кімнату модерованою" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Зробити кориÑтувачів учаÑниками за замовчуваннÑм" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Дозволити кориÑтувачам змінювати тему" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Дозволити приватні повідомленнÑ" #: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Дозволити приватні повідомленнÑ" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Дозволити iq-запити до кориÑтувачів" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Дозволити кориÑтувачам надÑилати запрошеннÑ" #: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Дозволити відвідувачам відÑилати текÑÑ‚ ÑтатуÑу в оновленнÑÑ… приÑутноÑті" #: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Дозволити відвідувачам змінювати пÑевдонім" #: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Дозволити кориÑтувачам надÑилати запрошеннÑ" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Зробити кімнату захищеною капчею" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "ПропуÑкати ці Jabber ID без CAPTCHA-запиту" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Включити журнал роботи" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "Ð”Ð»Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÑ–Ð¼Ð½Ð°Ñ‚Ð¸ потрібно викориÑтовувати клієнт з підтримкою x:" "data" #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "КількіÑть приÑутніх" #: mod_muc_room.erl:4260 msgid "private, " msgstr "приватна, " #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" #: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "КориÑтувач " #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s запрошує Ð²Ð°Ñ Ð´Ð¾ кімнати ~s" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "пароль:" #: mod_multicast.erl:291 msgid "Multicast" msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" #: 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:811 msgid "Time" msgstr "ЧаÑ" #: mod_offline.erl:812 msgid "From" msgstr "Від кого" #: mod_offline.erl:813 msgid "To" msgstr "Кому" #: mod_offline.erl:814 msgid "Packet" msgstr "Пакет" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Офлайнові повідомленнÑ:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Видалити вÑÑ– офлайнові повідомленнÑ" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams модуль" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "ПублікаціÑ-ПідпиÑка" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Модуль ejabberd Публікації-ПідпиÑки" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Запит на підпиÑку PubSub" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Вирішіть, чи задовольнити запит цього об'єкту на підпиÑку" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID вузла" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "ÐдреÑа абонента" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Чи дозволити цьому Jabber ID підпиÑатиÑÑŒ новини наданого вузла" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "ДоÑтавлÑти разом з повідомленнÑми про публікації Ñамі публікації" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "ДоÑтавлÑти ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ події" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "ПовідомлÑти абонентів про зміни в конфігурації збірника" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "ПовідомлÑти абонентів про Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð±Ñ–Ñ€Ð½Ð¸ÐºÐ°" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "ПовідомлÑти абонентів про Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿ÑƒÐ±Ð»Ñ–ÐºÐ°Ñ†Ñ–Ð¹ із збірника" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Зберегати публікації до Ñховища" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "ПÑевдонім Ð´Ð»Ñ Ð²ÑƒÐ·Ð»Ð°" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "МакÑимальне чиÑло збережених публікацій" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "ДозволÑти підпиÑку" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Визначити модель доÑтупу" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Дозволені Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñки групи роÑтера" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Умови публікації" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Видалити вÑÑ– елементи, коли оÑоба, що Ñ—Ñ… опублікувала, вимикаєтьÑÑ Ð²Ñ–Ð´ мережі" #: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Вкажіть тип повідомлень зі ÑповіщеннÑми про події" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "МакÑимальний розмір кориÑного Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð² байтах" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Коли надÑилати оÑтанній опублікований елемент" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "ДоÑтавлÑти повідомленнÑми тільки доÑтупним кориÑтувачам" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "КолекціÑ, до Ñкої входить вузол" #: 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: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-акаунт було уÑпішно Ñтворено." #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "Помилка при Ñтворенні акаунту:" #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Ваш Jabber-акаунт було уÑпішно видалено." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "Помилка при видаленні акаунту: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Пароль вашого Jabber-акаунту був уÑпішно змінений." #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "Помилка при зміні паролÑ: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Jabber-акаунту" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "ЗареєÑтрувати Jabber-акаунт" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Видалити Jabber-акаунт" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "Тут ви можете зареєÑтрувати обліковий Ð·Ð°Ð¿Ð¸Ñ Jabber на цьому Ñервері. Ваш JID " "(ідентифікатор Jabber) матиме виглÑд \"кориÑтувач@Ñервер\". Щоб вірно " "заповнити Ð¿Ð¾Ð»Ñ Ð½Ð¸Ð¶Ñ‡Ðµ, будь лаÑка, уважно читайте інÑтрукції до них." #: 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 "" "РегіÑтр не має значеннÑ: \"МÐШÐ\" та \"маша\" буде ÑприйматиÑÑ Ñк одне й те " "Ñаме ім'Ñ." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "Заборонені Ñимволи:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Сервер:" #: 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:249 msgid "You can later change your password using a Jabber client." msgstr "Пізніше можна змінити пароль через 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 "" "ДеÑкі Jabber-клієнти можуть зберігати пароль на вашому комп'ютері. " "КориÑтуйтеÑÑŒ цією функцією тільки у тому випадку, Ñкщо вважаєте Ñ—Ñ— безпечною." #: 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 "" "Запам'Ñтайте пароль, або запишіть його на папері, Ñкий треба зберегти у " "безпечному міÑці. У Jabber'Ñ– немає автоматизованих заÑобів Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ " "Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ð° той випадок, Ñкщо ви його забудете." #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Перевірка ПаролÑ:" #: mod_register_web.erl:269 msgid "Register" msgstr "РеєÑтраціÑ" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "Старий пароль:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "Ðовий Пароль:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "Ð¦Ñ Ñторінка дозволÑÑ” видалити Ñвій акаунт з Jabber-Ñервера." #: mod_register_web.erl:480 msgid "Unregister" msgstr "Видалити" #: mod_roster.erl:1436 msgid "Subscription" msgstr "ПідпиÑка" #: mod_roster.erl:1437 msgid "Pending" msgstr "ОчікуваннÑ" #: mod_roster.erl:1438 msgid "Groups" msgstr "Групи" #: mod_roster.erl:1476 msgid "Validate" msgstr "Затвердити" #: mod_roster.erl:1485 msgid "Remove" msgstr "Видалити" #: mod_roster.erl:1490 msgid "Roster of " msgstr "РоÑтер кориÑтувача " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Додати Jabber ID" #: mod_roster.erl:1622 msgid "Roster" msgstr "РоÑтер" #: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 #: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Спільні групи контактів" #: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Ðазва:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "ОпиÑ:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Члени:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Видимі групи:" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "Група " #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "День народженнÑ" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "МіÑто" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Країна" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Електронна пошта" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Прізвище" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Повне ім'Ñ" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "По-батькові" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Ðазва організації" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Відділ організації" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Пошук кориÑтувачів в " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Пошук кориÑтувачів по vCard" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard модуль" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Результати пошуку в " #: mod_vcard_ldap.erl:502 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 "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Цього учаÑника було відключено від кімнати через те, що він надіÑлав " #~ "помилкове повідомленнÑ" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "Цього учаÑника було відключено від кімнати через те, що він надіÑлав " #~ "помилкове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ–Ð½ÑˆÐ¾Ð¼Ñƒ учаÑнику" #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Цього учаÑника було відключено від кімнати через те, що він надіÑлав " #~ "помилковий ÑÑ‚Ð°Ñ‚ÑƒÑ Ð¿Ñ€Ð¸ÑутноÑті" #~ msgid "Captcha test failed" #~ msgstr "Перевірка капчею закінчилаÑÑŒ невдало" ejabberd-16.01/priv/msgs/th.msg0000644000232200023220000006406412645157216016724 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"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","เพิ่ม Jabber ID"}. {"Add New","เพิ่มผู้ใช้ใหม่"}. {"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","อนุà¸à¸²à¸•ให้ผู้ใช้ถามคำถามà¸à¸±à¸šà¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸„นอื่นๆ ได้"}. {"Allow users to send invites","อนุà¸à¸²à¸•ให้ผู้ใช้ส่งคำเชิà¸à¸–ึงà¸à¸±à¸™à¹„ด้"}. {"Allow users to send private messages","อนุà¸à¸²à¸•ให้ผู้ใช้ส่งข้อความส่วนตัว"}. {"All Users","ผู้ใช้ทั้งหมด"}. {"Announcements","ประà¸à¸²à¸¨"}. {"anyone","ทุà¸à¸„น"}. {"April","เมษายน"}. {"August","สิงหาคม"}. {"Backup","à¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูล "}. {"Backup Management","à¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£à¸‚้อมูลสำรอง"}. {"Backup to File at ","สำรองไฟล์ข้อมูลที่"}. {"Bad format","รูปà¹à¸šà¸šà¸—ี่ไม่ถูà¸à¸•้อง"}. {"Birthday","วันเà¸à¸´à¸”"}. {"Change Password","เปลี่ยนรหัสผ่าน"}. {"Change User Password","เปลี่ยนรหัสผ่านของผู้ใช้"}. {"Chatroom configuration modified","มีà¸à¸²à¸£à¸›à¸£à¸±à¸šà¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าของห้องสนทนา"}. {"Chatrooms","ห้องสนทนา"}. {"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.","เลือà¸à¸§à¹ˆà¸²à¸ˆà¸°à¸­à¸™à¸¸à¸¡à¸±à¸•ิà¸à¸²à¸£à¸ªà¸¡à¸±à¸„รเข้าใช้งานของเอนทิตี้นี้หรือไม่"}. {"City","เมือง"}. {"Commands","คำสั่ง"}. {"Conference room does not exist","ไม่มีห้องประชุม"}. {"Configuration","à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่า"}. {"Connected Resources:","ทรัพยาà¸à¸£à¸—ี่เชื่อมต่อ:"}. {"Country","ประเทศ"}. {"CPU Time:","เวลาà¸à¸²à¸£à¸—ำงานของ CPU:"}. {"Database","à¸à¸²à¸™à¸‚้อมูล"}. {"Database Tables Configuration at ","à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าตารางà¸à¸²à¸™à¸‚้อมูลที่"}. {"December","ธันวาคม"}. {"Default users as participants","ผู้ใช้เริ่มต้นเป็นผู้เข้าร่วม"}. {"Delete message of the day","ลบข้อความของวัน"}. {"Delete message of the day on all hosts","ลบข้อความของวันบนโฮสต์ทั้งหมด"}. {"Delete Selected","ลบข้อความที่เลือà¸"}. {"Delete User","ลบผู้ใช้"}. {"Deliver event notifications","ส่งà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนเหตุà¸à¸²à¸£à¸“์"}. {"Deliver payloads with event notifications","ส่งส่วนของข้อมูล (payload) พร้อมà¸à¸±à¸šà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนเหตุà¸à¸²à¸£à¸“์"}. {"Description:","รายละเอียด:"}. {"Disc only copy","คัดลอà¸à¹€à¸‰à¸žà¸²à¸°à¸”ิสà¸à¹Œ"}. {"Displayed Groups:","à¸à¸¥à¸¸à¹ˆà¸¡à¸—ี่à¹à¸ªà¸”ง:"}. {"Dump Backup to Text File at ","ถ่ายโอนà¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูลไปยังไฟล์ข้อความที่"}. {"Dump to Text File","ถ่ายโอนข้อมูลไปยังไฟล์ข้อความ"}. {"Edit Properties","à¹à¸à¹‰à¹„ขคุณสมบัติ"}. {"ejabberd IRC module","ejabberd IRC module"}. {"ejabberd MUC module","ejabberd MUC module"}. {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe module"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","ejabberd vCard module"}. {"Email","อีเมล"}. {"Enable logging","เปิดใช้งานà¸à¸²à¸£à¸šà¸±à¸™à¸—ึà¸"}. {"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 dir"}. {"Enter path to jabberd14 spool file","ป้อนพาธไปยังไฟล์เà¸à¹‡à¸šà¸žà¸±à¸à¸‚้อมูล jabberd14"}. {"Enter path to text file","ป้อนพาธของไฟล์ข้อความ"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"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 ที่ตรงà¸à¸±à¸™ (ใส่เครื่องหมาย * ที่ท้ายสุดของฟิลด์เพื่อจับคู่à¸à¸±à¸šà¸ªà¸•ริงย่อย)"}. {"Friday","วันศุà¸à¸£à¹Œ"}. {"From","จาà¸"}. {"From ~s","จาภ~s"}. {"Full Name","ชื่อเต็ม"}. {"Get Number of Online Users","à¹à¸ªà¸”งจำนวนผู้ใช้ออนไลน์"}. {"Get Number of Registered Users","à¹à¸ªà¸”งจำนวนผู้ใช้ที่ลงทะเบียน"}. {"Get User Last Login Time","à¹à¸ªà¸”งเวลาเข้าสู่ระบบครั้งล่าสุดของผู้ใช้"}. {"Get User Password","ขอรับรหัสผ่านของผู้ใช้"}. {"Get User Statistics","à¹à¸ªà¸”งสถิติของผู้ใช้"}. {"Group ","à¸à¸¥à¸¸à¹ˆà¸¡"}. {"Groups","à¸à¸¥à¸¸à¹ˆà¸¡"}. {"has been banned","ถูà¸à¸ªà¸±à¹ˆà¸‡à¸«à¹‰à¸²à¸¡"}. {"has been kicked","ถูà¸à¹„ล่ออà¸"}. {" has set the subject to: "," ตั้งหัวข้อว่า: "}. {"Host","โฮสต์"}. {"Import Directory","อิมพอร์ตไดเร็à¸à¸—อรี"}. {"Import File","อิมพอร์ตไฟล์"}. {"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","มà¸à¸£à¸²à¸„ม"}. {"joins the room","เข้าห้องสนทนานี้"}. {"July","à¸à¸£à¸à¸Žà¸²à¸„ม"}. {"June","มิถุนายน"}. {"Last Activity","à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸¥à¹ˆà¸²à¸ªà¸¸à¸”"}. {"Last login","à¸à¸²à¸£à¹€à¸‚้าสู่ระบบครั้งล่าสุด"}. {"Last month","เดือนที่à¹à¸¥à¹‰à¸§"}. {"Last year","ปีที่à¹à¸¥à¹‰à¸§"}. {"leaves the room","ออà¸à¸ˆà¸²à¸à¸«à¹‰à¸­à¸‡"}. {"Listened Ports","พอร์ทฟัง"}. {"Listened Ports at ","พอร์ทฟังที่"}. {"List of modules to start","รายà¸à¸²à¸£à¸‚องโมดูลที่จะเริ่มà¸à¸²à¸£à¸—ำงาน"}. {"Low level update script","อัพเดตสคริปต์ระดับต่ำ"}. {"Make participants list public","สร้างรายà¸à¸²à¸£à¸œà¸¹à¹‰à¹€à¸‚้าร่วมสำหรับใช้งานโดยบุคคลทั่วไป"}. {"Make room members-only","สร้างห้องสำหรับสมาชิà¸à¹€à¸—่านั้น"}. {"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) มีหน่วยเป็นไบต์"}. {"May","พฤษภาคม"}. {"Members:","สมาชิà¸:"}. {"Memory","หน่วยความจำ"}. {"Message body","เนื้อหาของข้อความ"}. {"Middle Name","ชื่อà¸à¸¥à¸²à¸‡"}. {"Moderator privileges required","ต้องมีสิทธิพิเศษของผู้ดูà¹à¸¥à¸à¸²à¸£à¸ªà¸™à¸—นา"}. {"moderators only","สำหรับผู้ดูà¹à¸¥à¸à¸²à¸£à¸ªà¸™à¸—นาเท่านั้น"}. {"Module","โมดูล"}. {"Modules","โมดูล"}. {"Monday","วันจันทร์"}. {"Name:","ชื่อ:"}. {"Name","ชื่อ"}. {"Never","ไม่เคย"}. {"Nickname","ชื่อเล่น"}. {"Nickname Registration at ","à¸à¸²à¸£à¸¥à¸‡à¸—ะเบียนชื่อเล่นที่ "}. {"Nickname ~s does not exist in the room","ไม่มีชื่อเล่น ~s อยู่ในห้องนี้"}. {"No body provided for announce message","ไม่ได้ป้อนเนื้อหาสำหรับข้อความที่ประà¸à¸²à¸¨"}. {"No Data","ไม่มีข้อมูล"}. {"Node ID","ID โหนด"}. {"Node not found","ไม่พบโหนด"}. {"Nodes","โหนด"}. {"No limit","ไม่จำà¸à¸±à¸”"}. {"None","ไม่มี"}. {"No resource provided","ไม่ได้ระบุข้อมูล"}. {"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","จำนวนผู้ใช้ออนไลน์"}. {"Number of registered users","จำนวนผู้ใช้ที่ลงทะเบียน"}. {"October","ตุลาคม"}. {"Offline Messages:","ข้อความออฟไลน์:"}. {"Offline Messages","ข้อความออฟไลน์"}. {"OK","ตà¸à¸¥à¸‡"}. {"Online","ออนไลน์"}. {"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 ขาออà¸"}. {"Owner privileges required","ต้องมีสิทธิพิเศษของเจ้าของ"}. {"Packet","à¹à¸žà¹‡à¸à¹€à¸à¹‡à¸•"}. {"Password:","รหัสผ่าน:"}. {"Password","รหัสผ่าน"}. {"Password Verification","à¸à¸²à¸£à¸•รวจสอบรหัสผ่าน"}. {"Path to Dir","พาธไปยัง Dir"}. {"Path to File","พาธของไฟล์ข้อมูล"}. {"Pending","ค้างอยู่"}. {"Period: ","ระยะเวลา:"}. {"Persist items to storage","ยืนยันรายà¸à¸²à¸£à¸—ี่จะจัดเà¸à¹‡à¸š"}. {"Ping","Ping"}. {"Pong","Pong"}. {"Port","พอร์ท"}. {"Present real Jabber IDs to","à¹à¸ªà¸”ง Jabber IDs ที่ถูà¸à¸•้องà¹à¸à¹ˆ"}. {"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 สำหรับ"}. {"Remote copy","คัดลอà¸à¸£à¸°à¸¢à¸°à¹„à¸à¸¥"}. {"Remove","ลบ"}. {"Remove User","ลบผู้ใช้"}. {"Replaced by new connection","à¹à¸—นที่ด้วยà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•่อใหม่"}. {"Resources","ทรัพยาà¸à¸£"}. {"Restart","เริ่มต้นใหม่"}. {"Restart Service","เริ่มต้นà¸à¸²à¸£à¸šà¸£à¸´à¸à¸²à¸£à¹ƒà¸«à¸¡à¹ˆà¸­à¸µà¸à¸„รั้ง"}. {"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:","คืนค่าข้อมูลสำรองที่เป็นข้อความธรรมดาโดยทันที:"}. {"Room Configuration","à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าห้องสนทนา"}. {"Room creation is denied by service policy","à¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¸«à¹‰à¸­à¸‡à¸ªà¸™à¸—นาถูà¸à¸›à¸à¸´à¹€à¸ªà¸˜à¹‚ดยนโยบายà¸à¸²à¸£à¸šà¸£à¸´à¸à¸²à¸£"}. {"Room title","ชื่อห้อง"}. {"Roster","บัà¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­"}. {"Roster of ","บัà¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­à¸‚อง "}. {"Roster size","ขนาดของบัà¸à¸Šà¸µà¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­"}. {"RPC Call Error","ข้อผิดพลาดจาà¸à¸à¸²à¸£à¹€à¸£à¸µà¸¢à¸à¹ƒà¸Šà¹‰ RPC"}. {"Running Nodes","โหนดที่ทำงาน"}. {"~s access rule configuration","~s à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าà¸à¸Žà¸à¸²à¸£à¹€à¸‚้าถึง"}. {"Saturday","วันเสาร์"}. {"Script check","ตรวจสอบคริปต์"}. {"Search Results for ","ผลà¸à¸²à¸£à¸„้นหาสำหรับ "}. {"Search users in ","ค้นหาผู้ใช้ใน "}. {"Send announcement to all online users","ส่งประà¸à¸²à¸¨à¸–ึงผู้ใช้ออนไลน์ทั้งหมด"}. {"Send announcement to all online users on all hosts","ส่งประà¸à¸²à¸¨à¸–ึงผู้ใช้ออนไลน์ทั้งหมดบนโฮสต์ทั้งหมด"}. {"Send announcement to all users","ส่งประà¸à¸²à¸¨à¸–ึงผู้ใช้ทั้งหมด"}. {"Send announcement to all users on all hosts","ส่งประà¸à¸²à¸¨à¸–ึงผู้ใช้ทั้งหมดบนโฮสต์ทั้งหมด"}. {"September","à¸à¸±à¸™à¸¢à¸²à¸¢à¸™"}. {"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"}. {"Specify the access model","ระบุโมเดลà¸à¸²à¸£à¹€à¸‚้าถึง"}. {"Specify the publisher model","ระบุโมเดลผู้เผยà¹à¸žà¸£à¹ˆ"}. {"~s's Offline Messages Queue","~s's ลำดับข้อความออฟไลน์"}. {"Start","เริ่ม"}. {"Start Modules","เริ่มโมดูล"}. {"Start Modules at ","เริ่มโมดูลที่"}. {"Statistics","สถิติ"}. {"Statistics of ~p","สถิติของ ~p"}. {"Stop","หยุด"}. {"Stop Modules","หยุดโมดูล"}. {"Stop Modules at ","หยุดโมดูลที่"}. {"Stopped Nodes","โหนดที่หยุด"}. {"Storage Type","ชนิดที่เà¸à¹‡à¸šà¸‚้อมูล"}. {"Store binary backup:","จัดเà¸à¹‡à¸šà¸‚้อมูลสำรองà¹à¸šà¸šà¹„บนารี:"}. {"Store plain text backup:","จัดเà¸à¹‡à¸šà¸‚้อมูลสำรองที่เป็นข้อความธรรมดา:"}. {"Subject","หัวเรื่อง"}. {"Submit","ส่ง"}. {"Submitted","ส่งà¹à¸¥à¹‰à¸§"}. {"Subscriber Address","ที่อยู่ของผู้สมัคร"}. {"Subscription","à¸à¸²à¸£à¸ªà¸¡à¸±à¸„รสมาชิà¸"}. {"Sunday","วันอาทิตย์"}. {"the password is","รหัสผ่านคือ"}. {"Thursday","วันพฤหัสบดี"}. {"Time","เวลา"}. {"Time delay","à¸à¸²à¸£à¸«à¸™à¹ˆà¸§à¸‡à¹€à¸§à¸¥à¸²"}. {"To","ถึง"}. {"To ~s","ถึง ~s"}. {"Traffic rate limit is exceeded","อัตราของปริมาณà¸à¸²à¸£à¹€à¸‚้าใช้เà¸à¸´à¸™à¸‚ีดจำà¸à¸±à¸”"}. {"Transactions Aborted:","ทรานà¹à¸‹à¸à¸Šà¸±à¸™à¸—ี่ถูà¸à¸¢à¸à¹€à¸¥à¸´à¸:"}. {"Transactions Committed:","ทรานà¹à¸‹à¸à¸Šà¸±à¸™à¸—ี่ได้รับมอบหมาย:"}. {"Transactions Logged:","ทรานà¹à¸‹à¸à¸Šà¸±à¸™à¸—ี่บันทึà¸:"}. {"Transactions Restarted:","ทรานà¹à¸‹à¸à¸Šà¸±à¸™à¸—ี่เริ่มทำงานใหม่อีà¸à¸„รั้ง:"}. {"Tuesday","วันอังคาร"}. {"Update","อัพเดต"}. {"Update message of the day (don't send)","อัพเดตข้อความของวัน (ไม่ต้องส่ง)"}. {"Update message of the day on all hosts (don't send)","อัพเดตข้อความของวันบนโฮสต์ทั้งหมด (ไม่ต้องส่ง) "}. {"Update plan","à¹à¸œà¸™à¸à¸²à¸£à¸­à¸±à¸žà¹€à¸”ต"}. {"Update script","อัพเดตสคริปต์"}. {"Uptime:","เวลาà¸à¸²à¸£à¸—ำงานต่อเนื่อง:"}. {"Use of STARTTLS required","ต้องใช้ STARTTLS"}. {"User","ผู้ใช้"}. {"User Management","à¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰"}. {"Users","ผู้ใช้"}. {"Users Last Activity","à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸¥à¹ˆà¸²à¸ªà¸¸à¸”ของผู้ใช้"}. {"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.","ลำดับข้อความออฟไลน์ของผู้ที่ติดต่อของคุณเต็มà¹à¸¥à¹‰à¸§ ข้อความถูà¸à¸¥à¸šà¸—ิ้งà¹à¸¥à¹‰à¸§"}. ejabberd-16.01/priv/msgs/nl.msg0000644000232200023220000006707312645157216016725 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Toegangsinstellingen"}. {"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"}. {"Add Jabber ID","Jabber ID toevoegen"}. {"Add New","Toevoegen"}. {"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?"}. {"Allow users to change the subject","Sta gebruikers toe het onderwerp te veranderen"}. {"Allow users to query other users","Gebruikers mogen naar andere gebruikers verzoeken verzenden"}. {"Allow users to send invites","Gebruikers mogen uitnodigingen verzenden"}. {"Allow users to send private messages","Gebruikers mogen privéberichten verzenden"}. {"Allow visitors to change nickname","Sta bezoekers toe hun naam te veranderen"}. {"Allow visitors to send private messages to","Gebruikers mogen privéberichten verzenden aan"}. {"Allow visitors to send status text in presence updates","Sta bezoekers toe hun statusbericht in te stellen"}. {"Allow visitors to send voice requests","Gebruikers mogen stemaanvragen verzenden"}. {"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"}. {"Backup Management","Backup"}. {"Backup of ~p","Backup maken van ~p"}. {"Backup to File at ","Binaire backup maken op "}. {"Bad format","Verkeerd formaat"}. {"Birthday","Geboortedatum"}. {"CAPTCHA web page","CAPTCHA webpagina."}. {"Change Password","Wachtwoord wijzigen"}. {"Change User Password","Verander Gebruikerswachtwoord"}. {"Characters not allowed:","Niet-toegestane karakters:"}. {"Chatroom configuration modified","De instellingen van de chatruimte werden veranderd"}. {"Chatroom is created","Gespreksruimte gecreëerd"}. {"Chatroom is destroyed","Gespreksruimte vernietigd"}. {"Chatroom is started","Gespreksruimte gestart"}. {"Chatroom is stopped","Gespreksruimte gestopt"}. {"Chatrooms","Groepsgesprekken"}. {"Choose a username and password to register with this server","Kies een gebruikersnaam en een wachtwoord om u te registreren op deze server"}. {"Choose modules to stop","Selecteer de modules die u wilt stoppen"}. {"Choose storage type of tables","Opslagmethode voor tabellen kiezen"}. {"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:"}. {"Connections parameters","Verbindingsparameters"}. {"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"}. {"Delete message of the day","Bericht van de dag verwijderen"}. {"Delete message of the day on all hosts","Verwijder bericht-van-de-dag op alle hosts"}. {"Delete Selected","Geselecteerde verwijderen"}. {"Delete User","Verwijder Gebruiker"}. {"Deliver event notifications","Gebeurtenisbevestigingen Sturen"}. {"Deliver payloads with event notifications","Berichten bezorgen samen met gebeurtenisnotificaties"}. {"Description:","Beschrijving:"}. {"Disc only copy","Harde schijf"}. {"Displayed Groups:","Weergegeven groepen:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Geef Uw wachtwoord aan niemand, zelfs niet aan de beheerders van deze Jabber-server."}. {"Dump Backup to Text File at ","Backup naar een tekstbestand schrijven op "}. {"Dump to Text File","Backup naar een tekstbestand schrijven"}. {"Edit Properties","Eigenschappen bewerken"}. {"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"}. {"ejabberd Web Admin","ejabberd Webbeheer"}. {"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]}"}. {"Enter nickname you want to register","Voer de bijnaam in die u wilt registreren"}. {"Enter path to backup file","Voer pad naar backupbestand in"}. {"Enter path to jabberd14 spool dir","Voer pad naar jabberd14-spool-directory in"}. {"Enter path to jabberd14 spool file","Voer pad naar jabberd14-spool-bestand in"}. {"Enter path to text file","Voer pad naar backupbestand in"}. {"Enter the text you see","Voer de getoonde tekst in"}. {"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.","Voer de gebruikersnaam en de coderingen in die u wilt gebruiken voor verbindingen met IRC-servers. Klik op 'Volgende' om meer velden aan te maken. Klik op \"Voltooi' om de instellingen op te slaan."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Voer de gebruikersnaam, coderingen, poorten en wachtwoorden in die U wilt gebruiken voor het verbinden met IRC-servers"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"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):"}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Gebruik de velden om te zoeken (Voeg achteraan het teken * toe om te zoeken naar alles wat met het eerste deel begint.)."}. {"Friday","Vrijdag"}. {"From ~s","Van ~s"}. {"From","Van"}. {"Full Name","Volledige naam"}. {"Get Number of Online Users","Aantal Aanwezige Gebruikers Opvragen"}. {"Get Number of Registered Users","Aantal Geregistreerde Gebruikers Opvragen"}. {"Get User Last Login Time","Tijd van Laatste Aanmelding Opvragen"}. {"Get User Password","Gebruikerswachtwoord Opvragen"}. {"Get User Statistics","Gebruikers-statistieken Opvragen"}. {"Grant voice to this person?","Stemaanvraag honoreren voor deze persoon?"}. {"Group ","Groep "}. {"Groups","Groepen"}. {"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","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."}. {"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.","Als u verschillende poorten, wachtwoorden en coderingen wilt opgeven voor elke IRC-server, vul dan deze lijst met het volgende formaat: '{\"IRC-server\", \"codering\", poort, \"wachtwoord\"}'. Standaard gebruikt deze service de codering \"~s\", poort ~p, leeg wachtwoord."}. {"Import Directory","Directory importeren"}. {"Import File","Bestand importeren"}. {"Import user data from jabberd14 spool file:","Importeer gebruikersdata via spool-bestanden van jabberd14"}. {"Import User from File at ","Importeer gebruiker via bestand op "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importeer gebruikersdata van een PIEFXIS-bestand (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","IRC kanaal (zonder eerste #)"}. {"IRC server","IRC-server"}. {"IRC settings","IRC instellingen"}. {"IRC Transport","IRC-transport"}. {"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"}. {"January","Januari"}. {"Join IRC channel","Ga IRC kanaal binnen"}. {"joins the room","betrad de chatruimte"}. {"Join the IRC channel here.","Ga het IRC kanaal binnen"}. {"Join the IRC channel in this Jabber ID: ~s","Ga het IRC kanaal van deze Jabber ID binnen: ~s"}. {"July","Juli"}. {"June","Juni"}. {"Last Activity","Laatste activiteit"}. {"Last login","Laatste Aanmelding"}. {"Last month","Afgelopen maand"}. {"Last year","Afgelopen jaar"}. {"leaves the room","verliet de chatruimte"}. {"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"}. {"Make room members-only","Chatruimte enkel toegankelijk maken voor leden"}. {"Make room moderated","Chatruimte gemodereerd maken"}. {"Make room password protected","Chatruimte beveiligen met een wachtwoord"}. {"Make room persistent","Chatruimte blijvend maken"}. {"Make room public searchable","Chatruimte doorzoekbaar maken"}. {"March","Maart"}. {"Maximum Number of Occupants","Maximum aantal aanwezigen"}. {"Max # of items to persist","Maximum aantal in het geheugen te bewaren items"}. {"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"}. {"Modules at ~p","Modules op ~p"}. {"Modules","Modules"}. {"Monday","Maandag"}. {"Multicast","Multicast"}. {"Multi-User Chat","Groepschat"}. {"Name:","Naam:"}. {"Name","Naam"}. {"Never","Nooit"}. {"New Password:","Nieuw Wachtwoord:"}. {"Nickname","Bijnaam"}. {"Nickname Registration at ","Registratie van een bijnaam op "}. {"Nickname ~s does not exist in the room","De bijnaam ~s bestaat niet in deze chatruimte"}. {"nobody","niemand"}. {"No body provided for announce message","De mededeling bevat geen bericht"}. {"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"}. {"No resource provided","Geen bron opgegeven"}. {"Not Found","Niet gevonden"}. {"Notify subscribers when items are removed from the node","Abonnees informeren wanneer items verwijderd worden uit de node"}. {"Notify subscribers when the node configuration changes","Abonnees informeren wanneer de instellingen van de node veranderen"}. {"Notify subscribers when the node is deleted","Abonnees informeren wanneer de node verwijderd word"}. {"November","November"}. {"Number of occupants","Aantal aanwezigen"}. {"Number of online users","Aantal Aanwezige Gebruikers"}. {"Number of registered users","Aantal Geregistreerde Gebruikers"}. {"October","Oktober"}. {"Offline Messages:","Offline berichten:"}. {"Offline Messages","Offline berichten"}. {"OK","OK"}. {"Old Password:","Oud Wachtwoord:"}. {"Online","Online"}. {"Online Users:","Online gebruikers:"}. {"Online Users","Online gebruikers"}. {"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"}. {"Owner privileges required","U hebt eigenaarsprivileges nodig"}. {"Packet","Pakket"}. {"Password ~b","Wachtwoord ~b"}. {"Password Verification:","Wachtwoord Bevestiging:"}. {"Password Verification","Wachtwoord Bevestiging"}. {"Password:","Wachtwoord:"}. {"Password","Wachtwoord"}. {"Path to Dir","Pad naar directory"}. {"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."}. {"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"}. {"Present real Jabber IDs to","Jabber ID's kunnen achterhaald worden door"}. {"private, ","privé, "}. {"Protocol","Protocol"}. {"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:"}. {"Registered Users","Geregistreerde gebruikers"}. {"Register","Registreer"}. {"Registration in mod_irc for ","Registratie van "}. {"Remote copy","Op andere nodes in de cluster"}. {"Remove All Offline Messages","Verwijder alle offline berichten"}. {"Remove User","Gebruiker verwijderen"}. {"Remove","Verwijderen"}. {"Replaced by new connection","Vervangen door een nieuwe verbinding"}. {"Resources","Bronnen"}. {"Restart","Herstarten"}. {"Restart Service","Herstart Service"}. {"Restore Backup from File at ","Binaire backup direct herstellen op "}. {"Restore","Binaire backup direct herstellen"}. {"Restore binary backup after next ejabberd restart (requires less memory):","Binaire backup herstellen na herstart van ejabberd (vereist minder geheugen):"}. {"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"}. {"Roster groups allowed to subscribe","Contactlijst-groepen die mogen abonneren"}. {"Roster of ","Roster van "}. {"Roster","Roster"}. {"Roster size","Contactlijst Groote"}. {"RPC Call Error","RPC-oproepfout"}. {"Running Nodes","Draaiende nodes"}. {"~s access rule configuration","Access rules op ~s"}. {"Saturday","Zaterdag"}. {"Script check","Controle van script"}. {"Search Results for ","Zoekresultaten voor "}. {"Search users in ","Gebruikers zoeken in "}. {"Send announcement to all online users","Mededeling verzenden naar alle online gebruikers"}. {"Send announcement to all online users on all hosts","Mededeling verzenden naar alle online gebruikers op alle virtuele hosts"}. {"Send announcement to all users","Mededeling verzenden naar alle gebruikers"}. {"Send announcement to all users on all hosts","Stuur aankondiging aan alle gebruikers op alle hosts"}. {"September","September"}. {"Server ~b","Server ~b"}. {"Server:","Server:"}. {"Set message of the day and send to online users","Bericht van de dag instellen en verzenden naar online gebruikers"}. {"Set message of the day on all hosts and send to online users","Stel bericht-van-de-dag in op alle hosts en stuur naar aanwezige gebruikers"}. {"Shared Roster Groups","Gedeelde rostergroepen"}. {"Show Integral Table","Volledige tabel laten zien"}. {"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 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"}. {"~s's Offline Messages Queue","offline berichten van ~s"}. {"Start Modules at ","Modules starten op "}. {"Start Modules","Modules starten"}. {"Start","Starten"}. {"Statistics of ~p","Statistieken van ~p"}. {"Statistics","Statistieken"}. {"Stop Modules at ","Modules stoppen op "}. {"Stop Modules","Modules stoppen"}. {"Stopped Nodes","Gestopte nodes"}. {"Stop","Stoppen"}. {"Storage Type","Opslagmethode"}. {"Store binary backup:","Binaire backup maken:"}. {"Store plain text backup:","Backup naar een tekstbestand schrijven:"}. {"Subject","Onderwerp"}. {"Submitted","Verzonden"}. {"Submit","Verzenden"}. {"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:"}. {"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."}. {"Thursday","Donderdag"}. {"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"}. {"Update","Bijwerken"}. {"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"}. {"User","Gebruiker"}. {"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"}. ejabberd-16.01/priv/msgs/zh.msg0000644000232200023220000005712312645157216016730 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","访问é…ç½®"}. {"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","对用户的动作"}. {"Add Jabber ID","添加 Jabber ID"}. {"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?","å…许该 Jabber ID 订阅该 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 voice requests","å…许访客å‘é€å£°éŸ³è¯·æ±‚"}. {"All Users","所有用户"}. {"Announcements","通知"}. {"anyone","任何人"}. {"A password is required to enter this room","进入此房间需è¦å¯†ç "}. {"April","四月"}. {"August","八月"}. {"Backup Management","备份管ç†"}. {"Backup to File at ","备份文件ä½äºŽ"}. {"Backup","备份"}. {"Bad format","æ ¼å¼é”™è¯¯"}. {"Birthday","出生日期"}. {"CAPTCHA web page","验è¯ç ç½‘页"}. {"Change Password","更改密ç "}. {"Change User Password","更改用户密ç "}. {"Characters not allowed:","ç¦ç”¨å­—符:"}. {"Chatroom configuration modified","èŠå¤©å®¤é…置已修改"}. {"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","请选择è¦åœæ­¢çš„æ¨¡å—"}. {"Choose storage type of tables","请选择表格的存储类型"}. {"Choose whether to approve this entity's subscription.","选择是å¦å…许该实体的订阅"}. {"City","城市"}. {"Commands","命令"}. {"Conference room does not exist","会议室ä¸å­˜åœ¨"}. {"Configuration of room ~s","房间 ~s çš„é…ç½® "}. {"Configuration","é…ç½®"}. {"Connected Resources:","已连接资æº:"}. {"Connections parameters","è¿žæŽ¥å‚æ•°"}. {"Country","国家"}. {"CPU Time:","CPU 时间:"}. {"Database Tables Configuration at ","æ•°æ®åº“表格é…ç½®ä½äºŽ"}. {"Database","æ•°æ®åº“"}. {"December","å二月"}. {"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","用事件通告传输有效负载"}. {"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","转储到文本文件"}. {"Edit Properties","编辑属性"}. {"Either approve or decline the voice request.","æŽ¥å—æˆ–æ‹’ç»å£°éŸ³è¯·æ±‚"}. {"ejabberd IRC module","ejabberd IRC 模å—"}. {"ejabberd MUC module","ejabberd MUC 模å—"}. {"ejabberd Publish-Subscribe module","ejabberd å‘行-订阅模å—"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 å­—èŠ‚æµæ¨¡å—"}. {"ejabberd vCard module","ejabberd vCard 模å—"}. {"ejabberd Web Admin","ejabberd 网页管ç†"}. {"Elements","元素"}. {"Email","电å­é‚®ä»¶"}. {"Enable logging","å¯ç”¨æœåŠ¡å™¨ç«¯èŠå¤©è®°å½•"}. {"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 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 æœåС噍"}. {"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 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 用户(在字段末添加*æ¥åŒ¹é…å­ä¸²)"}. {"Friday","星期五"}. {"From ~s","æ¥è‡ª~s"}. {"From","从"}. {"Full Name","å…¨å"}. {"Get Number of Online Users","获å–在线用户数"}. {"Get Number of Registered Users","èŽ·å–æ³¨å†Œç”¨æˆ·æ•°"}. {"Get User Last Login Time","获å–用户上次登陆时间"}. {"Get User Password","获å–用户密ç "}. {"Get User Statistics","获å–用户统计"}. {"Grant voice to this person?","为此人授æƒå£°éŸ³?"}. {"Groups","组"}. {"Group ","组"}. {"has been banned","å·²è¢«ç¦æ­¢"}. {"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 been kicked","已被踢出"}. {" has set the subject to: ","已将标题设置为: "}. {"Host","主机"}. {"If you don't see the CAPTCHA image here, visit the 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.","如果您想为 IRC æœåŠ¡å™¨æŒ‡å®šä¸åŒçš„端å£, 密ç , ç¼–ç , 请用 '{\"irc æœåС噍\", \"ç¼–ç \", 端å£, \"密ç \"}' æ ¼å¼çš„值填充此表å•. 默认情况下此æœåŠ¡ä½¿ç”¨\"~s\"ç¼–ç , ~p 端å£, 密ç ä¸ºç©º."}. {"Import Directory","导入目录"}. {"Import File","导入文件"}. {"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 文件导入用户"}. {"Improper message type","䏿°å½“的消æ¯ç±»åž‹"}. {"Incorrect password","密ç ä¸æ­£ç¡®"}. {"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","现在称呼为"}. {"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 无效"}. {"January","一月"}. {"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","七月"}. {"June","六月"}. {"Last Activity","上次活动"}. {"Last login","上次登陆"}. {"Last month","上个月"}. {"Last year","上一年"}. {"leaves the room","离开房间"}. {"Listened Ports at ","监å¬çš„端å£ä½äºŽ "}. {"Listened Ports","被监å¬çš„端å£"}. {"List of modules to start","è¦å¯åŠ¨çš„æ¨¡å—列表"}. {"Low level update script","低级别更新脚本"}. {"Make participants list public","公开å‚与人列表"}. {"Make room CAPTCHA protected","ä¿æŠ¤æˆ¿é—´éªŒè¯ç "}. {"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","最大有效负载字节数"}. {"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","模å—"}. {"Module","模å—"}. {"Monday","星期一"}. {"Name:","å§“å:"}. {"Name","å§“å"}. {"Never","从未"}. {"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 not found","没有找到节点"}. {"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","当节点被删除时通知订阅人"}. {"November","å一月"}. {"Number of occupants","驻留人数"}. {"Number of online users","在线用户数"}. {"Number of registered users","注册用户数"}. {"October","åæœˆ"}. {"Offline Messages:","离线消æ¯:"}. {"Offline Messages","离线消æ¯"}. {"OK","确定"}. {"Old Password:","旧密ç : "}. {"Online Users:","在线用户:"}. {"Online Users","在线用户"}. {"Online","在线"}. {"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 连接"}. {"Owner privileges required","éœ€è¦æŒæœ‰äººæƒé™"}. {"Packet","æ•°æ®åŒ…"}. {"Password ~b","~b 的密ç "}. {"Password Verification:","密ç ç¡®è®¤:"}. {"Password Verification","确认密ç "}. {"Password:","密ç :"}. {"Password","密ç "}. {"Path to Dir","目录的路径"}. {"Path to File","文件路径"}. {"Pending","挂起"}. {"Period: ","æŒç»­æ—¶é—´: "}. {"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","端å£"}. {"Present real Jabber IDs to","将真实 Jabber ID 显示给"}. {"private, ","ä¿å¯†, "}. {"Protocol","åè®®"}. {"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","注册用户"}. {"Register","注册"}. {"Registration in mod_irc for ","mod_irc 中的注册是为 "}. {"Remote copy","远程å¤åˆ¶"}. {"Remove All Offline Messages","移除所有离线消æ¯"}. {"Remove User","删除用户"}. {"Remove","移除"}. {"Replaced by new connection","被新的连接替æ¢"}. {"Resources","资æº"}. {"Restart Service","é‡å¯æœåŠ¡"}. {"Restart","é‡å¯"}. {"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 creation is denied by service policy","创建房间被æœåŠ¡ç­–ç•¥æ‹’ç»"}. {"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 ","æœç´¢ç»“æžœå±žäºŽå…³é”®è¯ "}. {"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:","æœåС噍:"}. {"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 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","å¯åŠ¨æ¨¡å—"}. {"Start","开始"}. {"Statistics of ~p","~p 的统计"}. {"Statistics","统计"}. {"Stop Modules at ","è¦åœæ­¢çš„æ¨¡å—ä½äºŽ "}. {"Stop Modules","åœæ­¢æ¨¡å—"}. {"Stopped Nodes","å·²ç»åœæ­¢çš„节点"}. {"Stop","åœæ­¢"}. {"Storage Type","存储类型"}. {"Store binary backup:","存储为二进制备份:"}. {"Store plain text backup:","存储为普通文本备份:"}. {"Subject","标题"}. {"Submitted","å·²æäº¤"}. {"Submit","æäº¤"}. {"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: ","修改密ç å‡ºé”™: "}. {"There was an error creating the account: ","叿ˆ·åˆ›å»ºå‡ºé”™: "}. {"There was an error deleting the account: ","叿ˆ·åˆ é™¤å¤±è´¥: "}. {"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 叿ˆ·"}. {"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","å–æ¶ˆæ³¨å†Œ"}. {"Update message of the day (don't send)","æ›´æ–°æ¯æ—¥æ¶ˆæ¯(ä¸å‘é€)"}. {"Update message of the day on all hosts (don't send)","æ›´æ–°æ‰€æœ‰ä¸»æœºä¸Šçš„æ¯æ—¥æ¶ˆæ¯(ä¸å‘é€)"}. {"Update plan","更新计划"}. {"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","用户上次活动"}. {"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"}. ejabberd-16.01/priv/msgs/ru.msg0000644000232200023220000011344512645157216016735 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"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","Добавить Jabber ID"}. {"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?","Разрешить Ñтому Jabber ID подпиÑатьÑÑ Ð½Ð° данный узел?"}. {"Allow users to change the subject","Разрешить пользователÑм изменÑть тему"}. {"Allow users to query other users","Разрешить iq-запроÑÑ‹ к пользователÑм"}. {"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","Разрешить поÑетителÑм вÑтавлÑть текcÑ‚ ÑтатуÑа в ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ приÑутÑтвии"}. {"Allow visitors to send voice requests","Разрешить поÑетителÑм запрашивать право голоÑа"}. {"All Users","Ð’Ñе пользователи"}. {"Announcements","ОбъÑвлениÑ"}. {"anyone","вÑем учаÑтникам"}. {"A password is required to enter this room","Чтобы войти в Ñту конференцию, нужен пароль"}. {"April","апрелÑ"}. {"August","авгуÑта"}. {"Backup Management","Управление резервным копированием"}. {"Backup of ~p","Резервное копирование ~p"}. {"Backup to File at ","Резервное копирование в файл на "}. {"Backup","Резервное копирование"}. {"Bad format","Ðеправильный формат"}. {"Birthday","День рождениÑ"}. {"CAPTCHA web page","СÑылка на капчу"}. {"Change Password","Сменить пароль"}. {"Change User Password","Изменить пароль пользователÑ"}. {"Characters not allowed:","ÐедопуÑтимые Ñимволы:"}. {"Chatroom configuration modified","ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ изменилаÑÑŒ"}. {"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","Выберите модули, которые Ñледует оÑтановить"}. {"Choose storage type of tables","Выберите тип Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†"}. {"Choose whether to approve this entity's subscription.","Решите: предоÑтавить ли подпиÑку Ñтому объекту."}. {"City","Город"}. {"Commands","Команды"}. {"Conference room does not exist","ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ Ð½Ðµ ÑущеÑтвует"}. {"Configuration of room ~s","ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹ ~s"}. {"Configuration","КонфигурациÑ"}. {"Connected Resources:","Подключённые реÑурÑÑ‹:"}. {"Connections parameters","Параметры ÑоединениÑ"}. {"Country","Страна"}. {"CPU Time:","ПроцеÑÑорное времÑ:"}. {"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 Selected","Удалить выделенные"}. {"Delete User","Удалить пользователÑ"}. {"Deliver event notifications","ДоÑтавлÑть ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ ÑобытиÑÑ…"}. {"Deliver payloads with event notifications","ДоÑтавлÑть вмеÑте Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñми o публикациÑÑ… Ñами публикации"}. {"Description:","ОпиÑание:"}. {"Disc only copy","только диÑк"}. {"Displayed Groups:","Видимые группы:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Ðе говорите никому Ñвой пароль, даже админиÑтраторам Ñервера."}. {"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 Multicast ÑервиÑ"}. {"ejabberd Publish-Subscribe module","Модуль ejabberd Публикации-ПодпиÑки"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}. {"ejabberd vCard module","ejabberd vCard модуль"}. {"ejabberd Web Admin","Web-Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸ÑÑ‚Ñ€Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ejabberd"}. {"Elements","Элементы"}. {"Email","Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð°"}. {"Enable logging","Включить журналирование"}. {"Enable message archiving","Включить хранение Ñообщений"}. {"Encoding for server ~b","Кодировка Ñервера ~b"}. {"End User Session","Завершить ÑÐµÐ°Ð½Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"}. {"Enter list of {Module, [Options]}","Введите ÑпиÑок вида {Module, [Options]}"}. {"Enter nickname you want to register","Введите пÑевдоним, который Ð’Ñ‹ хотели бы зарегиÑтрировать"}. {"Enter path to backup file","Введите путь к резервному файлу"}. {"Enter path to jabberd14 spool dir","Введите путь к директории Ñпула jabberd14"}. {"Enter path to jabberd14 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-Ñерверам"}. {"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","ИÑключить показ капчи Ð´Ð»Ñ ÑпиÑка 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 (ЕÑли добавить * в конец полÑ, то проиÑходит поиÑк подÑтроки)"}. {"Friday","ПÑтница"}. {"From ~s","От ~s"}. {"From","От кого"}. {"Full Name","Полное имÑ"}. {"Get Number of Online Users","Получить количеÑтво подключённых пользователей"}. {"Get Number of Registered Users","Получить количеÑтво зарегиÑтрированных пользователей"}. {"Get User Last Login Time","Получить Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"}. {"Get User Password","Получить пароль пользователÑ"}. {"Get User Statistics","Получить ÑтатиÑтику по пользователю"}. {"Grant voice to this person?","ПредоÑтавить голоÑ?"}. {"Groups","Группы"}. {"Group ","Группа "}. {"has been banned","запретили входить в комнату"}. {"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 been kicked","выгнали из комнаты"}. {" has set the subject to: "," уÑтановил(а) тему: "}. {"Host","ХоÑÑ‚"}. {"If you don't see the CAPTCHA image here, visit the 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.","Чтобы указать различные порты, пароли, кодировки Ð´Ð»Ñ Ñ€Ð°Ð·Ð½Ñ‹Ñ… Ñерверов IRC, заполните ÑпиÑок значениÑми в формате '{\"Ñервер IRC\", \"кодировка\", порт, \"пароль\"}'. По умолчанию ÑÐµÑ€Ð²Ð¸Ñ Ð¸Ñпользует кодировку \"~s\", порт ~p, пуÑтой пароль."}. {"Import Directory","Импорт из директории"}. {"Import File","Импорт из файла"}. {"Import user data from jabberd14 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:","Импорт пользовательÑких данных из буферной директории 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 адреÑа"}. {"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","изменил(а) Ð¸Ð¼Ñ Ð½Ð°"}. {"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 недопуÑтимый"}. {"January","ÑнварÑ"}. {"Join IRC channel","ПриÑоединитьÑÑ Ðº каналу IRC"}. {"joins the room","вошёл(а) в комнату"}. {"Join the IRC channel here.","ПриÑоединÑйтеÑÑŒ к каналу IRC"}. {"Join the IRC channel in this Jabber ID: ~s","ПриÑоединитьÑÑ Ðº каналу IRC Ñ Jabber ID: ~s"}. {"July","июлÑ"}. {"June","июнÑ"}. {"Last Activity","ПоÑледнее подключение"}. {"Last login","Ð’Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего подключениÑ"}. {"Last month","За поÑледний меÑÑц"}. {"Last year","За поÑледний год"}. {"leaves the room","вышел(а) из комнаты"}. {"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","Сделать комнату защищённой капчей"}. {"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","МакÑимальный размер полезной нагрузки в байтах"}. {"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"}. {"Modules","Модули"}. {"Module","Модуль"}. {"Monday","Понедельник"}. {"Multicast","МультикаÑÑ‚"}. {"Multi-User Chat","КонференциÑ"}. {"Name:","Ðазвание:"}. {"Name","Ðазвание"}. {"Never","Ðикогда"}. {"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 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","УведомлÑть подпиÑчиков об удалении Ñборника"}. {"November","ноÑбрÑ"}. {"Number of occupants","ЧиÑло приÑутÑтвующих"}. {"Number of online users","КоличеÑтво подключённых пользователей"}. {"Number of registered users","КоличеÑтво зарегиÑтрированных пользователей"}. {"October","октÑбрÑ"}. {"Offline Messages:","Офлайновые ÑообщениÑ:"}. {"Offline Messages","Офлайновые ÑообщениÑ"}. {"OK","Продолжить"}. {"Old Password:","Старый пароль:"}. {"Online Users:","Подключённые пользователи:"}. {"Online Users","Подключённые пользователи"}. {"Online","Подключён"}. {"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-ÑоединениÑ"}. {"Owner privileges required","ТребуютÑÑ Ð¿Ñ€Ð°Ð²Ð° владельца"}. {"Packet","Пакет"}. {"Password ~b","Пароль ~b"}. {"Password Verification:","Проверка паролÑ:"}. {"Password Verification","Проверка паролÑ"}. {"Password:","Пароль:"}. {"Password","Пароль"}. {"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), то его резервное копирование Ñледует оÑущеÑтвлÑть отдельно."}. {"Please, wait for a while before sending new voice request","ПожалуйÑта, подождите перед тем как подать новый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° право голоÑа"}. {"Pong","Понг"}. {"Port ~b","Порт ~b"}. {"Port","Порт"}. {"Present real Jabber IDs to","Сделать реальные Jabber ID учаÑтников видимыми"}. {"private, ","приватнаÑ, "}. {"Protocol","Протокол"}. {"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:","ЗарегиÑтрированные пользователи:"}. {"Registered Users","ЗарегиÑтрированные пользователи"}. {"Register","ЗарегиÑтрировать"}. {"Registration in mod_irc for ","РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð² mod_irc Ð´Ð»Ñ "}. {"Remote copy","не хранитÑÑ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾"}. {"Remove All Offline Messages","Удалить вÑе офлайновые ÑообщениÑ"}. {"Remove User","Удалить пользователÑ"}. {"Remove","Удалить"}. {"Replaced by new connection","Заменено новым Ñоединением"}. {"Resources","РеÑурÑÑ‹"}. {"Restart Service","ПерезапуÑтить Ñлужбу"}. {"Restart","ПерезапуÑтить"}. {"Restore Backup from File at ","ВоÑÑтановление из резервной копии на "}. {"Restore binary backup after next ejabberd restart (requires less memory):","ВоÑÑтановить из бинарной резервной копии при Ñледующем запуÑке (требует меньше памÑти):"}. {"Restore binary backup immediately:","ВоÑÑтановить из бинарной резервной копии немедленно:"}. {"Restore plain text backup immediately:","ВоÑÑтановить из текÑтовой резервной копии немедленно:"}. {"Restore","ВоÑÑтановление из резервной копии"}. {"Room Configuration","ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¼Ð½Ð°Ñ‚Ñ‹"}. {"Room creation is denied by service policy","Cоздавать конференцию запрещено политикой Ñлужбы"}. {"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 ","Результаты поиÑка в "}. {"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:","Сервер:"}. {"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 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","Oчередь офлайновых Ñообщений ~s"}. {"Start Modules at ","ЗапуÑк модулей на "}. {"Start Modules","ЗапуÑк модулей"}. {"Start","ЗапуÑтить"}. {"Statistics of ~p","ÑтатиÑтика узла ~p"}. {"Statistics","СтатиÑтика"}. {"Stop Modules at ","ОÑтановка модулей на "}. {"Stop Modules","ОÑтановка модулей"}. {"Stopped Nodes","ОÑтановленные узлы"}. {"Stop","ОÑтановить"}. {"Storage Type","Тип таблицы"}. {"Store binary backup:","Сохранить бинарную резервную копию:"}. {"Store plain text backup:","Сохранить текÑтовую резервную копию:"}. {"Subject","Тема"}. {"Submitted","Отправлено"}. {"Submit","Отправить"}. {"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: ","Ошибка при Ñмене паролÑ:"}. {"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-аккаунт Ñ Ñтого Ñервера."}. {"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","Удалить"}. {"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 Management","Управление пользователÑми"}. {"Username:","Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ:"}. {"Users are not allowed to register accounts so quickly","Пользователи не могут региÑтрировать учётные запиÑи так быÑтро"}. {"Users Last Activity","СтатиÑтика поÑледнего Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹"}. {"Users","Пользователи"}. {"User ~s","Пользователь ~s"}. {"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","Чтобы наÑтроить параметры 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"}. ejabberd-16.01/priv/msgs/cs.msg0000644000232200023220000006441612645157216016717 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"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)"}. {"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"}. {"Add Jabber ID","PÅ™idat Jabber ID"}. {"Add New","PÅ™idat nový"}. {"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?"}. {"Allow users to change the subject","Povolit uživatelům mÄ›nit téma místnosti"}. {"Allow users to query other users","Povolit uživatelům odesílat požadavky (query) ostatním uživatelům"}. {"Allow users to send invites","Povolit uživatelům posílání pozvánek"}. {"Allow users to send private messages","Povolit uživatelům odesílat soukromé zprávy"}. {"Allow visitors to change nickname","Povolit návÅ¡tÄ›vníkům mÄ›nit pÅ™ezdívku"}. {"Allow visitors to send private messages to","Povolit návÅ¡tÄ›vníkům odesílat soukromé zprávy"}. {"Allow visitors to send status text in presence updates","Povolit návÅ¡tÄ›vníkům posílat stavové zprávy ve statusu"}. {"Allow visitors to send voice requests","Povolit uživatelům posílat žádosti o voice práva"}. {"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í"}. {"Backup to File at ","Záloha do souboru na "}. {"Backup","Zálohovat"}. {"Bad format","Nesprávný formát"}. {"Birthday","Datum narození"}. {"CAPTCHA web page","Webová stránka CAPTCHA"}. {"Change Password","ZmÄ›nit heslo"}. {"Change User Password","ZmÄ›nit heslo uživatele"}. {"Characters not allowed:","Nepřípustné znaky:"}. {"Chatroom configuration modified","Nastavení diskuzní místnosti bylo zmÄ›nÄ›no"}. {"Chatroom is created","Konference vytvoÅ™ena"}. {"Chatroom is destroyed","Konference zruÅ¡ena"}. {"Chatroom is started","Konference spuÅ¡tÄ›na"}. {"Chatroom is stopped","Konference zastavena"}. {"Chatrooms","Konference"}. {"Choose a username and password to register with this server","Zadejte jméno uživatele a heslo pro registraci na tomto serveru"}. {"Choose modules to stop","Vyberte moduly, které mají být zastaveny"}. {"Choose storage type of tables","Vyberte typ úložiÅ¡tÄ› pro tabulky"}. {"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:"}. {"Connections parameters","Parametry spojení"}. {"Country","ZemÄ›"}. {"CPU Time:","ÄŒas procesoru"}. {"Database","Databáze"}. {"Database Tables Configuration at ","Konfigurace databázových tabulek "}. {"December",". prosince"}. {"Default users as participants","Uživatelé jsou implicitnÄ› Äleny"}. {"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 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"}. {"Description:","Popis:"}. {"Disc only copy","Jen kopie disku"}. {"Displayed Groups:","Zobrazené skupiny:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Nikdy nikomu nesdÄ›lujte své heslo, ani administrátorovi serveru Jabberu."}. {"Dump Backup to Text File at ","Uložit zálohu do textového souboru na "}. {"Dump to Text File","Uložit do textového souboru"}. {"Edit Properties","Upravit vlastnosti"}. {"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 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"}. {"Enable logging","Zaznamenávat konverzace"}. {"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]}"}. {"Enter nickname you want to register","Zadejte pÅ™ezdívku, kterou chcete zaregistrovat"}. {"Enter path to backup file","Zadajte cestu k souboru se zálohou"}. {"Enter path to jabberd14 spool dir","Zadejte cestu k jabberd14 spool adresáři"}. {"Enter path to jabberd14 spool file","Zadejte cestu k spool souboru jabberd14"}. {"Enter path to text file","Zadajte cestu k textovému souboru"}. {"Enter the text you see","Zadejte text, který vidíte"}. {"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.","Zadejte pÅ™ezdívku a kódování, které chcete používat pro pÅ™ipojení k serverům IRC. StisknÄ›te 'Další' pro více políÄek k vyplnÄ›ní. StisknÄ›te 'DokonÄit' pro uložení nastavení."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Zadejte pÅ™ezdívku, kódování, porty a hesla, které chcete používat pro pÅ™ipojení k serverům IRC"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"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 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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Pro vyhledání uživatele Jabberu vyplňte formulář (na konec pÅ™idejte znak * pro vyhledání podÅ™etÄ›zce)"}. {"Friday","Pátek"}. {"From","Od"}. {"From ~s","Od ~s"}. {"Full Name","Celé jméno"}. {"Get Number of Online Users","Získat poÄet online uživatelů"}. {"Get Number of Registered Users","Získat poÄet registrovaných uživatelů"}. {"Get User Last Login Time","Získat Äas podleního pÅ™ihlášení uživatele"}. {"Get User Password","Získat heslo uživatele"}. {"Get User Statistics","Získat statistiky uživatele"}. {"Grant voice to this person?","UdÄ›lit voice práva této osobÄ›?"}. {"Group ","Skupina "}. {"Groups","Skupiny"}. {"has been banned","byl(a) zablokován(a)"}. {"has been kicked because of an affiliation change","byl(a) vyhozen(a) kvůli zmÄ›nÄ› pÅ™iÅ™azení"}. {"has been kicked because of a system shutdown","byl(a) vyhozen(a), protože dojde k vypnutí systému"}. {"has been kicked because the room has been changed to members-only","byl(a) vyhozen(a), protože mísnost je nyní pouze pro Äleny"}. {"has been kicked","byl(a) vyhozen(a) z místnosti"}. {" has set the subject to: "," zmÄ›nil(a) téma na: "}. {"Host","Hostitel"}. {"If you don't see the CAPTCHA image here, visit the web page.","Pokud zde nevidíte obrázek CAPTCHA, pÅ™ejdÄ›te na webovou stránku."}. {"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.","Pokud chcete zadat jiné kódování pro IRC servery, vyplňte seznam s hodnotami ve formátu '{\"irc server\",\"encoding\", port, \"password\"}'. Výchozí kódování pro tuto službu je \"~s\", port ~p, empty password."}. {"Import Directory","Import adresáře"}. {"Import File","Import souboru"}. {"Import user data from jabberd14 spool file:","Importovat uživatele z jabberd14 spool souborů:"}. {"Import User from File at ","Importovat uživatele ze souboru na "}. {"Import users data from a PIEFXIS file (XEP-0227):","Importovat uživatele ze souboru ve formátu PIEFXIS (XEP-0227):"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","IRC kanál (bez poÄáteÄního #)"}. {"IRC server","IRC pÅ™ezdívka"}. {"IRC settings","Nastavení IRC"}. {"IRC Transport","IRC transport"}. {"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é"}. {"January",". ledna"}. {"Join IRC channel","Vstoupit do IRC kanálu"}. {"joins the room","vstoupil(a) do místnosti"}. {"Join the IRC channel here.","Vstoupit do tohoto IRC kanálu."}. {"Join the IRC channel in this Jabber ID: ~s","Vstupte do IRC kanálu s tímto Jabber ID: ~s"}. {"July",". Äervence"}. {"June",". Äervna"}. {"Last Activity","Poslední aktivita"}. {"Last login","Poslední pÅ™ihlášení"}. {"Last month","Poslední mÄ›síc"}. {"Last year","Poslední rok"}. {"leaves the room","opustil(a) místnost"}. {"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é"}. {"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"}. {"Make room members-only","Zpřístupnit místnost jen Älenům"}. {"Make room moderated","Nastavit místnost jako moderovanou"}. {"Make room password protected","Chránit místnost heslem"}. {"Make room persistent","Nastavit místnost jako stálou"}. {"Make room public searchable","Nastavit místnost jako veÅ™ejnou"}. {"March",". bÅ™ezna"}. {"Maximum Number of Occupants","PoÄet úÄastníků"}. {"Max # of items to persist","Maximální poÄet položek, které je možné natrvalo uložit"}. {"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"}. {"Modules","Moduly"}. {"Monday","PondÄ›lí"}. {"Name:","Jméno:"}. {"Name","Jméno"}. {"Never","Nikdy"}. {"New Password:","Nové heslo:"}. {"Nickname","PÅ™ezdívka"}. {"Nickname Registration at ","Registrace pÅ™ezdívky na "}. {"Nickname ~s does not exist in the room","PÅ™ezdívka ~s v místnosti neexistuje"}. {"nobody","nikdo"}. {"No body provided for announce message","Zpráva neobsahuje text"}. {"No Data","Žádná data"}. {"Node ID","ID uzlu"}. {"Node not found","Uzel nenalezen"}. {"Nodes","Uzly"}. {"No limit","Bez limitu"}. {"None","Nic"}. {"No resource provided","Nebyl poskytnut žádný zdroj"}. {"Not Found","Nenalezeno"}. {"Notify subscribers when items are removed from the node","Upozornit odbÄ›ratele na odstranÄ›ní položek z uzlu"}. {"Notify subscribers when the node configuration changes","Upozornit odbÄ›ratele na zmÄ›nu nastavení uzlu"}. {"Notify subscribers when the node is deleted","Upozornit odbÄ›ratele na smazání uzlu"}. {"November",". listopadu"}. {"Number of occupants","PoÄet úÄastníků"}. {"Number of online users","PoÄet online uživatelů"}. {"Number of registered users","PoÄet registrovaných uživatelů"}. {"October",". října"}. {"Offline Messages:","Offline zprávy:"}. {"Offline Messages","Offline zprávy"}. {"OK","OK"}. {"Old Password:","SouÄasné heslo:"}. {"Online","Online"}. {"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 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í"}. {"Owner privileges required","Jsou vyžadována práva vlastníka"}. {"Packet","Paket"}. {"Password ~b","Heslo ~b"}. {"Password:","Heslo:"}. {"Password","Heslo"}. {"Password Verification:","Ověření hesla:"}. {"Password Verification","Ověření hesla"}. {"Path to Dir","Cesta k adresáři"}. {"Path to File","Cesta k souboru"}. {"Pending","ÄŒekající"}. {"Period: ","ÄŒas: "}. {"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"}. {"Present real Jabber IDs to","Odhalovat skuteÄná Jabber ID"}. {"private, ","soukromá, "}. {"Protocol","Protokol"}. {"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é:"}. {"Register","Zaregistrovat se"}. {"Registration in mod_irc for ","Registrace do mod_irc na "}. {"Remote copy","Vzdálená kopie"}. {"Remove All Offline Messages","Odstranit vÅ¡echny offline zprávy"}. {"Remove","Odstranit"}. {"Remove User","Odstranit uživatele"}. {"Replaced by new connection","Nahrazeno novým spojením"}. {"Resources","Zdroje"}. {"Restart","Restart"}. {"Restart Service","Restartovat službu"}. {"Restore Backup from File at ","Obnovit zálohu ze souboru na "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Obnovit binární zálohu pÅ™i následujícím restartu ejabberd (vyžaduje ménÄ› pamÄ›ti)"}. {"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:"}. {"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"}. {"Roster groups allowed to subscribe","Skupiny kontaktů, které mohou odebírat"}. {"Roster of ","Seznam kontaktů "}. {"Roster","Seznam kontaktů"}. {"Roster size","Velikost seznamu kontaktů"}. {"RPC Call Error","Chyba RPC volání"}. {"Running Nodes","Běžící uzly"}. {"~s access rule configuration","~s konfigurace pravidla přístupu"}. {"Saturday","Sobota"}. {"Script check","Kontrola skriptu"}. {"Search Results for ","Výsledky hledání pro "}. {"Search users in ","Hledat uživatele v "}. {"Send announcement to all online users","Odeslat oznámení vÅ¡em online uživatelům"}. {"Send announcement to all online users on all hosts","Odeslat oznámení vÅ¡em online uživatelům na vÅ¡ech hostitelích"}. {"Send announcement to all users","Odeslat oznámení vÅ¡em uživatelům"}. {"Send announcement to all users on all hosts","Odeslat oznámení vÅ¡em uživatelům na vÅ¡ech hostitelích"}. {"September",". září"}. {"Server ~b","Server ~b"}. {"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ů"}. {"Show Integral Table","Zobrazit kompletní tabulku"}. {"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 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í"}. {"~s's Offline Messages Queue","Fronta offline zpráv uživatele ~s"}. {"Start Modules at ","Spustit moduly na "}. {"Start Modules","Spustit moduly"}. {"Start","Start"}. {"Statistics of ~p","Statistiky ~p"}. {"Statistics","Statistiky"}. {"Stop Modules at ","Zastavit moduly na "}. {"Stop Modules","Zastavit moduly"}. {"Stopped Nodes","Zastavené uzly"}. {"Stop","Stop"}. {"Storage Type","Typ úložiÅ¡tÄ›"}. {"Store binary backup:","Uložit binární zálohu:"}. {"Store plain text backup:","Uložit zálohu do textového souboru:"}. {"Subject","PÅ™edmÄ›t"}. {"Submit","Odeslat"}. {"Submitted","Odeslané"}. {"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Ä›."}. {"There was an error deleting the account: ","PÅ™i mazání úÄtu doÅ¡lo k chybÄ›: "}. {"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."}. {"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"}. {"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 plan","Aktualizovat plán"}. {"Update script","Aktualizované skripty"}. {"Uptime:","ÄŒas bÄ›hu:"}. {"Use of STARTTLS required","Je vyžadováno STARTTLS"}. {"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"}. ejabberd-16.01/priv/msgs/pt-br.msg0000644000232200023220000006710712645157216017336 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"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"}. {"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"}. {"Add Jabber ID","Adicionar ID jabber"}. {"Add New","Adicionar novo"}. {"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?"}. {"Allow users to change the subject","Permitir a usuários modificar o assunto"}. {"Allow users to query other users","Permitir a usuários pesquisar informações sobre os demais"}. {"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"}. {"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"}. {"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:"}. {"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 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"}. {"Choose modules to stop","Selecione módulos a parar"}. {"Choose storage type of tables","Selecione o tipo de armazenamento das tabelas"}. {"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:"}. {"Connections parameters","Parâmetros para as Conexões"}. {"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 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"}. {"Delete User","Deletar Usuário"}. {"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"}. {"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 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"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"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]}"}. {"Enter nickname you want to register","Introduza o apelido que quer registrar"}. {"Enter path to backup file","Introduza o caminho do arquivo de backup"}. {"Enter path to jabberd14 spool dir","Introduza o caminho para o diretório de fila do jabberd14"}. {"Enter path to jabberd14 spool file","Insira o caminho para a fila (arquivo) do jabberd14"}. {"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"}. {"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\"}]."}. {"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):"}. {"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"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Preencha o formulário para buscar usuários Jabber. Agrega * ao final de um campo para buscar sub-palavras."}. {"Friday","Sexta"}. {"From","De"}. {"From ~s","De ~s"}. {"Full Name","Nome completo"}. {"Get Number of Online Users","Obter Número de Usuários Online"}. {"Get Number of Registered Users","Obter Número de Usuários Registrados"}. {"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"}. {"has been kicked because of an affiliation change","foi desconectado porque por afiliação inválida"}. {"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: "}. {"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"}. {"Import user data from jabberd14 spool file:","Importar dados dos usuários de uma fila jabberd14:"}. {"Import User from File at ","Importar usuário a partir do arquivo em "}. {"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 (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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","Canal IRC (não coloque o #)"}. {"IRC server","Servidor IRC"}. {"IRC settings","Configurações do IRC"}. {"IRC Transport","Transporte IRC"}. {"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"}. {"January","Janeiro"}. {"Join IRC channel","Juntar-se ao canal IRC"}. {"joins the room","Entrar na sala"}. {"Join the IRC channel here.","Aqui! Juntar-se ao canal IRC."}. {"Join the IRC channel in this Jabber ID: ~s","Entrar no canal IRC, neste ID Jabber: ~s"}. {"July","Julho"}. {"June","Junho"}. {"Last Activity","Última atividade"}. {"Last login","Último login"}. {"Last month","Último mês"}. {"Last year","Último ano"}. {"leaves the room","Sair da sala"}. {"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"}. {"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 persistent","Tornar sala persistente"}. {"Make room public searchable","Tornar sala pública possível de ser encontrada"}. {"March","Março"}. {"Maximum Number of Occupants","Número máximo de participantes"}. {"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"}. {"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"}. {"nobody","ninguém"}. {"No body provided for announce message","Nenhum corpo de texto fornecido para anunciar mensagem"}. {"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"}. {"No resource provided","Nenhum recurso foi informado"}. {"Not Found","Não encontrado"}. {"Notify subscribers when items are removed from the node","Notificar subscritores quando os elementos se eliminem do nodo"}. {"Notify subscribers when the node configuration changes","Notificar subscritores quando cambia la configuração do nodo"}. {"Notify subscribers when the node is deleted","Notificar subscritores quando o nodo se elimine"}. {"November","Novembro"}. {"Number of occupants","Número de participantes"}. {"Number of online users","Número de usuários online"}. {"Number of registered users","Número de usuários registrados"}. {"October","Outubro"}. {"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"}. {"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"}. {"Owner privileges required","Se requere privilégios de proprietário da sala"}. {"Packet","Pacote"}. {"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."}. {"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"}. {"Present real Jabber IDs to","Tornar o Jabber ID real visível por"}. {"private, ","privado, "}. {"Protocol","Porta"}. {"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"}. {"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"}. {"Remove","Remover"}. {"Remove User","Remover usuário"}. {"Replaced by new connection","Substituído por nova conexão"}. {"Resources","Recursos"}. {"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 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"}. {"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"}. {"Roster groups allowed to subscribe","Listar grupos autorizados"}. {"Roster","Lista de contatos"}. {"Roster of ","Lista de contatos de "}. {"Roster size","Tamanho da Lista"}. {"RPC Call Error","Erro de chamada RPC"}. {"Running Nodes","Nos em execução"}. {"~s access rule configuration","Configuração da Regra de Acesso ~s"}. {"Saturday","Sábado"}. {"Script check","Verificação de Script"}. {"Search Results for ","Resultados de pesquisa para "}. {"Search users in ","Procurar usuários em "}. {"Send announcement to all online users","Enviar anúncio a todos os usuárions online"}. {"Send announcement to all online users on all hosts","Enviar anúncio a todos usuários online em todas as máquinas"}. {"Send announcement to all users","Enviar anúncio a todos os usuários"}. {"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"}. {"Show Integral Table","Mostrar Tabela Integral"}. {"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."}. {"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"}. {"~s's Offline Messages Queue","~s's Fila de Mensagens Offline"}. {"Start","Iniciar"}. {"Start Modules at ","Iniciar módulos em "}. {"Start Modules","Iniciar módulos"}. {"Statistics","Estatísticas"}. {"Statistics of ~p","Estatísticas de ~p"}. {"Stop Modules at ","Parar módulos em "}. {"Stop Modules","Parar módulos"}. {"Stop","Parar"}. {"Stopped Nodes","Nos parados"}. {"Storage Type","Tipo de armazenamento"}. {"Store binary backup:","Armazenar backup binário:"}. {"Store plain text backup:","Armazenar backup em texto:"}. {"Subject","Assunto"}. {"Submit","Enviar"}. {"Submitted","Submetido"}. {"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: "}. {"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."}. {"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"}. {"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 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"}. {"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 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"}. ejabberd-16.01/priv/msgs/de.msg0000644000232200023220000006770712645157216016710 0ustar debalancedebalance%% -*- coding: latin-1 -*- {"Access Configuration","Zugangskonfiguration"}. {"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"}. {"Add Jabber ID","Jabber-ID hinzufügen"}. {"Add New","Neue(n) hinzufügen"}. {"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?"}. {"Allow users to change the subject","Erlaube Benutzern das Thema zu ändern"}. {"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 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"}. {"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"}. {"Backup Management","Datensicherungsverwaltung"}. {"Backup of ~p","Sicherung von ~p"}. {"Backup to File at ","Datensicherung in die Datei "}. {"Bad format","Ungültiges Format"}. {"Birthday","Geburtsdatum"}. {"CAPTCHA web page","CAPTCHA Webseite"}. {"Change Password","Passwort ändern"}. {"Change User Password","Benutzer-Passwort ändern"}. {"Characters not allowed:","Nicht erlaubte Zeichen:"}. {"Chatroom configuration modified","Chatraum-Konfiguration geändert"}. {"Chatroom is created","Chatraum wurde erstellt"}. {"Chatroom is destroyed","Chatraum wurde entfernt"}. {"Chatroom is started","Chatraum wurde gestartet"}. {"Chatroom is stopped","Chatraum wurde beendet"}. {"Chatrooms","Chaträume"}. {"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ä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:"}. {"Connections parameters","Verbindungsparameter"}. {"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 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"}. {"Delete User","Benutzer löschen"}. {"Deliver event notifications","Ereignisbenachrichtigung zustellen"}. {"Deliver payloads with event notifications","Nachrichten mit Ereignis-Benachrichtigungen zustellen"}. {"Description:","Beschreibung:"}. {"Disc only copy","Nur auf Festplatte"}. {"Displayed Groups:","Angezeigte Gruppen:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Geben sie niemandem ihr Passwort, auch nicht den Administratoren des Jabber Servers."}. {"Dump Backup to Text File at ","Ausgabe der Sicherung in diese Textdatei "}. {"Dump to Text File","Ausgabe in Textdatei"}. {"Edit Properties","Einstellungen ändern"}. {"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"}. {"ejabberd Web Admin","ejabberd Web-Admin"}. {"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 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 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:"}. {"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"}. {"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"}. {"Full Name","Vollständiger Name"}. {"Get Number of Online Users","Anzahl der angemeldeten Benutzer abrufen"}. {"Get Number of Registered Users","Anzahl der registrierten Benutzer abrufen"}. {"Get User Last Login Time","letzte Anmeldezeit abrufen"}. {"Get User Password","Benutzer-Passwort abrufen"}. {"Get User Statistics","Benutzer-Statistiken abrufen"}. {"Grant voice to this person?","Sprachrechte dieser Person erteilen?"}. {"Group ","Gruppe "}. {"Groups","Gruppen"}. {"has been banned","wurde gebannt"}. {"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."}. {"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.","Wenn sie verschiedene Ports, Passwörter und Kodierungen für IRC Server angeben wollen, erstellen sie die Liste mit folgendem Format '{\"IRC Server\", \"Kodierung\", Port, \"Passwort\"}'. Standardmäßig benutzt dieser Dienst die \"~s\" Kodierung, den Port ~p und kein Passwort."}. {"Import Directory","Verzeichnis importieren"}. {"Import File","Datei importieren"}. {"Import user data from jabberd14 spool file:","Importiere Benutzer von jabberd14 Spool Datei:"}. {"Import User from File at ","Benutzer aus dieser Datei importieren "}. {"Import users data from a PIEFXIS file (XEP-0227):","Benutzerdaten von einer PIEFXIS Datei (XEP-0227) importieren:"}. {"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"}. {"IP","IP"}. {"IRC channel (don't put the first #)","IRC Channel (ohne dem ersten #)"}. {"IRC server","IRC Server"}. {"IRC settings","IRC Einstellungen"}. {"IRC Transport","IRC Transport"}. {"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"}. {"January","Januar"}. {"Join IRC channel","IRC Channel beitreten"}. {"joins the room","betretet den Raum"}. {"Join the IRC channel here.","Hier den IRC Channel beitreten."}. {"Join the IRC channel in this Jabber ID: ~s","Den IRC Channel mit dieser Jabber ID beitreten: ~s"}. {"July","Juli"}. {"June","Juni"}. {"Last Activity","Letzte Aktivität"}. {"Last login","Letzte Anmeldung"}. {"Last month","Letzter Monat"}. {"Last year","Letztes Jahr"}. {"leaves the room","verlässt den Raum"}. {"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"}. {"Make room members-only","Raum nur für Mitglieder zugänglich machen"}. {"Make room moderated","Raum moderiert machen"}. {"Make room password protected","Raum mit Passwort schützen"}. {"Make room persistent","Raum persistent machen"}. {"Make room public searchable","Raum öffentlich suchbar machen"}. {"March","März"}. {"Maximum Number of Occupants","Maximale Anzahl von Teilnehmern"}. {"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"}. {"Modules at ~p","Module bei ~p"}. {"Modules","Module"}. {"Monday","Montag"}. {"Multicast","Multicast"}. {"Multi-User Chat","Mehrbenutzer-Chat (MUC)"}. {"Name:","Name:"}. {"Name","Vorname"}. {"Never","Nie"}. {"New Password:","Neues Passwort:"}. {"Nickname","Benutzername"}. {"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"}. {"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"}. {"No resource provided","Keine Ressource angegeben"}. {"Not Found","Nicht gefunden"}. {"Notify subscribers when items are removed from the node","Abonnenten benachrichtigen, wenn Einträge vom Knoten entfernt werden"}. {"Notify subscribers when the node configuration changes","Abonnenten benachrichtigen, wenn sich die Knotenkonfiguration ändert"}. {"Notify subscribers when the node is deleted","Abonnenten benachrichtigen, wenn der Knoten gelöscht wird"}. {"November","November"}. {"Number of occupants","Anzahl der Teilnehmer"}. {"Number of online users","Anzahl der angemeldeten Benutzer"}. {"Number of registered users","Anzahl der registrierten Benutzer"}. {"October","Oktober"}. {"Offline Messages:","Offline-Nachrichten:"}. {"Offline Messages","Offline-Nachrichten"}. {"OK","OK"}. {"Old Password:","Aktuelles Passwort:"}. {"Online","Angemeldet"}. {"Online Users:","Angemeldete Benutzer:"}. {"Online Users","Angemeldete Benutzer"}. {"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"}. {"Owner privileges required","Besitzerrechte benötigt"}. {"Packet","Paket"}. {"Password ~b","Passwort ~b"}. {"Password:","Passwort:"}. {"Password","Passwort"}. {"Password Verification:","Passwort bestätigen:"}. {"Password Verification","Passwort bestätigen"}. {"Path to Dir","Pfad zum Verzeichnis"}. {"Path to File","Pfad zur Datei"}. {"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."}. {"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"}. {"Present real Jabber IDs to","Echte Jabber-IDs anzeigen für"}. {"private, ","privat, "}. {"Protocol","Protokoll"}. {"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"}. {"Registered Users:","Registrierte Benutzer:"}. {"Registered Users","Registrierte Benutzer"}. {"Registration in mod_irc for ","Registrierung in mod_irc für "}. {"Remote copy","Fernkopie"}. {"Remove All Offline Messages","Alle Offline Nachrichten löschen"}. {"Remove","Entfernen"}. {"Remove User","Benutzer löschen"}. {"Replaced by new connection","Durch neue Verbindung ersetzt"}. {"Resources","Ressourcen"}. {"Restart","Neustart"}. {"Restart Service","Dienst neustarten"}. {"Restore Backup from File at ","Datenwiederherstellung aus der Datei "}. {"Restore binary backup after next ejabberd restart (requires less memory):","Stelle binäre Sicherung beim nächsten ejabberd-Neustart wieder her (benötigt weniger Speicher):"}. {"Restore binary backup immediately:","Stelle binäre Sicherung sofort wieder her:"}. {"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"}. {"Roster groups allowed to subscribe","Kontaktlisten-Gruppen die abonnieren dürfen"}. {"Roster","Kontaktliste"}. {"Roster of ","Kontaktliste von "}. {"Roster size","Kontaktlistengröße"}. {"RPC Call Error","Fehler bei RPC-Aufruf"}. {"Running Nodes","Aktive Knoten"}. {"~s access rule configuration","~s Zugangsregel-Konfiguration"}. {"Saturday","Samstag"}. {"Script check","Script-Überprüfung"}. {"Search Results for ","Suchergebnisse für "}. {"Search users in ","Benutzer suchen in "}. {"Send announcement to all online users on all hosts","Sende Ankündigung an alle angemeldeten Benutzer auf allen Hosts"}. {"Send announcement to all online users","Sende Ankündigung an alle angemeldeten Benutzer"}. {"Send announcement to all users on all hosts","Sende Ankündigung an alle Benutzer auf allen Hosts"}. {"Send announcement to all users","Sende Ankündigung an alle Benutzer"}. {"September","September"}. {"Server ~b","Server ~b"}. {"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"}. {"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"}. {"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"}. {"~s's Offline Messages Queue","~s's Offline-Nachrichten-Warteschlange"}. {"Start Modules at ","Starte Module auf "}. {"Start Modules","Module starten"}. {"Start","Starten"}. {"Statistics of ~p","Statistiken von ~p"}. {"Statistics","Statistiken"}. {"Stop Modules at ","Stoppe Module auf "}. {"Stop Modules","Module stoppen"}. {"Stopped Nodes","Angehaltene Knoten"}. {"Stop","Stoppen"}. {"Storage Type","Speichertyp"}. {"Store binary backup:","Speichere binäre Sicherung:"}. {"Store plain text backup:","Speichere Klartext-Sicherung:"}. {"Subject","Betreff"}. {"Submit","Senden"}. {"Submitted","Gesendet"}. {"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: "}. {"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."}. {"Thursday","Donnerstag"}. {"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"}. {"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:"}. {"Use of STARTTLS required","Verwendung von STARTTLS erforderlich"}. {"User","Benutzer"}. {"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"}. ejabberd-16.01/priv/msgs/ja.po0000644000232200023220000015551212645157216016532 0ustar debalancedebalancemsgid "" msgstr "" "Project-Id-Version: ejabberd 2.1.x\n" "PO-Revision-Date: 2012-04-16 15:48+0900\n" "Last-Translator: Tsukasa Hamano \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Japanese (日本語)\n" "X-Additional-Translator: Tsukasa Hamano \n" "X-Additional-Translator: Mako N \n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "STARTTLS ã®ä½¿ç”¨ãŒå¿…è¦ã§ã™" #: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "ãƒªã‚½ãƒ¼ã‚¹ãŒæä¾›ã•れã¾ã›ã‚“ã§ã—ãŸ" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "æ–°ã—ã„コãƒã‚¯ã‚·ãƒ§ãƒ³ã«ã‚ˆã£ã¦ç½®ãæ›ãˆã‚‰ã‚Œã¾ã—ãŸ" #: 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: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:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "見ãˆã¦ã„るテキストを入力ã—ã¦ãã ã•ã„" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "~s å®›ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯ãƒ–ロックã•れã¦ã„ã¾ã™ã€‚解除ã™ã‚‹ã«ã¯ã“ã¡ã‚‰ã‚’見ã¦ãã ã•ã„ ~s" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "ã“ã“ã« CAPTCHA ç”»åƒãŒè¡¨ç¤ºã•れãªã„å ´åˆã€ã‚¦ã‚§ãƒ–ページをå‚ç…§ã—ã¦ãã ã•ã„。" #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA ウェブページ" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "CAPTCHA ã¯æœ‰åйã§ã™ã€‚" #: 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 "ユーザー" #: ejabberd_oauth.erl:256 #, fuzzy msgid "Server" 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 #: mod_muc_room.erl:3383 mod_register.erl:275 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 "ejabberd ウェブ管ç†" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "管ç†" #: 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: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: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: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:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Raw" #: 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:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "アクセスルール" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s アクセスルール設定" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "ãƒãƒ¼ãƒãƒ£ãƒ«ãƒ›ã‚¹ãƒˆ" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "ユーザー" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "オンラインユーザー" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æ´»å‹•履歴" #: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "期間: " #: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "先月" #: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "去年" #: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "ã™ã¹ã¦" #: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "通常ã®è¡¨ã‚’表示" #: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "ç´¯ç©ã®è¡¨ã‚’表示" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "統計" #: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "見ã¤ã‹ã‚Šã¾ã›ã‚“" #: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "ノードãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" #: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "æ–°è¦è¿½åŠ " #: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "ホスト" #: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "登録ユーザー" #: 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:1459 msgid "Offline Messages" msgstr "オフラインメッセージ" #: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "活動履歴" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 #: mod_configure.erl:1916 msgid "Never" msgstr "ãªã—" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 #: mod_configure.erl:1926 msgid "Online" msgstr "オンライン" #: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "登録ユーザー:" #: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 #: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "オンラインユーザー:" #: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "外å‘ã s2s コãƒã‚¯ã‚·ãƒ§ãƒ³:" #: ejabberd_web_admin.erl:1559 #, fuzzy msgid "Incoming s2s Connections:" 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 msgid "None" msgstr "ãªã—" #: 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:1673 msgid "User ~s" msgstr "ユーザー ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "接続リソース:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "パスワード" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "ユーザーを削除" #: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "データãªã—" #: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "ノード" #: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "起動ノード" #: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "åœæ­¢ãƒŽãƒ¼ãƒ‰" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "ノード ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "データーベース" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Listen ãƒãƒ¼ãƒˆ" #: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "æ›´æ–°" #: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 #: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "å†èµ·å‹•" #: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 #: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "åœæ­¢" #: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "モジュール" #: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC 呼ã³å‡ºã—エラー" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "データーベーステーブル: ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "å" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "ストレージタイプ" #: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "è¦ç´ " #: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "メモリ" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "エラー" #: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—: ~p" #: 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 "" "ã“れらã®ã‚ªãƒ—ションã¯çµ„ã¿è¾¼ã¿ã® Mnesia データーベースã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã®ã¿ã‚’行ã†" "ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。も㗠ODBC モジュールを使用ã—ã¦ã„ã‚‹å ´åˆã¯ã€SQL デー" "ターベースã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—を別ã«è¡Œã†å¿…è¦ãŒã‚りã¾ã™ã€‚" #: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "ãƒã‚¤ãƒŠãƒªãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‚’ä¿å­˜:" #: 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:1979 msgid "Restore binary backup immediately:" msgstr "ç›´ã¡ã«ãƒã‚¤ãƒŠãƒªãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‹ã‚‰ãƒªã‚¹ãƒˆã‚¢:" #: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "ejabberd ã®å†èµ·å‹•時ã«ãƒã‚¤ãƒŠãƒªãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‹ã‚‰ãƒªã‚¹ãƒˆã‚¢ (メモリ少):" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "プレーンテキストãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‚’ä¿å­˜:" #: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "ç›´ã¡ã«ãƒ—レーンテキストãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‹ã‚‰ãƒªã‚¹ãƒˆã‚¢:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "ユーザーデータを PIEFXIS ファイルã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆ (XEP-0227):" #: 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:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "ホストã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ‡ãƒ¼ã‚¿ã‚’ PIEFXIS ファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ (XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "ã™ã¹ã¦ã®ãƒ†ãƒ¼ãƒ–ルをSQLå½¢å¼ã§ãƒ•ァイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ: " #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "ユーザーデータを jabberd14 Spool ファイルã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆ:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "ユーザーデータを jabberd14 Spool ディレクトリã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆ:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Listen ãƒãƒ¼ãƒˆ " #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "モジュール ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "~p ã®çµ±è¨ˆ" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "起動時間:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU時間:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "トランザクションã®ã‚³ãƒŸãƒƒãƒˆ:" #: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "トランザクションã®å¤±æ•—:" #: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "トランザクションã®å†èµ·å‹•:" #: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "トランザクションã®ãƒ­ã‚°: " #: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "æ›´æ–° ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "更新計画" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "æ›´æ–°ã•れãŸãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«" #: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "ã‚¹ã‚¯ãƒªãƒ—ãƒˆã®æ›´æ–°" #: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "低レベル更新スクリプト" #: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "スクリプトãƒã‚§ãƒƒã‚¯" #: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "ãƒãƒ¼ãƒˆ" #: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "プロトコル" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "モジュール" #: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "オプション" #: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "é–‹å§‹" #: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "コマンド" #: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" #: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "本当ã«ãŠçŸ¥ã‚‰ã›ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’削除ã—ã¾ã™ã‹ ?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "ä»¶å" #: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "本文" #: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "アナウンスメッセージã¯ã‚りã¾ã›ã‚“ã§ã—ãŸ" #: mod_announce.erl:662 msgid "Announcements" msgstr "アナウンス" #: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚¢ãƒŠã‚¦ãƒ³ã‚¹ã‚’é€ä¿¡" #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "全ホストã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚¢ãƒŠã‚¦ãƒ³ã‚¹ã‚’é€ä¿¡" #: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "ã™ã¹ã¦ã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚¢ãƒŠã‚¦ãƒ³ã‚¹ã‚’é€ä¿¡" #: 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:672 msgid "Set message of the day and send to online users" msgstr "ãŠçŸ¥ã‚‰ã›ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’設定ã—ã€ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«é€ä¿¡" #: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "全ホストã®ãŠçŸ¥ã‚‰ã›ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’設定ã—ã€ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«é€ä¿¡" #: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "ãŠçŸ¥ã‚‰ã›ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’æ›´æ–° (é€ä¿¡ã—ãªã„)" #: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "全ホストã®ãŠçŸ¥ã‚‰ã›ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’æ›´æ–° (é€ä¿¡ã—ãªã„)" #: mod_announce.erl:680 msgid "Delete message of the day" msgstr "ãŠçŸ¥ã‚‰ã›ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’削除" #: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "全ホストã®ãŠçŸ¥ã‚‰ã›ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’削除" #: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 #: mod_configure.erl:522 msgid "Configuration" msgstr "設定" #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "モジュールを起動" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’åœæ­¢" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "リストア" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "テキストファイルã«å‡ºåŠ›" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "ファイルã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆ" #: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "ディレクトリインãƒãƒ¼ãƒˆ" #: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "サービスをå†èµ·å‹•" #: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "ã‚µãƒ¼ãƒ“ã‚¹ã‚’åœæ­¢" #: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "ユーザーを削除" #: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "エンドユーザーセッション" #: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 #: mod_configure.erl:1473 msgid "Get User Password" msgstr "パスワードをå–å¾—" #: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "パスワードを変更" #: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "最終ログイン時間をå–å¾—" #: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "ユーザー統計をå–å¾—" #: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "登録ユーザー数をå–å¾—" #: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "オンラインユーザー数をå–å¾—" #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "ユーザー管ç†" #: mod_configure.erl:525 msgid "All Users" msgstr "全ユーザー" #: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "外å‘ã s2s コãƒã‚¯ã‚·ãƒ§ãƒ³" #: mod_configure.erl:615 msgid "Backup Management" msgstr "ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—管ç†" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "jabberd14 Spool ファイルã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’インãƒãƒ¼ãƒˆ" #: mod_configure.erl:762 msgid "To ~s" msgstr "宛先 ~s" #: mod_configure.erl:782 msgid "From ~s" msgstr "差出人 ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "データーベーステーブル設定 " #: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "テーブルã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã‚¿ã‚¤ãƒ—ã‚’é¸æŠž" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "ディスクã ã‘ã®ã‚³ãƒ”ー" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM, ディスクコピー" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM コピー" #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "リモートコピー" #: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’åœæ­¢: " #: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "åœæ­¢ã™ã‚‹ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’é¸æŠž" #: mod_configure.erl:1072 msgid "Start Modules at " msgstr "モジュールを開始: " #: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "{モジュール, [オプション]}ã®ãƒªã‚¹ãƒˆã‚’入力ã—ã¦ãã ã•ã„" #: mod_configure.erl:1080 msgid "List of modules to start" msgstr "起動モジュールã®ä¸€è¦§" #: mod_configure.erl:1094 msgid "Backup to File at " msgstr "ファイルã«ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—: " #: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ファイルã®ãƒ‘スを入力ã—ã¦ãã ã•ã„" #: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 #: mod_configure.erl:1163 msgid "Path to File" msgstr "ファイルã®ãƒ‘ス" #: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "ファイルã‹ã‚‰ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—をリストア: " #: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "テキストファイルã«ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—: " #: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "テキストファイルã®ãƒ‘スを入力ã—ã¦ãã ã•ã„" #: mod_configure.erl:1156 msgid "Import User from File at " msgstr "ファイルã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’インãƒãƒ¼ãƒˆ: " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "jabberd14 spool ファイルã®ãƒ‘スを入力ã—ã¦ãã ã•ã„" #: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "ディレクトリã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’インãƒãƒ¼ãƒˆ: " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "jabberd14 spool ディレクトリã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’入力ã—ã¦ãã ã•ã„" #: mod_configure.erl:1184 msgid "Path to Dir" msgstr "ディレクトリã®ãƒ‘ス" #: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "é…延時間" #: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "アクセスコントロールリスト設定" #: mod_configure.erl:1321 msgid "Access control lists" msgstr "アクセスコントロールリスト" #: mod_configure.erl:1352 msgid "Access Configuration" msgstr "アクセス設定" #: mod_configure.erl:1356 msgid "Access rules" 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:1934 #: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" #: mod_configure.erl:1407 msgid "Password Verification" msgstr "パスワード (確èª)" #: mod_configure.erl:1540 msgid "Number of registered users" msgstr "登録ユーザー数" #: mod_configure.erl:1559 msgid "Number of online users" msgstr "オンラインユーザー数" #: mod_configure.erl:1936 msgid "Last login" msgstr "最終ログイン" #: mod_configure.erl:1963 msgid "Roster size" msgstr "å簿サイズ" #: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP アドレス" #: mod_configure.erl:1967 msgid "Resources" msgstr "リソース" #: mod_configure.erl:2095 msgid "Administration of " msgstr "管ç†: " #: mod_configure.erl:2100 msgid "Action on user" msgstr "ユーザーæ“作" #: mod_configure.erl:2108 msgid "Edit Properties" msgstr "プロパティを編集" #: 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_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:220 mod_muc.erl:467 msgid "Access denied by service policy" msgstr "サービスãƒãƒªã‚·ãƒ¼ã«ã‚ˆã£ã¦ã‚¢ã‚¯ã‚»ã‚¹ãŒç¦æ­¢ã•れã¾ã—ãŸ" #: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRCトランスãƒãƒ¼ãƒˆ" #: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC module" #: 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:653 msgid "Registration in mod_irc for " msgstr "mod_irc ã§ã®ç™»éŒ²: " #: 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:667 msgid "IRC Username" msgstr "IRC ユーザーå" #: 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." msgstr "" "別ã®ãƒãƒ¼ãƒˆã‚„ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã€æ–‡å­—エンコーディングを使用ã—ãŸã„å ´åˆã€'{\"irc server" "\", \"encoding\", port, \"password\"}' ã¨ã„ã†å½¢å¼ã®ãƒªã‚¹ãƒˆã‚’入力ã—ã¦ãã ã•ã„。" "デフォルトã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã¯ \"~s\" を使用ã—ã€ãƒãƒ¼ãƒˆã¯ ~pã€ãƒ‘スワードã¯ç©ºã«" "ãªã£ã¦ã„ã¾ã™ã€‚" #: 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 "" "例: [{\"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 "接続パラメーター" #: mod_irc.erl:886 msgid "Join IRC channel" msgstr "IRC ãƒãƒ£ãƒ³ãƒãƒ«ã«å‚加" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC ãƒãƒ£ãƒ³ãƒãƒ« (先頭ã«#ã¯ä¸è¦)" #: mod_irc.erl:903 msgid "IRC server" msgstr "IRC サーãƒãƒ¼" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "ã“ã® IRC ãƒãƒ£ãƒ³ãƒãƒ«ã«å‚加ã—ã¾ã™ã€‚" #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Jabber ID: ~s ã§ã“ã® IRC ãƒãƒ£ãƒ³ãƒãƒ«ã«å‚加" #: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC 設定" #: 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 "" "IRC サーãƒãƒ¼ã«æŽ¥ç¶šå…ˆã™ã‚‹ãŸã‚ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨æ–‡å­—エンコーディングを入力ã—ã¦ãã " "ã•ã„。'Next' を押ã—ã¦æ¬¡ã®é …ç›®ã«é€²ã¿ã¾ã™ã€‚'Complete' を押ã™ã¨è¨­å®šãŒä¿å­˜ã•れã¾" "ã™ã€‚" #: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC ユーザーå" #: mod_irc.erl:1126 msgid "Password ~b" msgstr "パスワード ~b" #: mod_irc.erl:1137 msgid "Port ~b" msgstr "ãƒãƒ¼ãƒˆ ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "サーãƒãƒ¼ã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚° ~b" #: mod_irc.erl:1171 msgid "Server ~b" msgstr "サーãƒãƒ¼ ~b" #: 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 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:941 msgid "Nickname Registration at " msgstr "ニックãƒãƒ¼ãƒ ç™»éŒ²: " #: mod_muc.erl:947 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_vcard.erl:621 msgid "Nickname" msgstr "ニックãƒãƒ¼ãƒ " #: 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モジュール" #: 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:249 msgid "Total rooms" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ æ•°" #: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "永続ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ " #: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "登録ニックãƒãƒ¼ãƒ " #: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®ä¸€è¦§" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®è¨­å®šãŒå¤‰æ›´ã•れã¾ã—ãŸ" #: mod_muc_log.erl:410 msgid "joins the room" msgstr "ãŒãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã«å‚加ã—ã¾ã—ãŸ" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "ãŒãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‹ã‚‰é€€å‡ºã—ã¾ã—ãŸ" #: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "ã¯ãƒãƒ³ã•れã¾ã—ãŸ" #: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "ã¯åˆ†æŽŒãŒå¤‰æ›´ã•れãŸãŸã‚キックã•れã¾ã—ãŸ" #: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "ã¯ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ãŒãƒ¡ãƒ³ãƒãƒ¼åˆ¶ã«å¤‰æ›´ã•れãŸãŸã‚キックã•れã¾ã—ãŸ" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "ã¯ã‚·ã‚¹ãƒ†ãƒ ã‚·ãƒ£ãƒƒãƒˆãƒ€ã‚¦ãƒ³ã®ãŸã‚キックã•れã¾ã—ãŸ" #: mod_muc_log.erl:450 msgid "is now known as" msgstr "ã¯åå‰ã‚’変更ã—ã¾ã—ãŸ: " #: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " ã¯ä»¶åを設定ã—ã¾ã—ãŸ: " #: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’作りã¾ã—ãŸ" #: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’終了ã—ã¾ã—ãŸ" #: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’é–‹å§‹ã—ã¾ã—ãŸ" #: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’åœæ­¢ã—ã¾ã—ãŸ" #: mod_muc_log.erl:503 msgid "Monday" msgstr "月曜日" #: mod_muc_log.erl:504 msgid "Tuesday" msgstr "ç«æ›œæ—¥" #: mod_muc_log.erl:505 msgid "Wednesday" msgstr "水曜日" #: mod_muc_log.erl:506 msgid "Thursday" msgstr "木曜日" #: mod_muc_log.erl:507 msgid "Friday" msgstr "金曜日" #: mod_muc_log.erl:508 msgid "Saturday" msgstr "土曜日" #: mod_muc_log.erl:509 msgid "Sunday" msgstr "日曜日" #: mod_muc_log.erl:513 msgid "January" msgstr "1月" #: mod_muc_log.erl:514 msgid "February" msgstr "2月" #: mod_muc_log.erl:515 msgid "March" msgstr "3月" #: mod_muc_log.erl:516 msgid "April" msgstr "4月" #: mod_muc_log.erl:517 msgid "May" msgstr "5月" #: mod_muc_log.erl:518 msgid "June" msgstr "6月" #: mod_muc_log.erl:519 msgid "July" msgstr "7月" #: mod_muc_log.erl:520 msgid "August" msgstr "8月" #: mod_muc_log.erl:521 msgid "September" msgstr "9月" #: mod_muc_log.erl:522 msgid "October" msgstr "10月" #: mod_muc_log.erl:523 msgid "November" msgstr "11月" #: mod_muc_log.erl:524 msgid "December" msgstr "12月" #: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®è¨­å®š" #: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "在室者" #: 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:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "モデレーターã®ã¿ãŒãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®ä»¶åを変更ã§ãã¾ã™" #: 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:2772 msgid "Nickname ~s does not exist in the room" msgstr "ニックãƒãƒ¼ãƒ  ~s ã¯ã“ã®ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã«ã„ã¾ã›ã‚“" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "無効ãªåˆ†æŽŒã§ã™: ~s" #: 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:3348 msgid "Configuration of room ~s" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ  ~s ã®è¨­å®š" #: mod_muc_room.erl:3359 msgid "Room title" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®ã‚¿ã‚¤ãƒˆãƒ«" #: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã®èª¬æ˜Ž" #: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’永続化" #: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’検索å¯" #: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "å‚加者一覧を公開" #: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’パスワードã§ä¿è­·" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "最大在室者数" #: mod_muc_room.erl:3406 msgid "No limit" msgstr "制é™ãªã—" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "本当㮠Jabber ID を公開" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "モデレーターã«ã®ã¿" #: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "誰ã«ã§ã‚‚" #: 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:3516 msgid "Make room moderated" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’モデレート化" #: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "デフォルトã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯å‚加者" #: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "ユーザーã«ã‚ˆã‚‹ä»¶åã®å¤‰æ›´ã‚’許å¯" #: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "ユーザーã«ã‚ˆã‚‹ãƒ—ライベートメッセージã®é€ä¿¡ã‚’許å¯" #: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "å‚è´è€…ã«ã‚ˆã‚‹ãƒ—ライベートメッセージã®é€ä¿¡ã‚’次ã®ç›¸æ‰‹ã«è¨±å¯" #: mod_muc_room.erl:3551 msgid "nobody" msgstr "誰ã«ã‚‚許å¯ã—ãªã„" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "ユーザーã«ã‚ˆã‚‹ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¸ã®ã‚¯ã‚¨ãƒªãƒ¼ã‚’許å¯" #: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "ユーザーã«ã‚ˆã‚‹æ‹›å¾…を許å¯" #: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "å‚è´è€…ã«ã‚ˆã‚‹ãƒ—レゼンス更新ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹æ–‡ã®é€ä¿¡ã‚’許å¯" #: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "å‚è´è€…ã®ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã®å¤‰æ›´ã‚’許å¯" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "å‚è´è€…ã«ã‚ˆã‚‹ç™ºè¨€æ¨©ã®è¦æ±‚を許å¯" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "発言権ã®è¦æ±‚ã®æœ€å°æ™‚é–“é–“éš” (ç§’)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’ CAPTCHA ã§ä¿è­·" #: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "メッセージアーカイブを有効化" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "CAPTCHA 試験をå…除ã™ã‚‹ Jabber ID" #: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "ロギングを有効" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ ã‚’設定ã™ã‚‹ã«ã¯ x:data をサãƒãƒ¼ãƒˆã™ã‚‹ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒå¿…è¦ã§ã™" #: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "åœ¨å®¤è€…ã®æ•°" #: mod_muc_room.erl:4260 msgid "private, " msgstr "プライベートã€" #: mod_muc_room.erl:4324 msgid "Voice request" msgstr "ç™ºè¨€æ¨©ã‚’è¦æ±‚" #: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "発言権ã®è¦æ±‚を承èªã¾ãŸã¯å´ä¸‹ã—ã¾ã™ã€‚" #: mod_muc_room.erl:4349 msgid "User JID" msgstr "ユーザー JID" #: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "ã“ã®äººã«ç™ºè¨€æ¨©ã‚’与ãˆã¾ã™ã‹ ?" #: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s ã¯ã‚ãªãŸã‚’ãƒãƒ£ãƒƒãƒˆãƒ«ãƒ¼ãƒ  ~s ã«æ‹›å¾…ã—ã¦ã„ã¾ã™" #: mod_muc_room.erl:4507 msgid "the password is" msgstr "パスワードã¯" #: mod_multicast.erl:291 msgid "Multicast" msgstr "マルãƒã‚­ãƒ£ã‚¹ãƒˆ" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberdマルãƒã‚­ãƒ£ã‚¹ãƒˆã‚µãƒ¼ãƒ“ス" #: 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:811 msgid "Time" msgstr "時間" #: mod_offline.erl:812 msgid "From" msgstr "差出人" #: mod_offline.erl:813 msgid "To" msgstr "宛先" #: mod_offline.erl:814 msgid "Packet" msgstr "パケット" #: mod_offline.erl:992 msgid "Offline Messages:" msgstr "オフラインメッセージ:" #: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "ã™ã¹ã¦ã®ã‚ªãƒ•ラインメッセージを削除" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams モジュール" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" #: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe モジュール" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub 購読者ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆ" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "ã“ã®ã‚¨ãƒ³ãƒˆãƒªã‚’承èªã™ã‚‹ã‹ã©ã†ã‹ã‚’é¸æŠžã—ã¦ãã ã•ã„" #: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ノードID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "購読者ã®ã‚¢ãƒ‰ãƒ¬ã‚¹" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "ã“ã® Jabber ID ã«ã€ã“ã® pubsubノードã®è³¼èª­ã‚’許å¯ã—ã¾ã™ã‹ ?" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "イベント通知ã¨åŒæ™‚ã«ãƒšã‚¤ãƒ­ãƒ¼ãƒ‰ã‚’é…é€ã™ã‚‹" #: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "イベント通知をé…é€ã™ã‚‹" #: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "ノード設定ã«å¤‰æ›´ãŒã‚ã£ãŸæ™‚ã«è³¼èª­è€…ã¸é€šçŸ¥ã™ã‚‹" #: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "ノードãŒå‰Šé™¤ã•ã‚ŒãŸæ™‚ã«è³¼èª­è€…ã¸é€šçŸ¥ã™ã‚‹" #: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "アイテムãŒãƒŽãƒ¼ãƒ‰ã‹ã‚‰æ¶ˆã•ã‚ŒãŸæ™‚ã«è³¼èª­è€…ã¸é€šçŸ¥ã™ã‚‹" #: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "アイテムをストレージã«ä¿å­˜ã™ã‚‹" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "ノードã®ãƒ•レンドリãƒãƒ¼ãƒ " #: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "ã‚¢ã‚¤ãƒ†ãƒ ã®æœ€å¤§ä¿å­˜æ•°" #: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "購読を許å¯ã™ã‚‹ã‹ã©ã†ã‹" #: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "アクセスモデルを設定ã™ã‚‹" #: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "å簿グループã¯è³¼èª­ã‚’許å¯ã—ã¾ã—ãŸ" #: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "公開モデルを指定ã™ã‚‹" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "公開者ãŒã‚ªãƒ•ラインã«ãªã‚‹ã¨ãã«ã€ã™ã¹ã¦ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’削除" #: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "イベントメッセージ種別を設定" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "最大ãºã‚¤ãƒ­ãƒ¼ãƒ‰ã‚µã‚¤ã‚º (byte)" #: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "最後ã®å…¬é–‹ã‚¢ã‚¤ãƒ†ãƒ ã‚’é€ä¿¡ã™ã‚‹ã‚¿ã‚¤ãƒŸãƒ³ã‚°ã§" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "有効ãªãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã®ã¿å‘ŠçŸ¥ã‚’é€ä¿¡ã™ã‚‹" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "ææºã•れãŸãƒŽãƒ¼ãƒ‰ã®é›†åˆã§ã™" #: 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: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 アカウントã®ä½œæˆã«æˆåŠŸã—ã¾ã—ãŸã€‚" #: mod_register_web.erl:110 msgid "There was an error creating the account: " msgstr "アカウントã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." msgstr "Jabber アカウントã®å‰Šé™¤ã«æˆåŠŸã—ã¾ã—ãŸã€‚" #: mod_register_web.erl:124 msgid "There was an error deleting the account: " msgstr "アカウントã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." msgstr "Jabber アカウントã®ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰å¤‰æ›´ã«æˆåŠŸã—ã¾ã—ãŸã€‚" #: mod_register_web.erl:140 msgid "There was an error changing the password: " msgstr "パスワードã®å¤‰æ›´ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" msgstr "Jabber アカウント登録" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" msgstr "Jabber アカウントを登録" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Jabber アカウントを削除" #: mod_register_web.erl:214 msgid "" "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." msgstr "" "ã“ã“ã¯ã“ã® Jabber サーãƒãƒ¼ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’作æˆã™ã‚‹ãƒšãƒ¼ã‚¸ã§ã™ã€‚ã‚ãªãŸã® JID " "(JabberID) 㯠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 ã¨åŒã˜ã§ã™ã€‚" #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "使用ã§ããªã„文字:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "サーãƒãƒ¼:" #: 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:249 msgid "You can later change your password using a Jabber client." msgstr "ã‚ãªãŸã¯å¾Œã§ 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 "" "Jabber クライアントã¯ã‚³ãƒ³ãƒ”ューターã«ãƒ‘スワードを記憶ã§ãã¾ã™ã€‚コンピューター" "ãŒå®‰å…¨ã§ã‚ã‚‹ã¨ä¿¡é ¼ã§ãã‚‹å ´åˆã«ã®ã¿ã€ã“ã®æ©Ÿèƒ½ã‚’使用ã—ã¦ãã ã•ã„。" #: 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 "" "パスワードã¯è¨˜æ†¶ã™ã‚‹ã‹ã€ç´™ã«æ›¸ã„ã¦å®‰å…¨ãªå ´æ‰€ã«ä¿ç®¡ã—ã¦ãã ã•ã„。もã—ã‚ãªãŸãŒ" "パスワードを忘れã¦ã—ã¾ã£ãŸå ´åˆã€Jabber ã§ã¯ãƒ‘スワードã®ãƒªã‚«ãƒãƒªã‚’自動的ã«è¡Œã†" "ã“ã¨ã¯ã§ãã¾ã›ã‚“。" #: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "パスワード (確èª):" #: mod_register_web.erl:269 msgid "Register" msgstr "登録" #: mod_register_web.erl:366 msgid "Old Password:" msgstr "å¤ã„パスワード:" #: mod_register_web.erl:370 msgid "New Password:" msgstr "æ–°ã—ã„パスワード:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "ã“ã“ã¯ã“ã® Jabber サーãƒãƒ¼ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã™ã‚‹ãƒšãƒ¼ã‚¸ã§ã™ã€‚" #: mod_register_web.erl:480 msgid "Unregister" msgstr "削除" #: mod_roster.erl:1436 msgid "Subscription" msgstr "èªå¯" #: mod_roster.erl:1437 msgid "Pending" msgstr "ä¿ç•™" #: mod_roster.erl:1438 msgid "Groups" msgstr "グループ" #: mod_roster.erl:1476 msgid "Validate" msgstr "検証" #: mod_roster.erl:1485 msgid "Remove" msgstr "削除" #: mod_roster.erl:1490 msgid "Roster of " msgstr "åç°¿: " #: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Jabber ID を追加" #: mod_roster.erl:1622 msgid "Roster" msgstr "åç°¿" #: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 #: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "共有å簿グループ" #: mod_shared_roster.erl:1232 msgid "Name:" msgstr "åå‰:" #: mod_shared_roster.erl:1236 msgid "Description:" msgstr "説明:" #: mod_shared_roster.erl:1243 msgid "Members:" msgstr "メンãƒãƒ¼:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "表示グループ" #: mod_shared_roster.erl:1259 msgid "Group " msgstr "グループ" #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "誕生日" #: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "都é“府県" #: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "国" #: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "メールアドレス" #: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "å§“" #: 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:490 mod_vcard.erl:615 msgid "Full Name" msgstr "æ°å" #: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "ミドルãƒãƒ¼ãƒ " #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "会社å" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "部署å" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æ¤œç´¢: " #: 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:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard検索" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard モジュール" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "æ¤œç´¢çµæžœ: " #: mod_vcard_ldap.erl:502 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 "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "エラーメッセージをé€ä¿¡ã—ãŸãŸã‚ã€ã“ã®å‚加者ã¯ã‚­ãƒƒã‚¯ã•れã¾ã—ãŸ" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "ä»–ã®å‚加者ã«ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ä¿¡ã—ãŸãŸã‚ã€ã“ã®å‚加者ã¯ã‚­ãƒƒã‚¯ã•れã¾ã—ãŸ" #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "エラープレゼンスをé€ä¿¡ã—ãŸãŸã‚ã€ã“ã®å‚加者ã¯ã‚­ãƒƒã‚¯ã•れã¾ã—ãŸ" #~ msgid "ejabberd virtual hosts" #~ msgstr "ejabberd ãƒãƒ¼ãƒãƒ£ãƒ«ãƒ›ã‚¹ãƒˆ" #~ msgid "Captcha test failed" #~ msgstr "キャプãƒãƒ£ã®ãƒ†ã‚¹ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ" #~ msgid "Encodings" #~ msgstr "エンコーディング" #~ msgid "(Raw)" #~ msgstr "(Raw)" #~ msgid "Specified nickname is already registered" #~ msgstr "指定ã•れãŸãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã¯æ—¢ã«ç™»éŒ²ã•れã¦ã„ã¾ã™" #~ msgid "Size" #~ msgstr "サイズ" ejabberd-16.01/README.md0000777000232200023220000000000012645157216015772 2READMEustar debalancedebalanceejabberd-16.01/rebar.config.script0000644000232200023220000001075112645157216017427 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov %%% @copyright (C) 2013, Evgeniy Khramtsov %%% @doc %%% %%% @end %%% Created : 1 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- Cfg = case file:consult(filename:join(filename:dirname(SCRIPT), "vars.config")) of {ok, Terms} -> Terms; _Err -> [] end, 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, ""), LDFLags = proplists:get_value(ldflags, Cfg, ""), ConfigureCmd = fun(Pkg, Flags) -> {'get-deps', "sh -c 'cd deps/" ++ Pkg ++ " && CFLAGS=\""++ CFLags ++"\" CPPFLAGS=\""++ CPPFLags ++"\" LDFLAGS=\""++ LDFLags ++"\"" ++ " ./configure " ++ Flags ++ "'"} end, Conf = ProcessVars(ProcessVars, CONFIG, []), 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, _} -> "-userconfig ct_config_plain " ++ TestConfigFile ++ " "; _ -> "" end, 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 %% End: %% vim: set filetype=erlang tabstop=8: ejabberd-16.01/ejabberd.init.template0000644000232200023220000000251412645157216020075 0ustar debalancedebalance#! /bin/sh ### BEGIN INIT INFO # Provides: ejabberd # Required-Start: $remote_fs $network $named $time # Required-Stop: $remote_fs $network $named $time # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Starts ejabberd jabber server # Description: Starts ejabberd jabber server, an XMPP # compliant server written in Erlang. ### END INIT INFO # chkconfig: 2345 90 10 # description: ejabberd XMPP server set -o errexit DIR=@ctlscriptpath@ CTL="$DIR"/ejabberdctl USER=@installuser@ test -x "$CTL" || { echo "ERROR: ejabberd not found: $DIR" exit 1 } getent passwd "$USER" >/dev/null || { echo "ERROR: System user not found: $USER" exit 2 } export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" case "$1" in start) test -x "$CTL" || exit 0 echo "Starting ejabberd..." su - $USER -c "$CTL start" su - $USER -c "$CTL started" echo "done." ;; stop) test -x "$CTL" || exit 0 echo "Stopping ejabberd..." su - $USER -c "$CTL stop" su - $USER -c "$CTL stopped" echo "done." ;; status) test -x "$CTL" || exit 0 echo "Getting ejabberd status..." su - $USER -c "$CTL status" ;; force-reload|restart) "$0" stop "$0" start ;; *) echo "Usage: $0 {start|stop|restart|force-reload|status}" exit 1 esac exit 0 ejabberd-16.01/.travis.yml0000644000232200023220000000325012645157216015747 0ustar debalancedebalancelanguage: erlang otp_release: - 17.1 - 17.5 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 before_script: - 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;" script: - ./autogen.sh - ./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 after_script: - find logs -name suite.log -exec cat '{}' ';' after_failure: - find logs -name ejabberd.log -exec cat '{}' ';' notifications: email: false ejabberd-16.01/asn1/0000755000232200023220000000000012645157216014500 5ustar debalancedebalanceejabberd-16.01/asn1/XmppAddr.asn10000644000232200023220000000057712645157216017014 0ustar debalancedebalanceXmppAddr { iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-on(8) id-on-xmppAddr(5) } DEFINITIONS EXPLICIT TAGS ::= BEGIN id-on-xmppAddr OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-on(8) 5 } XmppAddr ::= UTF8String END ejabberd-16.01/asn1/ELDAPv3.asn1~0000644000232200023220000002471412645157216016570 0ustar debalancedebalance-- LDAPv3 ASN.1 specification, taken from RFC 2251 -- Lightweight-Directory-Access-Protocol-V3 DEFINITIONS ELDAPv3 DEFINITIONS IMPLICIT TAGS ::= BEGIN LDAPMessage ::= SEQUENCE { messageID MessageID, protocolOp CHOICE { bindRequest BindRequest, bindResponse BindResponse, unbindRequest UnbindRequest, searchRequest SearchRequest, searchResEntry SearchResultEntry, searchResDone SearchResultDone, searchResRef SearchResultReference, modifyRequest ModifyRequest, modifyResponse ModifyResponse, addRequest AddRequest, addResponse AddResponse, delRequest DelRequest, delResponse DelResponse, modDNRequest ModifyDNRequest, modDNResponse ModifyDNResponse, compareRequest CompareRequest, compareResponse CompareResponse, abandonRequest AbandonRequest, extendedReq ExtendedRequest, extendedResp ExtendedResponse }, controls [0] Controls OPTIONAL } MessageID ::= INTEGER (0 .. maxInt) maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) -- LDAPString ::= OCTET STRING LDAPOID ::= OCTET STRING LDAPDN ::= LDAPString RelativeLDAPDN ::= LDAPString AttributeType ::= LDAPString AttributeDescription ::= LDAPString -- Wahl, et. al. Standards Track [Page 44] -- -- RFC 2251 LDAPv3 December 1997 AttributeDescriptionList ::= SEQUENCE OF AttributeDescription AttributeValue ::= OCTET STRING AttributeValueAssertion ::= SEQUENCE { attributeDesc AttributeDescription, assertionValue AssertionValue } AssertionValue ::= OCTET STRING Attribute ::= SEQUENCE { type AttributeDescription, vals SET OF AttributeValue } MatchingRuleId ::= LDAPString LDAPResult ::= SEQUENCE { resultCode ENUMERATED { success (0), operationsError (1), protocolError (2), timeLimitExceeded (3), sizeLimitExceeded (4), compareFalse (5), compareTrue (6), authMethodNotSupported (7), strongAuthRequired (8), -- 9 reserved -- referral (10), -- new adminLimitExceeded (11), -- new unavailableCriticalExtension (12), -- new confidentialityRequired (13), -- new saslBindInProgress (14), -- new noSuchAttribute (16), undefinedAttributeType (17), inappropriateMatching (18), constraintViolation (19), attributeOrValueExists (20), invalidAttributeSyntax (21), -- 22-31 unused -- noSuchObject (32), aliasProblem (33), invalidDNSyntax (34), -- 35 reserved for undefined isLeaf -- aliasDereferencingProblem (36), -- 37-47 unused -- inappropriateAuthentication (48), -- Wahl, et. al. Standards Track [Page 45] -- -- RFC 2251 LDAPv3 December 1997 invalidCredentials (49), insufficientAccessRights (50), busy (51), unavailable (52), unwillingToPerform (53), loopDetect (54), -- 55-63 unused -- namingViolation (64), objectClassViolation (65), notAllowedOnNonLeaf (66), notAllowedOnRDN (67), entryAlreadyExists (68), objectClassModsProhibited (69), -- 70 reserved for CLDAP -- affectsMultipleDSAs (71), -- new -- 72-79 unused -- other (80) }, -- 81-90 reserved for APIs -- matchedDN LDAPDN, errorMessage LDAPString, referral [3] Referral OPTIONAL } Referral ::= SEQUENCE OF LDAPURL LDAPURL ::= LDAPString -- limited to characters permitted in URLs Controls ::= SEQUENCE OF Control Control ::= SEQUENCE { controlType LDAPOID, criticality BOOLEAN DEFAULT FALSE, controlValue OCTET STRING OPTIONAL } BindRequest ::= [APPLICATION 0] SEQUENCE { version INTEGER (1 .. 127), name LDAPDN, authentication AuthenticationChoice } AuthenticationChoice ::= CHOICE { simple [0] OCTET STRING, -- 1 and 2 reserved sasl [3] SaslCredentials } SaslCredentials ::= SEQUENCE { mechanism LDAPString, credentials OCTET STRING OPTIONAL } BindResponse ::= [APPLICATION 1] SEQUENCE { -- Wahl, et. al. Standards Track [Page 46] -- -- RFC 2251 LDAPv3 December 1997 COMPONENTS OF LDAPResult, serverSaslCreds [7] OCTET STRING OPTIONAL } UnbindRequest ::= [APPLICATION 2] NULL SearchRequest ::= [APPLICATION 3] SEQUENCE { baseObject LDAPDN, scope ENUMERATED { baseObject (0), singleLevel (1), wholeSubtree (2) }, derefAliases ENUMERATED { neverDerefAliases (0), derefInSearching (1), derefFindingBaseObj (2), derefAlways (3) }, sizeLimit INTEGER (0 .. maxInt), timeLimit INTEGER (0 .. maxInt), typesOnly BOOLEAN, filter Filter, attributes AttributeDescriptionList } Filter ::= CHOICE { and [0] SET OF Filter, or [1] SET OF Filter, not [2] Filter, equalityMatch [3] AttributeValueAssertion, substrings [4] SubstringFilter, greaterOrEqual [5] AttributeValueAssertion, lessOrEqual [6] AttributeValueAssertion, present [7] AttributeDescription, approxMatch [8] AttributeValueAssertion, extensibleMatch [9] MatchingRuleAssertion } SubstringFilter ::= SEQUENCE { type AttributeDescription, -- at least one must be present substrings SEQUENCE OF CHOICE { initial [0] LDAPString, any [1] LDAPString, final [2] LDAPString } } MatchingRuleAssertion ::= SEQUENCE { matchingRule [1] MatchingRuleId OPTIONAL, type [2] AttributeDescription OPTIONAL, matchValue [3] AssertionValue, dnAttributes [4] BOOLEAN DEFAULT FALSE } -- Wahl, et. al. Standards Track [Page 47] -- -- RFC 2251 LDAPv3 December 1997 SearchResultEntry ::= [APPLICATION 4] SEQUENCE { objectName LDAPDN, attributes PartialAttributeList } PartialAttributeList ::= SEQUENCE OF SEQUENCE { type AttributeDescription, vals SET OF AttributeValue } SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL SearchResultDone ::= [APPLICATION 5] LDAPResult ModifyRequest ::= [APPLICATION 6] SEQUENCE { object LDAPDN, modification SEQUENCE OF SEQUENCE { operation ENUMERATED { add (0), delete (1), replace (2) }, modification AttributeTypeAndValues } } AttributeTypeAndValues ::= SEQUENCE { type AttributeDescription, vals SET OF AttributeValue } ModifyResponse ::= [APPLICATION 7] LDAPResult AddRequest ::= [APPLICATION 8] SEQUENCE { entry LDAPDN, attributes AttributeList } AttributeList ::= SEQUENCE OF SEQUENCE { type AttributeDescription, vals SET OF AttributeValue } AddResponse ::= [APPLICATION 9] LDAPResult DelRequest ::= [APPLICATION 10] LDAPDN DelResponse ::= [APPLICATION 11] LDAPResult ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { entry LDAPDN, newrdn RelativeLDAPDN, deleteoldrdn BOOLEAN, newSuperior [0] LDAPDN OPTIONAL } ModifyDNResponse ::= [APPLICATION 13] LDAPResult -- Wahl, et. al. Standards Track [Page 48] -- -- RFC 2251 LDAPv3 December 1997 CompareRequest ::= [APPLICATION 14] SEQUENCE { entry LDAPDN, ava AttributeValueAssertion } CompareResponse ::= [APPLICATION 15] LDAPResult AbandonRequest ::= [APPLICATION 16] MessageID ExtendedRequest ::= [APPLICATION 23] SEQUENCE { requestName [0] LDAPOID, requestValue [1] OCTET STRING OPTIONAL } ExtendedResponse ::= [APPLICATION 24] SEQUENCE { COMPONENTS OF LDAPResult, responseName [10] LDAPOID OPTIONAL, response [11] OCTET STRING OPTIONAL } passwdModifyOID LDAPOID ::= "1.3.6.1.4.1.4203.1.11.1" PasswdModifyRequestValue ::= SEQUENCE { userIdentity [0] OCTET STRING OPTIONAL, oldPasswd [1] OCTET STRING OPTIONAL, newPasswd [2] OCTET STRING OPTIONAL } PasswdModifyResponseValue ::= SEQUENCE { genPasswd [0] OCTET STRING OPTIONAL } END ejabberd-16.01/Makefile.in0000644000232200023220000002412712645157216015711 0ustar debalancedebalanceREBAR = @ESCRIPT@ rebar INSTALL = @INSTALL@ SED = @SED@ ERL = @ERL@ prefix = @prefix@ exec_prefix = @exec_prefix@ DESTDIR = # /etc/ejabberd/ ETCDIR = $(DESTDIR)@sysconfdir@/ejabberd # /bin/ BINDIR = $(DESTDIR)@bindir@ # /sbin/ SBINDIR = $(DESTDIR)@sbindir@ # /lib/ LIBDIR = $(DESTDIR)@libdir@ # /lib/ejabberd/ EJABBERDDIR = $(DESTDIR)@libdir@/ejabberd # /share/doc/ejabberd PACKAGE_TARNAME = @PACKAGE_TARNAME@ datarootdir = @datarootdir@ DOCDIR = $(DESTDIR)@docdir@ # /usr/lib/ejabberd/ebin/ BEAMDIR = $(EJABBERDDIR)/ebin # /usr/lib/ejabberd/include/ INCLUDEDIR = $(EJABBERDDIR)/include # /usr/lib/ejabberd/priv/ PRIVDIR = $(EJABBERDDIR)/priv # /usr/lib/ejabberd/priv/bin PBINDIR = $(PRIVDIR)/bin # /usr/lib/ejabberd/priv/lib SODIR = $(PRIVDIR)/lib # /usr/lib/ejabberd/priv/msgs MSGSDIR = $(PRIVDIR)/msgs # /usr/lib/ejabberd/priv/sql SQLDIR = $(PRIVDIR)/sql # /var/lib/ejabberd/ SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd # /var/lock/ejabberdctl CTLLOCKDIR = $(DESTDIR)@localstatedir@/lock/ejabberdctl # /var/lib/ejabberd/.erlang.cookie COOKIEFILE = $(SPOOLDIR)/.erlang.cookie # /var/log/ejabberd/ LOGDIR = $(DESTDIR)@localstatedir@/log/ejabberd INSTALLUSER=@INSTALLUSER@ # if no user was enabled, don't set privileges or ownership ifeq ($(INSTALLUSER),) O_USER= G_USER= CHOWN_COMMAND=echo CHOWN_OUTPUT=/dev/null INIT_USER=root else O_USER=-o $(INSTALLUSER) G_USER=-g $(INSTALLUSER) CHOWN_COMMAND=chown CHOWN_OUTPUT=&1 INIT_USER=$(INSTALLUSER) endif all: deps src deps: deps/.got deps/.got: rm -rf deps/.got rm -rf deps/.built $(REBAR) get-deps && :> deps/.got deps/.built: deps/.got $(REBAR) compile && :> deps/.built src: deps/.built $(REBAR) skip_deps=true compile update: rm -rf deps/.got rm -rf deps/.built $(REBAR) update-deps && :> deps/.got xref: all $(REBAR) skip_deps=true xref translations: contrib/extract_translations/prepare-translation.sh -updateall edoc: $(ERL) -noinput +B -eval \ 'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.' 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.' 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) $(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)))) 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)))) ifeq ($(MAKECMDGOALS),copy-files-sub) 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)) 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)) priv/bin priv/sql) define DEP_VERSION_template 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))) $(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)) endef $(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template,$(file)))) $(sort $(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS))): $(INSTALL) -d $@ $(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: copy-files-sub2 install: all copy-files # # Configuration files $(INSTALL) -d -m 750 $(G_USER) $(ETCDIR) [ -f $(ETCDIR)/ejabberd.yml ] \ && $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(ETCDIR)/ejabberd.yml-new \ || $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(ETCDIR)/ejabberd.yml $(SED) -e "s*{{rootdir}}*@prefix@*" \ -e "s*{{installuser}}*@INSTALLUSER@*" \ -e "s*{{bindir}}*@bindir@*" \ -e "s*{{libdir}}*@libdir@*" \ -e "s*{{sysconfdir}}*@sysconfdir@*" \ -e "s*{{localstatedir}}*@localstatedir@*" \ -e "s*{{docdir}}*@docdir@*" \ -e "s*{{erl}}*@ERL@*" ejabberdctl.template \ > ejabberdctl.example [ -f $(ETCDIR)/ejabberdctl.cfg ] \ && $(INSTALL) -b -m 640 $(G_USER) ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg-new \ || $(INSTALL) -b -m 640 $(G_USER) ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg $(INSTALL) -b -m 644 $(G_USER) inetrc $(ETCDIR)/inetrc # # Administration script [ -d $(SBINDIR) ] || $(INSTALL) -d -m 755 $(SBINDIR) $(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 || 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)*" \ -e "s*@installuser@*$(INIT_USER)*" ejabberd.init.template \ > ejabberd.init chmod 755 ejabberd.init # # Spool directory $(INSTALL) -d -m 750 $(O_USER) $(SPOOLDIR) $(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT) chmod -R 750 $(SPOOLDIR) [ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; } # # ejabberdctl lock directory $(INSTALL) -d -m 750 $(O_USER) $(CTLLOCKDIR) $(CHOWN_COMMAND) -R @INSTALLUSER@ $(CTLLOCKDIR) >$(CHOWN_OUTPUT) chmod -R 750 $(CTLLOCKDIR) # # Log directory $(INSTALL) -d -m 750 $(O_USER) $(LOGDIR) $(CHOWN_COMMAND) -R @INSTALLUSER@ $(LOGDIR) >$(CHOWN_OUTPUT) chmod -R 750 $(LOGDIR) # # Documentation $(INSTALL) -d $(DOCDIR) [ -f doc/guide.html ] \ && $(INSTALL) -m 644 doc/guide.html $(DOCDIR) \ || echo "Documentation not included in sources" $(INSTALL) -m 644 COPYING $(DOCDIR) uninstall: uninstall-binary uninstall-binary: rm -f $(SBINDIR)/ejabberdctl rm -f $(BINDIR)/iex rm -f $(BINDIR)/elixir rm -f $(BINDIR)/mix rm -fr $(DOCDIR) rm -f $(BEAMDIR)/*.beam rm -f $(BEAMDIR)/*.app rm -fr $(BEAMDIR) rm -f $(INCLUDEDIR)/*.hrl rm -fr $(INCLUDEDIR) rm -fr $(PBINDIR) rm -f $(SODIR)/*.so rm -fr $(SODIR) rm -f $(MSGSDIR)/*.msgs rm -fr $(MSGSDIR) rm -f $(SQLDIR)/*.sql rm -fr $(SQLDIR) rm -fr $(PRIVDIR) rm -fr $(EJABBERDDIR) uninstall-all: uninstall-binary rm -rf $(ETCDIR) rm -rf $(EJABBERDDIR) rm -rf $(SPOOLDIR) rm -rf $(CTLLOCKDIR) rm -rf $(LOGDIR) clean: rm -rf deps/.got rm -rf deps/.built rm -rf test/*.beam $(REBAR) clean clean-rel: rm -rf rel/ejabberd distclean: clean clean-rel rm -f config.status rm -f config.log rm -rf autom4te.cache rm -rf deps rm -rf ebin rm -f Makefile rm -f vars.config rm -f src/ejabberd.app.src [ ! -f ../ChangeLog ] || rm -f ../ChangeLog rel: all $(REBAR) generate TAGS: etags *.erl Makefile: Makefile.in deps := $(wildcard deps/*/ebin) dialyzer/erlang.plt: @mkdir -p dialyzer @dialyzer --build_plt --output_plt dialyzer/erlang.plt \ -o dialyzer/erlang.log --apps kernel stdlib sasl crypto \ public_key ssl mnesia inets odbc tools compiler erts webtool \ runtime_tools asn1 observer xmerl et gs wx syntax_tools; \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi dialyzer/deps.plt: @mkdir -p dialyzer @dialyzer --build_plt --output_plt dialyzer/deps.plt \ -o dialyzer/deps.log $(deps); \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi dialyzer/ejabberd.plt: @mkdir -p dialyzer @dialyzer --build_plt --output_plt dialyzer/ejabberd.plt \ -o dialyzer/ejabberd.log ebin; \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi erlang_plt: dialyzer/erlang.plt @dialyzer --plt dialyzer/erlang.plt --check_plt -o dialyzer/erlang.log; \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi deps_plt: dialyzer/deps.plt @dialyzer --plt dialyzer/deps.plt --check_plt -o dialyzer/deps.log; \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi ejabberd_plt: dialyzer/ejabberd.plt @dialyzer --plt dialyzer/ejabberd.plt --check_plt -o dialyzer/ejabberd.log; \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi dialyzer: erlang_plt deps_plt ejabberd_plt @dialyzer --plts dialyzer/*.plt --no_check_plt \ --get_warnings -o dialyzer/error.log ebin; \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi test: @echo "************************** NOTICE ***************************************" @cat test/README @echo "*************************************************************************" @cd priv && ln -sf ../sql $(REBAR) skip_deps=true ct quicktest: $(REBAR) skip_deps=true ct suites=elixir .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 ejabberd-16.01/include/0000755000232200023220000000000012645157216015261 5ustar debalancedebalanceejabberd-16.01/include/ejabberd_web_admin.hrl0000644000232200023220000000577112645157216021545 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -define(X(Name), #xmlel{name = Name, attrs = [], children = []}). -define(XA(Name, Attrs), #xmlel{name = Name, attrs = Attrs, children = []}). -define(XE(Name, Els), #xmlel{name = Name, attrs = [], children = Els}). -define(XAE(Name, Attrs, Els), #xmlel{name = Name, attrs = Attrs, children = Els}). -define(C(Text), {xmlcdata, Text}). -define(XC(Name, Text), ?XE(Name, [?C(Text)])). -define(XAC(Name, Attrs, Text), ?XAE(Name, Attrs, [?C(Text)])). -define(T(Text), translate:translate(Lang, Text)). -define(CT(Text), ?C((?T(Text)))). -define(XCT(Name, Text), ?XC(Name, (?T(Text)))). -define(XACT(Name, Attrs, Text), ?XAC(Name, Attrs, (?T(Text)))). -define(LI(Els), ?XE(<<"li">>, Els)). -define(A(URL, Els), ?XAE(<<"a">>, [{<<"href">>, URL}], Els)). -define(AC(URL, Text), ?A(URL, [?C(Text)])). -define(ACT(URL, Text), ?AC(URL, (?T(Text)))). -define(P, ?X(<<"p">>)). -define(BR, ?X(<<"br">>)). -define(INPUT(Type, Name, Value), ?XA(<<"input">>, [{<<"type">>, Type}, {<<"name">>, Name}, {<<"value">>, Value}])). -define(INPUTT(Type, Name, Value), ?INPUT(Type, Name, (?T(Value)))). -define(INPUTS(Type, Name, Value, Size), ?XA(<<"input">>, [{<<"type">>, Type}, {<<"name">>, Name}, {<<"value">>, Value}, {<<"size">>, Size}])). -define(INPUTST(Type, Name, Value, Size), ?INPUT(Type, Name, (?T(Value)), Size)). -define(ACLINPUT(Text), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"value", ID/binary>>, Text)])). -define(TEXTAREA(Name, Rows, Cols, Value), ?XAC(<<"textarea">>, [{<<"name">>, Name}, {<<"rows">>, Rows}, {<<"cols">>, Cols}], Value)). %% Build an xmlelement for result -define(XRES(Text), ?XAC(<<"p">>, [{<<"class">>, <<"result">>}], Text)). %% Guide Link -define(XREST(Text), ?XRES((?T(Text)))). -define(GL(Ref, Title), ?XAE(<<"div">>, [{<<"class">>, <<"guidelink">>}], [?XAE(<<"a">>, [{<<"href">>, <<"/admin/doc/guide.html#", Ref/binary>>}, {<<"target">>, <<"_blank">>}], [?C(<<"[Guide: ", Title/binary, "]">>)])])). %% h1 with a Guide Link -define(H1GL(Name, Ref, Title), [?XC(<<"h1">>, Name), ?GL(Ref, Title)]). ejabberd-16.01/include/ejabberd.hrl0000644000232200023220000000373712645157216017540 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -ifndef(EJABBERD_HRL). -define(EJABBERD_HRL, true). -define(VERSION, ejabberd_config:get_version()). -define(MYHOSTS, ejabberd_config:get_myhosts()). -define(MYNAME, hd(ejabberd_config:get_myhosts())). -define(MYLANG, ejabberd_config:get_mylang()). -define(MSGS_DIR, filename:join(["priv", "msgs"])). -define(SQL_DIR, filename:join(["priv", "sql"])). -define(CONFIG_PATH, <<"ejabberd.cfg">>). -define(LOG_PATH, <<"ejabberd.log">>). -define(EJABBERD_URI, <<"http://www.process-one.net/en/ejabberd/">>). -define(S2STIMEOUT, 600000). %%-define(DBGFSM, true). -record(scram, {storedkey = <<"">>, serverkey = <<"">>, salt = <<"">>, iterationcount = 0 :: integer()}). -type scram() :: #scram{}. -define(SCRAM_DEFAULT_ITERATION_COUNT, 4096). -ifdef(ERL_DEPRECATED_TYPES). -define(TDICT, dict()). -define(TGB_TREE, gb_tree()). -define(TGB_SET, gb_set()). -define(TQUEUE, queue()). -else. -define(TDICT, dict:dict()). -define(TGB_TREE, gb_trees:tree()). -define(TGB_SET, gb_set:set()). -define(TQUEUE, queue:queue()). -endif. -endif. ejabberd-16.01/include/ejabberd_ctl.hrl0000644000232200023220000000203412645157216020367 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -define(STATUS_SUCCESS, 0). -define(STATUS_ERROR, 1). -define(STATUS_USAGE, 2). -define(STATUS_BADRPC, 3). ejabberd-16.01/include/ns.hrl0000644000232200023220000001471312645157216016416 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -define(NS_DISCO_ITEMS, <<"http://jabber.org/protocol/disco#items">>). -define(NS_DISCO_INFO, <<"http://jabber.org/protocol/disco#info">>). -define(NS_VCARD, <<"vcard-temp">>). -define(NS_VCARD_UPDATE, <<"vcard-temp:x:update">>). -define(NS_AUTH, <<"jabber:iq:auth">>). -define(NS_AUTH_ERROR, <<"jabber:iq:auth:error">>). -define(NS_REGISTER, <<"jabber:iq:register">>). -define(NS_SEARCH, <<"jabber:iq:search">>). -define(NS_ROSTER, <<"jabber:iq:roster">>). -define(NS_ROSTER_VER, <<"urn:xmpp:features:rosterver">>). -define(NS_PRIVACY, <<"jabber:iq:privacy">>). -define(NS_BLOCKING, <<"urn:xmpp:blocking">>). -define(NS_PRIVATE, <<"jabber:iq:private">>). -define(NS_VERSION, <<"jabber:iq:version">>). -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_DELAY, <<"urn:xmpp:delay">>). -define(NS_HINTS, <<"urn:xmpp:hints">>). -define(NS_EXPIRE, <<"jabber:x:expire">>). -define(NS_EVENT, <<"jabber:x:event">>). -define(NS_CHATSTATES, <<"http://jabber.org/protocol/chatstates">>). -define(NS_XCONFERENCE, <<"jabber:x:conference">>). -define(NS_STATS, <<"http://jabber.org/protocol/stats">>). -define(NS_MUC, <<"http://jabber.org/protocol/muc">>). -define(NS_MUC_USER, <<"http://jabber.org/protocol/muc#user">>). -define(NS_MUC_ADMIN, <<"http://jabber.org/protocol/muc#admin">>). -define(NS_MUC_OWNER, <<"http://jabber.org/protocol/muc#owner">>). -define(NS_MUC_UNIQUE, <<"http://jabber.org/protocol/muc#unique">>). -define(NS_PUBSUB, <<"http://jabber.org/protocol/pubsub">>). -define(NS_PUBSUB_EVENT, <<"http://jabber.org/protocol/pubsub#event">>). -define(NS_PUBSUB_META_DATA, <<"http://jabber.org/protocol/pubsub#meta-data">>). -define(NS_PUBSUB_OWNER, <<"http://jabber.org/protocol/pubsub#owner">>). -define(NS_PUBSUB_NMI, <<"http://jabber.org/protocol/pubsub#node-meta-info">>). -define(NS_PUBSUB_ERRORS, <<"http://jabber.org/protocol/pubsub#errors">>). -define(NS_PUBSUB_NODE_CONFIG, <<"http://jabber.org/protocol/pubsub#node_config">>). -define(NS_PUBSUB_SUB_OPTIONS, <<"http://jabber.org/protocol/pubsub#subscribe_options">>). -define(NS_PUBSUB_SUBSCRIBE_OPTIONS, <<"http://jabber.org/protocol/pubsub#subscribe_options">>). -define(NS_PUBSUB_PUBLISH_OPTIONS, <<"http://jabber.org/protocol/pubsub#publish_options">>). -define(NS_PUBSUB_SUB_AUTH, <<"http://jabber.org/protocol/pubsub#subscribe_authorization">>). -define(NS_PUBSUB_GET_PENDING, <<"http://jabber.org/protocol/pubsub#get-pending">>). -define(NS_COMMANDS, <<"http://jabber.org/protocol/commands">>). -define(NS_BYTESTREAMS, <<"http://jabber.org/protocol/bytestreams">>). -define(NS_ADMIN, <<"http://jabber.org/protocol/admin">>). -define(NS_ADMIN_ANNOUNCE, <<"http://jabber.org/protocol/admin#announce">>). -define(NS_ADMIN_ANNOUNCE_ALL, <<"http://jabber.org/protocol/admin#announce-all">>). -define(NS_ADMIN_SET_MOTD, <<"http://jabber.org/protocol/admin#set-motd">>). -define(NS_ADMIN_EDIT_MOTD, <<"http://jabber.org/protocol/admin#edit-motd">>). -define(NS_ADMIN_DELETE_MOTD, <<"http://jabber.org/protocol/admin#delete-motd">>). -define(NS_ADMIN_ANNOUNCE_ALLHOSTS, <<"http://jabber.org/protocol/admin#announce-allhosts">>). -define(NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS, <<"http://jabber.org/protocol/admin#announce-all-allhosts">>). -define(NS_ADMIN_SET_MOTD_ALLHOSTS, <<"http://jabber.org/protocol/admin#set-motd-allhosts">>). -define(NS_ADMIN_EDIT_MOTD_ALLHOSTS, <<"http://jabber.org/protocol/admin#edit-motd-allhosts">>). -define(NS_ADMIN_DELETE_MOTD_ALLHOSTS, <<"http://jabber.org/protocol/admin#delete-motd-allhosts">>). -define(NS_SERVERINFO, <<"http://jabber.org/network/serverinfo">>). -define(NS_RSM, <<"http://jabber.org/protocol/rsm">>). -define(NS_EJABBERD_CONFIG, <<"ejabberd:config">>). -define(NS_STREAM, <<"http://etherx.jabber.org/streams">>). -define(NS_STANZAS, <<"urn:ietf:params:xml:ns:xmpp-stanzas">>). -define(NS_STREAMS, <<"urn:ietf:params:xml:ns:xmpp-streams">>). -define(NS_TLS, <<"urn:ietf:params:xml:ns:xmpp-tls">>). -define(NS_SASL, <<"urn:ietf:params:xml:ns:xmpp-sasl">>). -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">>). -define(NS_FEATURE_IQREGISTER, <<"http://jabber.org/features/iq-register">>). -define(NS_FEATURE_COMPRESS, <<"http://jabber.org/features/compress">>). -define(NS_FEATURE_MSGOFFLINE, <<"msgoffline">>). -define(NS_COMPRESS, <<"http://jabber.org/protocol/compress">>). -define(NS_CAPS, <<"http://jabber.org/protocol/caps">>). -define(NS_SHIM, <<"http://jabber.org/protocol/shim">>). -define(NS_ADDRESS, <<"http://jabber.org/protocol/address">>). -define(NS_OOB, <<"jabber:x:oob">>). -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_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">>). -define(NS_FORWARD, <<"urn:xmpp:forward:0">>). -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">>). ejabberd-16.01/include/mod_offline.hrl0000644000232200023220000000060212645157216020247 0ustar debalancedebalance-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}). ejabberd-16.01/include/http_bind.hrl0000644000232200023220000000321512645157216017744 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -define(CT_XML, {<<"Content-Type">>, <<"text/xml; charset=utf-8">>}). -define(CT_PLAIN, {<<"Content-Type">>, <<"text/plain">>}). -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(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, ?NO_CACHE]). ejabberd-16.01/include/mod_proxy65.hrl0000644000232200023220000000351112645157216020163 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% RFC 1928 constants. %%% %%% %%% 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. %%% %%%---------------------------------------------------------------------- %% Version -define(VERSION_5, 5). %% Authentication methods -define(AUTH_ANONYMOUS, 0). -define(AUTH_GSSAPI, 1). -define(AUTH_PLAIN, 2). %% Address Type -define(AUTH_NO_METHODS, 255). -define(ATYP_IPV4, 1). -define(ATYP_DOMAINNAME, 3). -define(ATYP_IPV6, 4). %% Commands -define(CMD_CONNECT, 1). -define(CMD_BIND, 2). -define(CMD_UDP, 3). %% RFC 1928 replies -define(SUCCESS, 0). -define(ERR_GENERAL_FAILURE, 1). -define(ERR_NOT_ALLOWED, 2). -define(ERR_NETWORK_UNREACHABLE, 3). -define(ERR_HOST_UNREACHABLE, 4). -define(ERR_CONNECTION_REFUSED, 5). -define(ERR_TTL_EXPIRED, 6). -define(ERR_COMMAND_NOT_SUPPORTED, 7). -define(ERR_ADDRESS_TYPE_NOT_SUPPORTED, 8). %% RFC 1928 defined timeout. -define(SOCKS5_REPLY_TIMEOUT, 10000). -record(s5_request, {rsv = 0 :: integer(), cmd = connect :: connect | udp, sha1 = <<"">> :: binary()}). ejabberd-16.01/include/ELDAPv3.hrl0000644000232200023220000000416612645157216017075 0ustar debalancedebalance%% Generated by the Erlang ASN.1 compiler version:2.0.1 %% Purpose: Erlang record definitions for each named and unnamed %% SEQUENCE and SET, and macro definitions for each value %% definition,in module ELDAPv3 -record('LDAPMessage',{ messageID, protocolOp, controls = asn1_NOVALUE}). -record('AttributeValueAssertion',{ attributeDesc, assertionValue}). -record('Attribute',{ type, vals}). -record('LDAPResult',{ resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE}). -record('Control',{ controlType, criticality = asn1_DEFAULT, controlValue = asn1_NOVALUE}). -record('BindRequest',{ version, name, authentication}). -record('SaslCredentials',{ mechanism, credentials = asn1_NOVALUE}). -record('BindResponse',{ resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE, serverSaslCreds = asn1_NOVALUE}). -record('SearchRequest',{ baseObject, scope, derefAliases, sizeLimit, timeLimit, typesOnly, filter, attributes}). -record('SubstringFilter',{ type, substrings}). -record('MatchingRuleAssertion',{ matchingRule = asn1_NOVALUE, type = asn1_NOVALUE, matchValue, dnAttributes = asn1_DEFAULT}). -record('SearchResultEntry',{ objectName, attributes}). -record('PartialAttributeList_SEQOF',{ type, vals}). -record('ModifyRequest',{ object, modification}). -record('ModifyRequest_modification_SEQOF',{ operation, modification}). -record('AttributeTypeAndValues',{ type, vals}). -record('AddRequest',{ entry, attributes}). -record('AttributeList_SEQOF',{ type, vals}). -record('ModifyDNRequest',{ entry, newrdn, deleteoldrdn, newSuperior = asn1_NOVALUE}). -record('CompareRequest',{ entry, ava}). -record('ExtendedRequest',{ requestName, requestValue = asn1_NOVALUE}). -record('ExtendedResponse',{ resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE, responseName = asn1_NOVALUE, response = asn1_NOVALUE}). -record('PasswdModifyRequestValue',{ userIdentity = asn1_NOVALUE, oldPasswd = asn1_NOVALUE, newPasswd = asn1_NOVALUE}). -record('PasswdModifyResponseValue',{ genPasswd = asn1_NOVALUE}). -define('maxInt', 2147483647). -define('passwdModifyOID', [49,46,51,46,54,46,49,46,52,46,49,46,52,50,48,51,46,49,46,49,49,46,49]). ejabberd-16.01/include/ejabberd_http.hrl0000644000232200023220000000435012645157216020567 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -record(request, {method :: method(), path = [] :: [binary()], q = [] :: [{binary() | nokey, binary()}], us = {<<>>, <<>>} :: {binary(), binary()}, auth :: {binary(), binary()} | {auth_jid, {binary(), binary()}, jlib:jid()}, lang = <<"">> :: binary(), data = <<"">> :: binary(), ip :: {inet:ip_address(), inet:port_number()}, host = <<"">> :: binary(), port = 5280 :: inet:port_number(), 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, ip :: {inet:ip_address(), inet:port_number()}, host = <<"">> :: binary(), port = 5280 :: inet:port_number(), path = [] :: [binary()], headers = [] :: [{atom() | binary(), binary()}], local_path = [] :: [binary()], 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{}. ejabberd-16.01/include/eldap.hrl0000644000232200023220000000544512645157216017065 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -define(LDAP_PORT, 389). -define(LDAPS_PORT, 636). -type scope() :: baseObject | singleLevel | wholeSubtree. -record(eldap_search, {scope = wholeSubtree :: scope(), base = <<"">> :: binary(), filter :: eldap:filter(), limit = 0 :: non_neg_integer(), attributes = [] :: [binary()], types_only = false :: boolean(), deref_aliases = neverDerefAliases :: neverDerefAliases | derefInSearching | derefFindingBaseObj | derefAlways, timeout = 0 :: non_neg_integer()}). -record(eldap_search_result, {entries = [] :: [eldap_entry()], referrals = [] :: list()}). -record(eldap_entry, {object_name = <<>> :: binary(), attributes = [] :: [{binary(), [binary()]}]}). -type tlsopts() :: [{encrypt, tls | starttls | none} | {tls_cacertfile, binary() | undefined} | {tls_depth, non_neg_integer() | undefined} | {tls_verify, hard | soft | false}]. -record(eldap_config, {servers = [] :: [binary()], backups = [] :: [binary()], tls_options = [] :: tlsopts(), port = ?LDAP_PORT :: inet:port_number(), dn = <<"">> :: binary(), password = <<"">> :: binary(), base = <<"">> :: binary(), deref_aliases = never :: never | searching | finding | always}). -type eldap_config() :: #eldap_config{}. -type eldap_search() :: #eldap_search{}. -type eldap_entry() :: #eldap_entry{}. ejabberd-16.01/include/jlib.hrl0000644000232200023220000003510612645157216016715 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -include("ns.hrl"). -ifdef(NO_EXT_LIB). -include("xml.hrl"). -else. -include_lib("p1_xml/include/xml.hrl"). -endif. -define(STANZA_ERROR(Code, Type, Condition), #xmlel{name = <<"error">>, attrs = [{<<"code">>, Code}, {<<"type">>, Type}], children = [#xmlel{name = Condition, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = []}]}). -define(ERR_BAD_FORMAT, ?STANZA_ERROR(<<"406">>, <<"modify">>, <<"bad-format">>)). -define(ERR_BAD_REQUEST, ?STANZA_ERROR(<<"400">>, <<"modify">>, <<"bad-request">>)). -define(ERR_CONFLICT, ?STANZA_ERROR(<<"409">>, <<"cancel">>, <<"conflict">>)). -define(ERR_FEATURE_NOT_IMPLEMENTED, ?STANZA_ERROR(<<"501">>, <<"cancel">>, <<"feature-not-implemented">>)). -define(ERR_FORBIDDEN, ?STANZA_ERROR(<<"403">>, <<"auth">>, <<"forbidden">>)). -define(ERR_GONE, ?STANZA_ERROR(<<"302">>, <<"modify">>, <<"gone">>)). -define(ERR_INTERNAL_SERVER_ERROR, ?STANZA_ERROR(<<"500">>, <<"wait">>, <<"internal-server-error">>)). -define(ERR_ITEM_NOT_FOUND, ?STANZA_ERROR(<<"404">>, <<"cancel">>, <<"item-not-found">>)). -define(ERR_JID_MALFORMED, ?STANZA_ERROR(<<"400">>, <<"modify">>, <<"jid-malformed">>)). -define(ERR_NOT_ACCEPTABLE, ?STANZA_ERROR(<<"406">>, <<"modify">>, <<"not-acceptable">>)). -define(ERR_NOT_ALLOWED, ?STANZA_ERROR(<<"405">>, <<"cancel">>, <<"not-allowed">>)). -define(ERR_NOT_AUTHORIZED, ?STANZA_ERROR(<<"401">>, <<"auth">>, <<"not-authorized">>)). -define(ERR_PAYMENT_REQUIRED, ?STANZA_ERROR(<<"402">>, <<"auth">>, <<"payment-required">>)). -define(ERR_RECIPIENT_UNAVAILABLE, ?STANZA_ERROR(<<"404">>, <<"wait">>, <<"recipient-unavailable">>)). -define(ERR_REDIRECT, ?STANZA_ERROR(<<"302">>, <<"modify">>, <<"redirect">>)). -define(ERR_REGISTRATION_REQUIRED, ?STANZA_ERROR(<<"407">>, <<"auth">>, <<"registration-required">>)). -define(ERR_REMOTE_SERVER_NOT_FOUND, ?STANZA_ERROR(<<"404">>, <<"cancel">>, <<"remote-server-not-found">>)). -define(ERR_REMOTE_SERVER_TIMEOUT, ?STANZA_ERROR(<<"504">>, <<"wait">>, <<"remote-server-timeout">>)). -define(ERR_RESOURCE_CONSTRAINT, ?STANZA_ERROR(<<"500">>, <<"wait">>, <<"resource-constraint">>)). -define(ERR_SERVICE_UNAVAILABLE, ?STANZA_ERROR(<<"503">>, <<"cancel">>, <<"service-unavailable">>)). -define(ERR_SUBSCRIPTION_REQUIRED, ?STANZA_ERROR(<<"407">>, <<"auth">>, <<"subscription-required">>)). -define(ERR_UNEXPECTED_REQUEST, ?STANZA_ERROR(<<"400">>, <<"wait">>, <<"unexpected-request">>)). -define(ERR_UNEXPECTED_REQUEST_CANCEL, ?STANZA_ERROR(<<"401">>, <<"cancel">>, <<"unexpected-request">>)). %-define(ERR_, % ?STANZA_ERROR("", "", "")). -define(STANZA_ERRORT(Code, Type, Condition, Lang, Text), #xmlel{name = <<"error">>, attrs = [{<<"code">>, Code}, {<<"type">>, Type}], children = [#xmlel{name = Condition, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = []}, #xmlel{name = <<"text">>, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = [{xmlcdata, translate:translate(Lang, Text)}]}]}). -define(ERRT_BAD_FORMAT(Lang, Text), ?STANZA_ERRORT(<<"406">>, <<"modify">>, <<"bad-format">>, Lang, Text)). -define(ERRT_BAD_REQUEST(Lang, Text), ?STANZA_ERRORT(<<"400">>, <<"modify">>, <<"bad-request">>, Lang, Text)). -define(ERRT_CONFLICT(Lang, Text), ?STANZA_ERRORT(<<"409">>, <<"cancel">>, <<"conflict">>, Lang, Text)). -define(ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Text), ?STANZA_ERRORT(<<"501">>, <<"cancel">>, <<"feature-not-implemented">>, Lang, Text)). -define(ERRT_FORBIDDEN(Lang, Text), ?STANZA_ERRORT(<<"403">>, <<"auth">>, <<"forbidden">>, Lang, Text)). -define(ERRT_GONE(Lang, Text), ?STANZA_ERRORT(<<"302">>, <<"modify">>, <<"gone">>, Lang, Text)). -define(ERRT_INTERNAL_SERVER_ERROR(Lang, Text), ?STANZA_ERRORT(<<"500">>, <<"wait">>, <<"internal-server-error">>, Lang, Text)). -define(ERRT_ITEM_NOT_FOUND(Lang, Text), ?STANZA_ERRORT(<<"404">>, <<"cancel">>, <<"item-not-found">>, Lang, Text)). -define(ERRT_JID_MALFORMED(Lang, Text), ?STANZA_ERRORT(<<"400">>, <<"modify">>, <<"jid-malformed">>, Lang, Text)). -define(ERRT_NOT_ACCEPTABLE(Lang, Text), ?STANZA_ERRORT(<<"406">>, <<"modify">>, <<"not-acceptable">>, Lang, Text)). -define(ERRT_NOT_ALLOWED(Lang, Text), ?STANZA_ERRORT(<<"405">>, <<"cancel">>, <<"not-allowed">>, Lang, Text)). -define(ERRT_NOT_AUTHORIZED(Lang, Text), ?STANZA_ERRORT(<<"401">>, <<"auth">>, <<"not-authorized">>, Lang, Text)). -define(ERRT_PAYMENT_REQUIRED(Lang, Text), ?STANZA_ERRORT(<<"402">>, <<"auth">>, <<"payment-required">>, Lang, Text)). -define(ERRT_RECIPIENT_UNAVAILABLE(Lang, Text), ?STANZA_ERRORT(<<"404">>, <<"wait">>, <<"recipient-unavailable">>, Lang, Text)). -define(ERRT_REDIRECT(Lang, Text), ?STANZA_ERRORT(<<"302">>, <<"modify">>, <<"redirect">>, Lang, Text)). -define(ERRT_REGISTRATION_REQUIRED(Lang, Text), ?STANZA_ERRORT(<<"407">>, <<"auth">>, <<"registration-required">>, Lang, Text)). -define(ERRT_REMOTE_SERVER_NOT_FOUND(Lang, Text), ?STANZA_ERRORT(<<"404">>, <<"cancel">>, <<"remote-server-not-found">>, Lang, Text)). -define(ERRT_REMOTE_SERVER_TIMEOUT(Lang, Text), ?STANZA_ERRORT(<<"504">>, <<"wait">>, <<"remote-server-timeout">>, Lang, Text)). -define(ERRT_RESOURCE_CONSTRAINT(Lang, Text), ?STANZA_ERRORT(<<"500">>, <<"wait">>, <<"resource-constraint">>, Lang, Text)). -define(ERRT_SERVICE_UNAVAILABLE(Lang, Text), ?STANZA_ERRORT(<<"503">>, <<"cancel">>, <<"service-unavailable">>, Lang, Text)). -define(ERRT_SUBSCRIPTION_REQUIRED(Lang, Text), ?STANZA_ERRORT(<<"407">>, <<"auth">>, <<"subscription-required">>, Lang, Text)). -define(ERRT_UNEXPECTED_REQUEST(Lang, Text), ?STANZA_ERRORT(<<"400">>, <<"wait">>, <<"unexpected-request">>, Lang, Text)). -define(ERR_AUTH_NO_RESOURCE_PROVIDED(Lang), ?ERRT_NOT_ACCEPTABLE(Lang, <<"No resource provided">>)). -define(ERR_AUTH_BAD_RESOURCE_FORMAT(Lang), ?ERRT_NOT_ACCEPTABLE(Lang, <<"Illegal resource format">>)). -define(ERR_AUTH_RESOURCE_CONFLICT(Lang), ?ERRT_CONFLICT(Lang, <<"Resource conflict">>)). -define(STREAM_ERROR(Condition, Cdata), #xmlel{name = <<"stream:error">>, attrs = [], children = [#xmlel{name = Condition, attrs = [{<<"xmlns">>, ?NS_STREAMS}], children = [{xmlcdata, Cdata}]}]}). -define(SERR_BAD_FORMAT, ?STREAM_ERROR(<<"bad-format">>, <<"">>)). -define(SERR_BAD_NAMESPACE_PREFIX, ?STREAM_ERROR(<<"bad-namespace-prefix">>, <<"">>)). -define(SERR_CONFLICT, ?STREAM_ERROR(<<"conflict">>, <<"">>)). -define(SERR_CONNECTION_TIMEOUT, ?STREAM_ERROR(<<"connection-timeout">>, <<"">>)). -define(SERR_HOST_GONE, ?STREAM_ERROR(<<"host-gone">>, <<"">>)). -define(SERR_HOST_UNKNOWN, ?STREAM_ERROR(<<"host-unknown">>, <<"">>)). -define(SERR_IMPROPER_ADDRESSING, ?STREAM_ERROR(<<"improper-addressing">>, <<"">>)). -define(SERR_INTERNAL_SERVER_ERROR, ?STREAM_ERROR(<<"internal-server-error">>, <<"">>)). -define(SERR_INVALID_FROM, ?STREAM_ERROR(<<"invalid-from">>, <<"">>)). -define(SERR_INVALID_ID, ?STREAM_ERROR(<<"invalid-id">>, <<"">>)). -define(SERR_INVALID_NAMESPACE, ?STREAM_ERROR(<<"invalid-namespace">>, <<"">>)). -define(SERR_INVALID_XML, ?STREAM_ERROR(<<"invalid-xml">>, <<"">>)). -define(SERR_NOT_AUTHORIZED, ?STREAM_ERROR(<<"not-authorized">>, <<"">>)). -define(SERR_POLICY_VIOLATION, ?STREAM_ERROR(<<"policy-violation">>, <<"">>)). -define(SERR_REMOTE_CONNECTION_FAILED, ?STREAM_ERROR(<<"remote-connection-failed">>, <<"">>)). -define(SERR_RESOURSE_CONSTRAINT, ?STREAM_ERROR(<<"resource-constraint">>, <<"">>)). -define(SERR_RESTRICTED_XML, ?STREAM_ERROR(<<"restricted-xml">>, <<"">>)). -define(SERR_SEE_OTHER_HOST(Host), ?STREAM_ERROR(<<"see-other-host">>, Host)). -define(SERR_SYSTEM_SHUTDOWN, ?STREAM_ERROR(<<"system-shutdown">>, <<"">>)). -define(SERR_UNSUPPORTED_ENCODING, ?STREAM_ERROR(<<"unsupported-encoding">>, <<"">>)). -define(SERR_UNSUPPORTED_STANZA_TYPE, ?STREAM_ERROR(<<"unsupported-stanza-type">>, <<"">>)). -define(SERR_UNSUPPORTED_VERSION, ?STREAM_ERROR(<<"unsupported-version">>, <<"">>)). -define(SERR_XML_NOT_WELL_FORMED, ?STREAM_ERROR(<<"xml-not-well-formed">>, <<"">>)). %-define(SERR_, % ?STREAM_ERROR("", "")). -define(STREAM_ERRORT(Condition, Cdata, Lang, Text), #xmlel{name = <<"stream:error">>, attrs = [], children = [#xmlel{name = Condition, attrs = [{<<"xmlns">>, ?NS_STREAMS}], children = [{xmlcdata, Cdata}]}, #xmlel{name = <<"text">>, attrs = [{<<"xml:lang">>, Lang}, {<<"xmlns">>, ?NS_STREAMS}], children = [{xmlcdata, translate:translate(Lang, Text)}]}]}). -define(SERRT_BAD_FORMAT(Lang, Text), ?STREAM_ERRORT(<<"bad-format">>, <<"">>, Lang, Text)). -define(SERRT_BAD_NAMESPACE_PREFIX(Lang, Text), ?STREAM_ERRORT(<<"bad-namespace-prefix">>, <<"">>, Lang, Text)). -define(SERRT_CONFLICT(Lang, Text), ?STREAM_ERRORT(<<"conflict">>, <<"">>, Lang, Text)). -define(SERRT_CONNECTION_TIMEOUT(Lang, Text), ?STREAM_ERRORT(<<"connection-timeout">>, <<"">>, Lang, Text)). -define(SERRT_HOST_GONE(Lang, Text), ?STREAM_ERRORT(<<"host-gone">>, <<"">>, Lang, Text)). -define(SERRT_HOST_UNKNOWN(Lang, Text), ?STREAM_ERRORT(<<"host-unknown">>, <<"">>, Lang, Text)). -define(SERRT_IMPROPER_ADDRESSING(Lang, Text), ?STREAM_ERRORT(<<"improper-addressing">>, <<"">>, Lang, Text)). -define(SERRT_INTERNAL_SERVER_ERROR(Lang, Text), ?STREAM_ERRORT(<<"internal-server-error">>, <<"">>, Lang, Text)). -define(SERRT_INVALID_FROM(Lang, Text), ?STREAM_ERRORT(<<"invalid-from">>, <<"">>, Lang, Text)). -define(SERRT_INVALID_ID(Lang, Text), ?STREAM_ERRORT(<<"invalid-id">>, <<"">>, Lang, Text)). -define(SERRT_INVALID_NAMESPACE(Lang, Text), ?STREAM_ERRORT(<<"invalid-namespace">>, <<"">>, Lang, Text)). -define(SERRT_INVALID_XML(Lang, Text), ?STREAM_ERRORT(<<"invalid-xml">>, <<"">>, Lang, Text)). -define(SERRT_NOT_AUTHORIZED(Lang, Text), ?STREAM_ERRORT(<<"not-authorized">>, <<"">>, Lang, Text)). -define(SERRT_POLICY_VIOLATION(Lang, Text), ?STREAM_ERRORT(<<"policy-violation">>, <<"">>, Lang, Text)). -define(SERRT_REMOTE_CONNECTION_FAILED(Lang, Text), ?STREAM_ERRORT(<<"remote-connection-failed">>, <<"">>, Lang, Text)). -define(SERRT_RESOURSE_CONSTRAINT(Lang, Text), ?STREAM_ERRORT(<<"resource-constraint">>, <<"">>, Lang, Text)). -define(SERRT_RESTRICTED_XML(Lang, Text), ?STREAM_ERRORT(<<"restricted-xml">>, <<"">>, Lang, Text)). -define(SERRT_SEE_OTHER_HOST(Host, Lang, Text), ?STREAM_ERRORT(<<"see-other-host">>, Host, Lang, Text)). -define(SERRT_SYSTEM_SHUTDOWN(Lang, Text), ?STREAM_ERRORT(<<"system-shutdown">>, <<"">>, Lang, Text)). -define(SERRT_UNSUPPORTED_ENCODING(Lang, Text), ?STREAM_ERRORT(<<"unsupported-encoding">>, <<"">>, Lang, Text)). -define(SERRT_UNSUPPORTED_STANZA_TYPE(Lang, Text), ?STREAM_ERRORT(<<"unsupported-stanza-type">>, <<"">>, Lang, Text)). -define(SERRT_UNSUPPORTED_VERSION(Lang, Text), ?STREAM_ERRORT(<<"unsupported-version">>, <<"">>, Lang, Text)). -define(SERRT_XML_NOT_WELL_FORMED(Lang, Text), ?STREAM_ERRORT(<<"xml-not-well-formed">>, <<"">>, Lang, Text)). -record(jid, {user = <<"">> :: binary(), server = <<"">> :: binary(), resource = <<"">> :: binary(), luser = <<"">> :: binary(), lserver = <<"">> :: binary(), lresource = <<"">> :: binary()}). -type(jid() :: #jid{}). -type(ljid() :: {binary(), binary(), binary()}). -record(iq, {id = <<"">> :: binary(), type = get :: get | set | result | error, xmlns = <<"">> :: binary(), lang = <<"">> :: binary(), sub_el = #xmlel{} :: xmlel() | [xmlel()]}). -type(iq_get() :: #iq{ id :: binary(), type :: get, xmlns :: binary(), lang :: binary(), sub_el :: xmlel() } ). -type(iq_set() :: #iq{ id :: binary(), type :: set, xmlns :: binary(), lang :: binary(), sub_el :: xmlel() } ). -type iq_request() :: iq_get() | iq_set(). -type(iq_result() :: #iq{ id :: binary(), type :: result, xmlns :: binary(), lang :: binary(), sub_el :: [xmlel()] } ). -type(iq_error() :: #iq{ id :: binary(), type :: error, xmlns :: binary(), lang :: binary(), sub_el :: [xmlel()] } ). -type iq_reply() :: iq_result() | iq_error() . -type(iq() :: iq_request() | iq_reply()). -record(rsm_in, {max :: integer() | error, direction :: before | aft, id :: binary(), index :: integer() | error}). -record(rsm_out, {count :: integer(), index :: integer(), first :: binary(), last :: binary()}). -type(rsm_in() :: #rsm_in{}). -type(rsm_out() :: #rsm_out{}). -type broadcast() :: {broadcast, broadcast_data()}. -type broadcast_data() :: {rebind, pid(), binary()} | %% ejabberd_c2s {item, ljid(), mod_roster:subscription()} | %% mod_roster/mod_shared_roster {exit, binary()} | %% mod_roster/mod_shared_roster {privacy_list, mod_privacy:userlist(), binary()} | %% mod_privacy {blocking, unblock_all | {block | unblock, [ljid()]}}. %% mod_blocking -record(xmlelement, {name = "" :: string(), attrs = [] :: [{string(), string()}], children = [] :: [{xmlcdata, iodata()} | xmlelement()]}). -type xmlelement() :: #xmlelement{}. ejabberd-16.01/include/mod_roster.hrl0000644000232200023220000000337312645157216020153 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -record(roster, { usj = {<<>>, <<>>, {<<>>, <<>>, <<>>}} :: {binary(), binary(), ljid()} | '_', us = {<<>>, <<>>} :: {binary(), binary()} | '_', jid = {<<>>, <<>>, <<>>} :: ljid(), name = <<>> :: binary() | '_', subscription = none :: subscription() | '_', ask = none :: ask() | '_', groups = [] :: [binary()] | '_', askmessage = <<"">> :: binary() | '_', xs = [] :: [xmlel()] | '_' }). -record(roster_version, { us = {<<>>, <<>>} :: {binary(), binary()}, version = <<>> :: binary() }). -type ask() :: none | in | out | both | subscribe | unsubscribe. -type subscription() :: none | both | from | to | remove. ejabberd-16.01/include/mod_muc_room.hrl0000644000232200023220000001130312645157216020445 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -include("ejabberd.hrl"). -define(MAX_USERS_DEFAULT, 200). -define(SETS, gb_sets). -define(DICT, dict). -record(lqueue, { queue :: ?TQUEUE, len :: integer(), max :: integer() }). -type lqueue() :: #lqueue{}. -record(config, { title = <<"">> :: binary(), description = <<"">> :: binary(), allow_change_subj = true :: boolean(), allow_query_users = true :: boolean(), allow_private_messages = true :: boolean(), allow_private_messages_from_visitors = anyone :: anyone | moderators | nobody , allow_visitor_status = true :: boolean(), allow_visitor_nickchange = true :: boolean(), public = true :: boolean(), public_list = true :: boolean(), persistent = false :: boolean(), moderated = true :: boolean(), captcha_protected = false :: boolean(), members_by_default = true :: boolean(), members_only = false :: boolean(), allow_user_invites = false :: boolean(), 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, logging = false :: boolean(), vcard = <<"">> :: binary(), captcha_whitelist = (?SETS):empty() :: ?TGB_SET, mam = false :: boolean() }). -type config() :: #config{}. -type role() :: moderator | participant | visitor | none. -record(user, { jid :: jid(), nick :: binary(), role :: role(), last_presence :: xmlel() }). -record(activity, { message_time = 0 :: integer(), presence_time = 0 :: integer(), message_shaper :: shaper:shaper(), presence_shaper :: shaper:shaper(), message :: xmlel(), presence :: {binary(), xmlel()} }). -record(state, { room = <<"">> :: binary(), host = <<"">> :: binary(), server_host = <<"">> :: binary(), access = {none,none,none,none} :: {atom(), atom(), atom(), atom()}, jid = #jid{} :: jid(), config = #config{} :: config(), users = (?DICT):new() :: ?TDICT, last_voice_request_time = treap:empty() :: treap:treap(), robots = (?DICT):new() :: ?TDICT, nicks = (?DICT):new() :: ?TDICT, affiliations = (?DICT):new() :: ?TDICT, history :: lqueue(), subject = <<"">> :: binary(), subject_author = <<"">> :: binary(), just_created = false :: boolean(), activity = treap:empty() :: treap:treap(), room_shaper = none :: shaper:shaper(), room_queue = queue:new() :: ?TQUEUE }). -record(muc_online_users, {us = {<<>>, <<>>} :: {binary(), binary()}, resource = <<>> :: binary() | '_', room = <<>> :: binary() | '_' | '$1', host = <<>> :: binary() | '_' | '$2'}). -type muc_online_users() :: #muc_online_users{}. -type muc_room_state() :: #state{}. ejabberd-16.01/include/pubsub.hrl0000644000232200023220000001264412645157216017277 0ustar debalancedebalance%%% ==================================================================== %%% ``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 %%% %%% This file contains pubsub types definition. %%% ==================================================================== -include("ejabberd.hrl"). %% ------------------------------- %% Pubsub constants -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). %% this is currently a hard limit. %% Would be nice to have it configurable. -define(MAX_PAYLOAD_SIZE, 60000). %% ------------------------------- %% Pubsub types -type(hostPubsub() :: binary()). %%

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

-type(hostPEP() :: {binary(), binary(), <<>>}). %% @type hostPEP() = {User, Server, Resource} %% User = string() %% Server = string() %% Resource = []. %%

For example, it can be : %% ```{"bob", "example.org", []}'''.

-type(host() :: hostPubsub() | hostPEP()). %% @type host() = hostPubsub() | hostPEP(). -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: %% ```<<"/home/localhost/user">>'''

-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(). -type(subId() :: binary()). %% @type subId() = string(). -type(nodeOption() :: {Option::atom(), Value::atom() | [binary()] | boolean() | non_neg_integer() }). -type(nodeOptions() :: [mod_pubsub:nodeOption(),...]). %% @type nodeOption() = {Option, Value} %% Option = atom() %% Value = term(). %% Example: %% ```{deliver_payloads, true}''' -type(subOption() :: {Option::atom(), Value::binary() | [binary()] | boolean() }). -type(subOptions() :: [mod_pubsub:subOption(),...]). -type(affiliation() :: 'none' | 'owner' | 'publisher' | 'publish_only' | 'member' | 'outcast' ). %% @type affiliation() = 'none' | 'owner' | 'publisher' | 'publish-only' | 'member' | 'outcast'. -type(subscription() :: 'none' | 'pending' | 'unconfigured' | 'subscribed' ). %% @type subscription() = 'none' | 'pending' | 'unconfigured' | 'subscribed'. -type(accessModel() :: 'open' | 'presence' | 'roster' | 'authorize' | 'whitelist' ). %% @type accessModel() = 'open' | 'presence' | 'roster' | 'authorize' | 'whitelist'. -type(publishModel() :: 'publishers' | 'subscribers' | 'open' ). %% @type publishModel() = 'publishers' | 'subscribers' | 'open' -record(pubsub_index, { index :: atom(), last :: mod_pubsub:nodeIdx(), free :: [mod_pubsub:nodeIdx()] }). -record(pubsub_node, { 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() }). -record(pubsub_state, { stateid ,% :: {jlib:ljid(), mod_pubsub:nodeIdx()}, items = [] ,% :: [mod_pubsub:itemId(),...], affiliation = 'none',% :: mod_pubsub:affiliation(), subscriptions = [] % :: [{mod_pubsub:subscription(), mod_pubsub:subId()}] }). -record(pubsub_item, { 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() }). -record(pubsub_subscription, { subid ,% :: mod_pubsub:subId(), options = [] % :: mod_pubsub:subOptions() }). -record(pubsub_last_item, { nodeid ,% :: mod_pubsub:nodeIdx(), itemid ,% :: mod_pubsub:itemId(), creation ,% :: {erlang:timestamp(), jlib:ljid()}, payload % :: mod_pubsub:payload() }). ejabberd-16.01/include/ejabberd_config.hrl0000644000232200023220000000242212645157216021053 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -record(local_config, {key :: any(), value :: any()}). -type local_config() :: #local_config{}. -record(state, {opts = [] :: [acl:acl() | local_config()], hosts = [] :: [binary()], override_local = false :: boolean(), override_global = false :: boolean(), override_acls = false :: boolean()}). ejabberd-16.01/include/mod_privacy.hrl0000644000232200023220000000356212645157216020312 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -record(privacy, {us = {<<"">>, <<"">>} :: {binary(), binary()}, default = none :: none | binary(), lists = [] :: [{binary(), [listitem()]}]}). -record(listitem, {type = none :: none | jid | group | subscription, value = none :: none | both | from | to | ljid() | binary(), action = allow :: allow | deny, order = 0 :: integer(), match_all = false :: boolean(), match_iq = false :: boolean(), match_message = false :: boolean(), match_presence_in = false :: boolean(), match_presence_out = false :: boolean()}). -type listitem() :: #listitem{}. -record(userlist, {name = none :: none | binary(), list = [] :: [listitem()], needdb = false :: boolean()}). -type userlist() :: #userlist{}. -export_type([userlist/0]). ejabberd-16.01/include/adhoc.hrl0000644000232200023220000000316012645157216017046 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -record(adhoc_request, { lang = <<"">> :: binary(), node = <<"">> :: binary(), sessionid = <<"">> :: binary(), action = <<"">> :: binary(), xdata = false :: false | xmlel(), others = [] :: [xmlel()] }). -record(adhoc_response, { lang = <<"">> :: binary(), node = <<"">> :: binary(), sessionid = <<"">> :: binary(), status :: atom(), defaultaction = <<"">> :: binary(), actions = [] :: [binary()], notes = [] :: [{binary(), binary()}], elements = [] :: [xmlel()] }). -type adhoc_request() :: #adhoc_request{}. -type adhoc_response() :: #adhoc_response{}. ejabberd-16.01/include/logger.hrl0000644000232200023220000000345212645157216017253 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -define(PRINT(Format, Args), io:format(Format, Args)). -ifdef(LAGER). -compile([{parse_transform, lager_transform}]). -define(DEBUG(Format, Args), lager:debug(Format, Args)). -define(INFO_MSG(Format, Args), lager:info(Format, Args)). -define(WARNING_MSG(Format, Args), lager:warning(Format, Args)). -define(ERROR_MSG(Format, Args), lager:error(Format, Args)). -define(CRITICAL_MSG(Format, Args), lager:critical(Format, Args)). -else. -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)). -endif. ejabberd-16.01/include/ejabberd_sm.hrl0000644000232200023220000000066212645157216020231 0ustar debalancedebalance-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()}. -type ip() :: {inet:ip_address(), inet:port_number()} | undefined. -type info() :: [{conn, atom()} | {ip, ip()} | {node, atom()} | {oor, boolean()} | {auth_module, atom()}]. -type prio() :: undefined | integer(). -endif. ejabberd-16.01/include/ejabberd_commands.hrl0000644000232200023220000000663612645157216021422 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% %%% 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. %%% %%%---------------------------------------------------------------------- -type aterm() :: {atom(), atype()}. -type atype() :: integer | string | binary | {tuple, [aterm()]} | {list, aterm()}. -type rterm() :: {atom(), rtype()}. -type rtype() :: integer | string | atom | {tuple, [rterm()]} | {list, rterm()} | rescode | restuple. -record(ejabberd_commands, {name :: atom(), tags = [] :: [atom()] | '_' | '$2', desc = "" :: string() | '_' | '$3', longdesc = "" :: string() | '_', module :: atom(), function :: atom(), args = [] :: [aterm()] | '_' | '$1' | '$2', policy = restricted :: open | restricted | admin | user, 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()], desc :: string(), longdesc :: string(), module :: atom(), function :: atom(), args :: [aterm()], result :: rterm()}. %% @type ejabberd_commands() = #ejabberd_commands{ %% name = atom(), %% tags = [atom()], %% desc = string(), %% longdesc = string(), %% module = atom(), %% function = atom(), %% args = [aterm()], %% result = rterm() %% }. %% desc: Description of the command %% args: Describe the accepted arguments. %% This way the function that calls the command can format the %% arguments before calling. %% @type atype() = integer | string | {tuple, [aterm()]} | {list, aterm()}. %% Allowed types for arguments are integer, string, tuple and list. %% @type rtype() = integer | string | atom | {tuple, [rterm()]} | {list, rterm()} | rescode | restuple. %% A rtype is either an atom or a tuple with two elements. %% @type aterm() = {Name::atom(), Type::atype()}. %% An argument term is a tuple with the term name and the term type. %% @type rterm() = {Name::atom(), Type::rtype()}. %% A result term is a tuple with the term name and the term type. ejabberd-16.01/win32/0000755000232200023220000000000012645157216014600 5ustar debalancedebalanceejabberd-16.01/win32/CheckUser.ini0000644000232200023220000000044312645157216017156 0ustar debalancedebalance[Settings] NumFields=1 [Field 1] Type=label Left=0 Right=-1 Top=10 Bottom=-10 Text="Administrator privileges are recommended for Ejabberd install.\r\n\r\nOtherwise installing Ejabberd as a service will be impossible.\r\n\r\nIf you want to continue installing Ejabberd anyway, click Next." ejabberd-16.01/win32/ejabberd_intro.bmp0000644000232200023220000006357612645157216020272 0ustar debalancedebalanceBM~gv(¤:g  €€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿDDD@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@DDDDDDDDD@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDD@@@@DDDDDDDDDD@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@DDDDDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@DDDDDDDDDD@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@DDDDDDDDD@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@DDDDDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDD@@@@@DDDDDDDDD@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@DDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@DDDDDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@DDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDD@@@@@@DDDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@DDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDD@@@@@@@@@DDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@DDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@@@DDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDD@@@@@@@@@@@@@@@@DDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDD@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDD@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@DDDDD@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@DDDDDD@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@DDDDDD@@@@@@@DDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@DDDDD@@@@@@DDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@DDDDDD@@@@@DDDDDD@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@DDDDDD@@@@@DDDD@@@@@@@@@@@@@@@@@DDDDDDDDDD@DDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@DDDDDDDDDDDDDDDDDDD@@@@@@DDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@DDDDDD@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@DDDDDDDDDDDDDDDDD@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@DDDDDDD@@@@@@@@@@@@@@@@@@@@DDDDDDDDD@@@@@@DDDDDDDDDDDDDDD@@@@@@@DDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@DDDDDDD@@@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@DDDDDDDDDDDDDD@@@@@@DDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@DDDDDDD@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@DDDDDDDDDDD@@@@@@@DDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDD@@@@@@@@@@@@DDDDDDDDD@@@@@@@@@@@@DDDDDDDDD@@@@@@@DDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDD@@@@@@@@@@@DDDDDDDD@@@@@@@@@@@@@DDDDDDDD@@@@@@@DDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@DDDDDDDD@@@@@@@@@@DDDDDD@@@@@@@@@@@@@@@DDDDDD@@@@@@@DDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@DDDDDDDD@@@@@@@@@@DDDD@@@@@@@@@@@@@@@@@DDDD@@@@@@DDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@DDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDD@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@DDDDDDDD@@@@@@@@@@@@@@@@@DDDDDDD@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@DDDDDDDDD@@@@@@@@@@@@@DDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@DDDDDDDDDDD@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@DDDDDDDDDDD@@@@@@DDDDDDDDDDDD@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@DDDDDDDDDDDD@DDDDDDDDDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDD@DDDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@DDDDDDDDD@@@@@@@@@@@@@DDDDDDDDDDDDDDDDD@@DDDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@DDDDDDDDDD@@@@@@@@@@@@@@DDDDDDDDDDDD@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDD@@@@@@@@@@@@@@DDDDDDDD@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@DDDDDDDDDDDD@@@@@@@@@@@@@@DDDD@@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@DDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@DDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@DDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@DDDDDDDDDD@@@@@@@@@@@@@@@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@@DD@@@@@@DD@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDD@@@@DDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@DDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@DDDDDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@DDD@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@@@@@@@@@@@@DDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôDDDDDDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôDDDDDDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@@@@@@@@@@@DDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôDDDDDDOôDDDDDDDDDDDDDDDDDDDDDDOðÿððÿððÿÿÿÿÿôDDDDDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@@@@@@@@@DDDDDDDDDOðÿððÿððÿÿÿÿÿôDDDDDOôDDDDDDDDDDDDDDDDDDDDDDDOðÿððÿÿÿðÿððÿðÿÿÿÿÿôDDDDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@@@@@@@DDDDDDDDDDDOðÿððÿÿÿðÿððÿðÿÿÿÿÿôDDDDOôDDDDDDDDDDDDDDDDDDDDDDDDDOðÿðÿðÿðÿðÿÿÿÿÿÿôDDDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@@@@@@DDDDDDDDDDDDOðÿðÿðÿðÿðÿÿÿÿÿÿôDDDOôDDDDDDDDDDDDDDDDDDDDDDDDDDDOðÿððÿÿÿðÿððÿðÿÿÿÿÿÿÿôDDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@@@@DDDDDDDDDDDDDDOðÿððÿÿÿðÿððÿðÿÿÿÿÿÿÿôDDOôDDDDDDDDDDDDDDDDDDDDDDDDDDDDOðÿððÿðÿÿÿÿÿÿÿÿôDDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@@@DDDDDDDDDDDDDDDOðÿððÿðÿÿÿÿÿÿÿÿôDDOôDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@@@DDDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôDOôDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDOðÿôDDOÿÿÿÿÿÿÿôDDDOÿÿÿÿÿÿÿôDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@@DDDDDDDDDDDDDDDDDDDOðÿôDDOÿÿÿÿÿÿÿôDDDOÿÿÿÿÿÿÿôDOôDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDDOÿÿÿÿÿÿôDDDDDOÿÿÿÿÿÿôDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDD@DDDDDDDDDDDDDDDDDDDDOðÿðôDDOÿÿÿÿÿÿôDDDDDOÿÿÿÿÿÿôDOôDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDOðÿôDOÿÿÿÿÿÿôDDDDDDOÿÿÿÿÿÿôDOôDDDDDDDD@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDOðÿôDOÿÿÿÿÿÿôDDDDDDOÿÿÿÿÿÿôDOôDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDOÿÿÿÿÿÿôDDDDDDOÿÿÿÿÿÿÿôOôDDDDDDDD@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDOÿÿÿÿÿÿôDDDDDDOÿÿÿÿÿÿÿôOôDDDDDDD@DDDDDDDDDDDDDDDDDDDDDDDDDOðÿôDOÿÿÿÿÿÿôDDDDDDOÿÿÿÿÿÿÿôOôDDDDDDD@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDOðÿôDOÿÿÿÿÿÿôDDDDDDOÿÿÿÿÿÿÿôOôDDDDD@@@DDDDDDDDDDDDDDDDDDDDDDDDDOÿÿÿÿÿôOÿÿÿÿÿÿÿÿôDDDDDOÿÿÿÿÿÿÿôOôDDDDD@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDOÿÿÿÿÿôOÿÿÿÿÿÿÿÿôDDDDDOÿÿÿÿÿÿÿôOôDDDD@@@@DDDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOôDDD@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOôDD@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDOðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOôDD@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDDOðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDOðÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDOÿðÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDDOÿðÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDOÿÿÿÿÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDDOÿÿÿÿÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDOÿðÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDDOÿðÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDDDDDDDDDOðÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDDOðÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDDDDDDDDOÿÿÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDDDOÿÿÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDDDDDDDOÿÿÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDDDOÿÿÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDDDDDOÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDDDDDDOÿðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@DDDDDDDDDDDDDOÿÿÿÿÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DDDDDDDDDDDOÿÿÿÿÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@ðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@OðôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@ðÿÿÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOô@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@OðÿÿÿôDDDDDDDDDDDDDDDOÿÿÿÿÿÿÿôOð@@@@@@@@ðÿôDDDDDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿô@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@OðÿôDDDDDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿð@@@@@@@@ðÿÿÿôDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿô@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@OðÿÿÿôDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿð@@@@@@@@ðôDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿô@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@OðôDDDDDDDDDDOÿÿÿÿÿÿÿÿÿÿÿÿÿÿð@@@@@@@@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿô@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Oÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ejabberd-16.01/win32/ejabberd.cfg0000644000232200023220000001161212645157216017020 0ustar debalancedebalance% $Id$ %override_acls. % Users that have admin access. Add line like one of the following after you % will be successfully registered on server to get admin access: %{acl, admin, {user, "aleksey"}}. %{acl, admin, {user, "ermine"}}. % Blocked users: %{acl, blocked, {user, "test"}}. % Local users: {acl, local, {user_regexp, ""}}. % Another examples of ACLs: %{acl, jabberorg, {server, "jabber.org"}}. %{acl, aleksey, {user, "aleksey", "jabber.ru"}}. %{acl, test, {user_regexp, "^test"}}. %{acl, test, {user_glob, "test*"}}. % Only admins can use configuration interface: {access, configure, [{allow, admin}]}. % Every username can be registered via in-band registration: {access, register, [{allow, all}]}. % After successful registration user will get message with following subject % and body: {welcome_message, {"Welcome!", "Welcome to Jabber Service. " "For information about Jabber visit http://jabber.org"}}. % Replace them with 'none' if you don't want to send such message: %{welcome_message, none}. % List of people who will get notifications about registered users %{registration_watchers, ["admin1@localhost", % "admin2@localhost"]}. % Only admins can send announcement messages: {access, announce, [{allow, admin}]}. % Only non-blocked users can use c2s connections: {access, c2s, [{deny, blocked}, {allow, all}]}. % Set shaper with name "normal" to limit traffic speed to 1000B/s {shaper, normal, {maxrate, 1000}}. % Set shaper with name "fast" to limit traffic speed to 50000B/s {shaper, fast, {maxrate, 50000}}. % For all users except admins used "normal" shaper {access, c2s_shaper, [{none, admin}, {normal, all}]}. % For all S2S connections used "fast" shaper {access, s2s_shaper, [{fast, all}]}. % Admins of this server are also admins of MUC service: {access, muc_admin, [{allow, admin}]}. % All users are allowed to use MUC service: {access, muc, [{allow, all}]}. % This rule allows access only for local users: {access, local, [{allow, local}]}. % Authentification method. If you want to use internal user base, then use % this line: {auth_method, internal}. % For LDAP authentification use these lines instead of above one: %{auth_method, ldap}. %{ldap_servers, ["localhost"]}. % List of LDAP servers %{ldap_uidattr, "uid"}. % LDAP attribute that holds user ID %{ldap_base, "dc=example,dc=com"}. % Base of LDAP directory %{ldap_rootdn, "dc=example,dc=com"}. % LDAP manager %{ldap_password, "******"}. % Password to LDAP manager % For authentification via external script use the following: %{auth_method, external}. %{extauth_program, "/path/to/authentification/script"}. % For authentification via ODBC use the following: %{auth_method, odbc}. %{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}. % Host name(s): {hosts, ["localhost"]}. % Default language: {language, "en"}. % Listened ports: {listen, [ {5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]}, % To create selfsigned certificate run the following command from the % command prompt: % % openssl req -new -x509 -days 365 -nodes -out ejabberd.pem -keyout ejabberd.pem % % and answer the questions. % {5222, ejabberd_c2s, [{access, c2s}, % starttls, {certfile, "./ejabberd.pem"}, % {shaper, c2s_shaper}]}, % When using SSL/TLS ssl option is not recommended (it requires patching % erlang ssl application). Use tls option instead (as shown below). % {5223, ejabberd_c2s, [{access, c2s}, % tls, {certfile, "./ejabberd.pem"}, % {shaper, c2s_shaper}]}, {5269, ejabberd_s2s_in, [{shaper, s2s_shaper}]}, % {5555, ejabberd_service, [{access, all}, % {host, "icq.localhost", [{password, "secret"}]}]}, {5280, ejabberd_http, [http_poll, web_admin]} ]}. % If SRV lookup fails, then port 5269 is used to communicate with remote server {outgoing_s2s_port, 5269}. % Used modules: {modules, [ {mod_register, [{access, register}]}, {mod_roster, []}, {mod_shared_roster, []}, {mod_privacy, []}, {mod_configure, []}, {mod_disco, []}, {mod_stats, []}, {mod_vcard, []}, {mod_offline, []}, {mod_announce, [{access, announce}]}, {mod_private, []}, {mod_irc, []}, % Default options for mod_muc: % host: "conference." ++ ?MYNAME % access: all % access_create: all % access_admin: none (only room creator has owner privileges) {mod_muc, [{access, muc}, {access_create, muc}, {access_admin, muc_admin}]}, {mod_pubsub, []}, {mod_time, []}, {mod_last, []}, {mod_version, []} ]}. % Local Variables: % mode: erlang % End: ejabberd-16.01/win32/ejabberd_header.bmp0000644000232200023220000010271612645157216020355 0ustar debalancedebalanceBMÎ…6(–9   ·|Uÿ·}Uÿ¸}Vÿ¸~Vÿ¸~Wÿ¸Wÿ¹Xÿº€YÿºZÿº[ÿº‚\ÿºƒ\ÿ»ƒ^ÿ»„^ÿ¼…_ÿ¼†`ÿ¼†aÿ½†bÿ½‡bÿ¾ˆdÿ¾ˆeÿ¿‰fÿ¾‹fÿÀ‹hÿÀŒiÿÀjÿÁŽkÿÁŽlÿÁmÿÂmÿÃoÿÃ’qÿÃ’qÿÄ“rÿÄ”tÿÅ•uÿÅ–vÿÆ—xÿǘyÿÇ™zÿÇš{ÿÈš|ÿÈ›~ÿÉÿÊž€ÿÊŸ‚ÿË ƒÿË¡„ÿÌ¢…ÿÍ¢†ÿÍ£ˆÿÍ¥‰ÿΦ‹ÿϧŒÿϨÿЩŽÿЪÿÑ«’ÿÒ­“ÿÒ­”ÿÓ®–ÿÓ¯˜ÿÔ°˜ÿÔ±™ÿÕ³œÿÖ´ÿÖµžÿ×¶ŸÿØ·¡ÿظ£ÿÙ¹¤ÿÙº¥ÿÙ¼§ÿÚ½¨ÿÛ¾©ÿÛ¿ªÿÝÀ­ÿÝÁ­ÿݰÿÞðÿßIJÿàÆ´ÿàÆµÿàǶÿáɸÿâɹÿã˺ÿã̼ÿãͽÿäοÿåÎÀÿåÐÁÿæÑÃÿæÑÅÿæÓÆÿçÔÇÿèÕÉÿéÖÉÿé×ËÿêØÍÿëÙÍÿêÚÏÿëÛÑÿìÝÒÿìÝÓÿíÞÕÿíßÖÿîà×ÿîáØÿïâÚÿïãÚÿðäÜÿñåÝÿñæÞÿòçàÿòèàÿóéâÿóéâÿôêäÿôëåÿõìæÿõìçÿöîéÿöïêÿöïêÿöðìÿ÷ñíÿøòíÿøòîÿøôðÿøôðÿùõòÿùöòÿúöóÿúöôÿû÷õÿûøõÿüù÷ÿüù÷ÿüùùÿýûùÿýûúÿýüúÿýüûÿþýüÿþýýÿþþýÿÿþþÿÿÿþÿÿÿÿÿ¸}Uÿ·|Uÿ·~Vÿ¸}Wÿ¸~Xÿ¸Xÿ¹Xÿº€YÿºZÿº‚[ÿº‚\ÿ»‚]ÿ»ƒ]ÿ»„^ÿ¼„_ÿ¼…`ÿ¼†aÿ½‡aÿ½‡bÿ¾ˆdÿ½ˆcÿ¾ˆeÿ¾‰eÿ¾Šgÿ¾Šgÿ¿‹hÿÀŒjÿÀjÿÀŽlÿÁmÿÁnÿÂpÿÂ’pÿÃ’rÿÄ”sÿÄ”tÿÅ•uÿÅ–wÿÆ—xÿƘyÿÆ™zÿÇš{ÿÈ›}ÿÈœ~ÿÉÿÉžÿÉŸ‚ÿÊ ƒÿË¡„ÿÌ¢…ÿÌ£‡ÿͤˆÿͤŠÿϧÿШŽÿÏ©ÿѪÿÑ«’ÿÒ¬“ÿÒ­•ÿÓ¯•ÿÓ¯—ÿÔ±™ÿÕ±šÿÕ³œÿÕ´ÿÖ´žÿÖ¶Ÿÿض¡ÿظ£ÿÙ¹¤ÿÙº¥ÿÚ¼§ÿÚ¼¨ÿÛ½©ÿÛ¿«ÿÝÀ¬ÿÜÁ®ÿݯÿÞñÿßIJÿßÅ´ÿàÆµÿàǶÿáɸÿâʹÿâË»ÿã̼ÿãͽÿäξÿåÏÁÿåÐÂÿæÑÃÿæÒÄÿæÓÅÿçÔÇÿèÕÈÿéÖÊÿé×ËÿêØÍÿêÙÎÿëÚÏÿëÛÐÿìÜÒÿíÝÓÿíÞÔÿîßÖÿîàÖÿïáØÿïâÙÿðãÛÿðäÛÿñåÝÿñæÞÿòçßÿòèàÿóéáÿóéãÿôêäÿôëåÿôìæÿõíçÿõîèÿöïéÿöðëÿ÷ðìÿ÷ðìÿøñíÿøóïÿùóðÿùôñÿùôñÿúõóÿúöóÿú÷ôÿú÷õÿûøöÿûøöÿüùøÿýùøÿüûùÿýûùÿýüúÿýüûÿþýüÿþýüÿþýýÿþþþÿÿþÿÿÿÿÿÿ·}Tÿ¸}Vÿ¸}Uÿ¸~Vÿ¸Wÿ¸Xÿ¹€Yÿ¹Yÿ¹€ZÿºZÿº‚[ÿ»‚]ÿ»ƒ^ÿ»„^ÿ¼…_ÿ¼…_ÿ¼…aÿ½†aÿ¼†aÿ¼‡bÿ½‡dÿ¾ˆdÿ¼ˆfÿ½‰fÿ¾Šgÿ¾Šiÿ¿Œjÿ¿Œkÿ¿kÿÀmÿÀnÿÁpÿÁ‘qÿ‘rÿÁ“rÿÓtÿÄ•vÿÕvÿÄ–xÿÄ—xÿĘyÿÆ™{ÿÆš}ÿÇ›~ÿÈœ~ÿÈœÿÇžÿÉŸ‚ÿÊ ƒÿË¡…ÿË¢†ÿͤ‰ÿÍ¥‰ÿͦ‹ÿϨÿÏ©ŽÿЪÿÑ«‘ÿÒ¬“ÿÒ­”ÿÓ®•ÿÓ¯—ÿÓ°™ÿÕ±šÿÕ³›ÿÖ´œÿ×µžÿ×¶ ÿ×·¡ÿظ£ÿع£ÿÙº¥ÿÚ¼§ÿÚ½¨ÿÛ¾ªÿÜ¿«ÿÜÀ­ÿÝÁ­ÿݰÿÞñÿßIJÿàųÿàÆµÿàÇ·ÿáÉ·ÿáɹÿâ˺ÿã̼ÿãͽÿäÍ¿ÿäÏÁÿæÐÁÿåÑÃÿæÒÄÿæÓÆÿçÔÇÿèÕÉÿéÖÊÿé×ËÿêØÍÿêÚÎÿêÛÏÿìÛÐÿìÜÑÿìÝÓÿíÞÔÿîàÖÿîà×ÿîáØÿïâÚÿðãÚÿðäÛÿðåÝÿñåÞÿòæàÿòçáÿóéáÿóéâÿôëãÿôëåÿõìæÿôíèÿöîèÿöïéÿöïêÿ÷ðìÿ÷ñìÿ÷òîÿøòîÿøóðÿùôðÿùõòÿúõòÿúöóÿû÷ôÿû÷õÿüøöÿüø÷ÿüú÷ÿýùøÿýúùÿýûúÿýûûÿþüüÿþüüÿþýýÿþýþÿÿþþÿÿÿþÿÿÿÿÿ·|Tÿ·|Uÿ¸}Vÿ¸}Vÿ¸~Wÿ¹Xÿ¹Xÿº€Yÿ¹Zÿº[ÿº‚\ÿºƒ\ÿ»„]ÿ»ƒ^ÿ»„^ÿ»„_ÿ»…_ÿ»…aÿ»…bÿ»†cÿ»‡cÿ»†dÿ¼‡dÿ»ˆdÿ»ˆfÿ»‰fÿ»Šhÿ¼‹iÿ¼‹jÿ½Œkÿ½lÿ½lÿ¾Žnÿ¿oÿ¾pÿÀ‘rÿÀ‘rÿÀ’sÿÁ“tÿ•vÿ•wÿÖyÿ×yÿØ{ÿÙ}ÿÅ›}ÿÄ›ÿÆ€ÿÇ‚ÿÈŸ‚ÿÈŸ…ÿÊ¢‡ÿˤ‰ÿͤŠÿϧŒÿϨÿЪÿÑ«’ÿѬ“ÿÒ­•ÿÓ®•ÿÓ¯—ÿÔ°™ÿÕ±šÿÕ²œÿÖ³ÿÖµžÿ×¶Ÿÿ×·¡ÿظ£ÿع£ÿÙ»¥ÿÚ»¦ÿÚ½¨ÿÛ¾ªÿÛ¿«ÿÝÀ­ÿÝÁ®ÿÞÁ¯ÿÞðÿßIJÿ߯³ÿàÆµÿáÇ·ÿáȸÿâɹÿâË»ÿâ̼ÿã;ÿäοÿäÏÀÿåÐÂÿåÑÃÿæÒÄÿçÓÅÿèÔÇÿèÕÈÿèÖÉÿéØËÿêØÌÿëÙÎÿëÛÏÿëÛÐÿìÜÒÿíÝÓÿíÞÔÿíßÕÿîà×ÿîâØÿïâÙÿðãÚÿðäÜÿñåÜÿñæÞÿòçàÿòèàÿóèáÿóéãÿóêäÿõëåÿôìæÿõíçÿõíèÿöïêÿ÷ðêÿ÷ðìÿ÷ðíÿ÷ñíÿøòïÿøóïÿùôðÿúôòÿúõóÿúöóÿú÷ôÿû÷õÿûøöÿüø÷ÿüù÷ÿüùøÿüûùÿýûùÿýûûÿþüûÿýýüÿþýýÿþýýÿÿþþÿþÿþÿÿÿÿÿ·|Tÿ¸}Uÿ·}Uÿ¸~Vÿ¸~Xÿ¸Xÿ¹€Xÿ¹€Yÿ¹Zÿº‚[ÿº‚[ÿ»‚\ÿ»ƒ]ÿ»ƒ]ÿºƒ^ÿ»„_ÿ»„`ÿº…_ÿº„aÿº…aÿº†cÿ¹†bÿ¸‡dÿ¹†dÿ¸†cÿ¸‡dÿ·†fÿ¸‡gÿ¹ˆhÿ¹‰iÿ¹Šjÿº‹kÿº‹lÿ»mÿ¼Žnÿ¼Žoÿ½pÿ½qÿ½‘rÿ¾’tÿ¾“vÿ¿”vÿ¿”wÿÀ•yÿÀ–zÿÁ˜{ÿ™}ÿÚ~ÿÛÿÄœÿŃÿÇ …ÿÉ¢ˆÿʤ‰ÿ̦‹ÿͧÿÏ©ÿѬ’ÿÒ¬“ÿÒ­”ÿÒ¯–ÿÓ°—ÿÔ°˜ÿÕ²™ÿÕ²›ÿÖ´œÿÖµžÿÖ¶ŸÿØ·¡ÿظ¢ÿÙ¹¤ÿÙº¥ÿÚ»§ÿÚ¼©ÿÛ¾©ÿÛ¿«ÿÜÀ­ÿÜÁ®ÿÞ¯ÿÞðÿÞIJÿßÅ´ÿ߯µÿàÇ·ÿáÉ·ÿâɹÿâ˺ÿâ˼ÿãͽÿä;ÿåÏÀÿåÐÂÿæÑÃÿæÒÅÿçÓÅÿçÔÇÿèÖÉÿèÖÊÿé×ËÿêØÌÿêÚÎÿêÚÏÿëÛÑÿìÜÒÿíÝÓÿíÞÔÿíàÕÿîà×ÿïâ×ÿïâÙÿïãÚÿðäÜÿñåÝÿñæÞÿòçßÿòçàÿóèáÿóêãÿôêäÿôëåÿôìæÿôíçÿõîèÿöïéÿöïêÿ÷ðëÿ÷ñíÿøñíÿøòïÿøóðÿøôñÿùõñÿúöòÿúöóÿû÷ôÿûøõÿûøöÿûù÷ÿûù÷ÿüúøÿüúùÿýûùÿýûúÿýüûÿþýüÿþýýÿÿþýÿþþþÿþÿþÿÿÿÿÿ·}Tÿ¸}Uÿ¸}Uÿ¸~Vÿ¹Wÿ¸Wÿ¹Yÿ¹€Zÿº€Zÿº[ÿº‚\ÿ»ƒ]ÿº‚\ÿºƒ]ÿºƒ^ÿ¹ƒ]ÿ¹ƒ^ÿ¹„`ÿ·ƒ`ÿ¸ƒ`ÿ¶ƒaÿµ‚aÿ´‚aÿ³‚aÿ±‚aÿ±bÿ±aÿ±ƒcÿ±ƒdÿ²„dÿ²…eÿ²…fÿ²†gÿ³‡iÿ´‡jÿ´ˆkÿ´‰lÿµŠnÿµ‹nÿ¶Œoÿ¶pÿ·Žqÿ·sÿ¸tÿ¸uÿ¹vÿ»“wÿ»“zÿ¼•zÿ½—|ÿÀ˜ÿÛ‚ÿÅŸ…ÿÉ¢ˆÿʤŠÿͧÿΨŽÿЪÿÒ¬“ÿÒ­”ÿÓ®–ÿÓ°—ÿÔ±™ÿÔ²šÿÕ³œÿÕ´ÿ×µŸÿ×¶ŸÿØ· ÿظ¢ÿع¤ÿÙº¥ÿÚ»§ÿÛ¼¨ÿÛ½©ÿÛ¿«ÿÜÀ¬ÿÝÁ®ÿÞ¯ÿÞñÿÞIJÿßÅ´ÿàÆµÿàǶÿáɸÿâʹÿâ˺ÿã̼ÿã̽ÿäξÿåÏÁÿåÐÂÿåÑÃÿæÒÄÿçÓÆÿçÔÇÿèÕÈÿéÖÊÿé×ËÿêØÍÿêÙÎÿëÛÏÿëÛÐÿìÜÒÿíÝÓÿíÞÔÿíßÕÿîá×ÿïáØÿïâÙÿðãÚÿðäÜÿñåÝÿñæÞÿòçßÿóèáÿòèáÿóéãÿôêäÿôëåÿõìæÿôìçÿöîèÿöïéÿöðêÿ÷ðìÿøñíÿøñíÿøòîÿùóðÿùôñÿùõñÿùõóÿúöóÿú÷ôÿûøõÿûøõÿûùöÿüùøÿüùøÿüúùÿýûúÿýüúÿþüûÿþüüÿþýüÿÿþýÿþþþÿÿþþÿÿÿÿÿ·|Tÿ¸}Uÿ·~Uÿ¸~Wÿ¸~Xÿ¸Xÿ¹€Xÿº€Yÿ¹Zÿº[ÿº‚\ÿ¹‚[ÿ¹ƒ\ÿ¹‚]ÿ¹‚]ÿ¸‚^ÿ·^ÿ¶^ÿµ_ÿµ^ÿ²€_ÿ±€^ÿ°^ÿ­~]ÿ«}]ÿª}^ÿ©|]ÿª}_ÿ©}^ÿª~`ÿª~aÿª~aÿ«€cÿ¬dÿ¬‚eÿ­‚fÿ­ƒgÿ­„hÿ®„hÿ®†jÿ¯‡lÿ¯ˆmÿ¯ˆmÿ¯ˆoÿ¯‰oÿ±‹rÿ³sÿ³tÿ´uÿ·’yÿ¹”{ÿ½˜~ÿÁ›‚ÿÆž…ÿÉ¢ˆÿÊ¥ŒÿͨŽÿЫÿÒ¬“ÿÒ®•ÿÓ®–ÿÔ¯—ÿÔ±™ÿÕ±šÿÕ²œÿÕ³ÿÖ´žÿ×¶ŸÿØ·¡ÿظ¢ÿÙº¤ÿÙº¥ÿÙ»¦ÿÚ¼¨ÿÛ½ªÿÜ¿«ÿÜÀ¬ÿÝÀ­ÿÝÁ¯ÿÞðÿÞIJÿßÅ´ÿàÆµÿàÇ·ÿáȸÿâɹÿâÊ»ÿã˼ÿã̽ÿäοÿåÏÀÿåÐÂÿæÑÃÿæÒÄÿçÓÆÿèÔÇÿèÕÈÿéÖÉÿéØËÿéØÌÿëÙÎÿëÛÏÿëÜÐÿìÝÒÿíÝÓÿíÞÔÿíßÖÿîà×ÿîâØÿïâÙÿïãÚÿðäÜÿñåÝÿñæÞÿòçßÿòèáÿóéâÿóéâÿôêäÿôëåÿõìæÿõíçÿõîèÿöîêÿöðëÿ÷ðëÿ÷ñìÿøñíÿøòîÿøóïÿùôðÿùôñÿùõòÿúöóÿúöôÿû÷õÿûøöÿüù÷ÿüù÷ÿüúøÿýûùÿýûúÿýûûÿýüûÿþüüÿþýýÿþýýÿÿþþÿÿþÿÿÿÿÿÿ·|Uÿ¸}Uÿ¸}Vÿ¸~Vÿ¸Wÿ¸Wÿ¹Yÿ¹€Yÿ¹Zÿº[ÿº\ÿ¹\ÿ¹\ÿ¸‚\ÿ¸‚]ÿ·]ÿ¶€\ÿ´€]ÿ±]ÿ°~\ÿ­|\ÿ«{Zÿ§yZÿ¤wXÿ¡uWÿ tXÿžtXÿžuXÿžtXÿžuYÿtZÿžv[ÿŸw[ÿŸw]ÿ x]ÿ y_ÿ y_ÿ {`ÿ¡{bÿ¢|cÿ¢}dÿ£~eÿ£~eÿ£fÿ£€gÿ¤€iÿ¥ƒkÿ§ƒlÿ¨†nÿ¬‰qÿ°Œtÿ¶’zÿ»—~ÿÁ›‚ÿÆ ‡ÿÈ£Šÿ̧ÿÏ©ÿЫ’ÿÒ­”ÿÒ¯–ÿÓ°—ÿÓ±™ÿÕ²šÿÕ³›ÿÖ´ÿ×µžÿ×¶ ÿ×·¡ÿظ¢ÿع£ÿÙº¥ÿÚ¼¦ÿÚ½¨ÿÛ¾ªÿÜ¿«ÿÝÀ­ÿÜÁ­ÿݯÿÞñÿßIJÿàÅ´ÿàǵÿàǶÿáÈ·ÿâɹÿâË»ÿã̼ÿãͽÿäοÿåÏÁÿåÐÂÿæÑÃÿçÒÅÿçÓÆÿçÔÇÿèÕÈÿéÖÉÿé×ËÿéØÍÿêÙÍÿêÛÏÿëÛÐÿìÜÑÿíÝÓÿíÞÕÿîßÕÿîàÖÿïáØÿðâÙÿðãÛÿðäÛÿñåÝÿñæÞÿñçßÿòçàÿóéâÿóéãÿóêäÿõëåÿôìæÿõíçÿöîèÿöîêÿ÷ðêÿ÷ðìÿ÷ñíÿøñíÿøóïÿùôðÿøôñÿúôñÿúõòÿúõóÿûöôÿû÷õÿûøöÿûøöÿüù÷ÿüúøÿüúùÿýûùÿýûûÿýüûÿþýüÿþþýÿþþýÿþþýÿþÿÿÿÿÿÿÿ·|Uÿ·}Vÿ¸~Vÿ¸~Wÿ¸~Wÿ¹Xÿ¹Xÿ¹€Yÿ¹Zÿº[ÿ¹€Zÿº[ÿ¹]ÿ¹\ÿ·\ÿµ€\ÿ´~\ÿ±~[ÿ¯|[ÿ«zYÿ§xXÿ£uWÿŸsVÿ›pTÿ˜nSÿ•mRÿ“lQÿ’lQÿ‘kRÿ’lRÿ‘lSÿ‘mTÿ’nUÿ’nUÿ“nVÿ“oWÿ“pXÿ”qYÿ”qYÿ•q[ÿ•s\ÿ•t\ÿ•t]ÿ–u_ÿ—u_ÿ˜waÿ™ycÿ›{dÿ}gÿ¢€jÿ¦…nÿ¬‹tÿ´‘yÿ¼—€ÿÞ„ÿÆ¢ˆÿ˦ŽÿΨÿÑ«’ÿѬ“ÿÒ¯•ÿÓ¯—ÿÔ°™ÿÕ±šÿÕ³›ÿÖ³ÿÖµžÿ×¶ ÿØ·¡ÿظ¢ÿع¤ÿÙº¦ÿÚ»§ÿÛ¼¨ÿÛ½ªÿܾ«ÿÜÀ¬ÿÝÀ®ÿݯÿÞñÿÞIJÿßųÿàǵÿàȶÿáÈ·ÿâɹÿâ˺ÿâ˼ÿã̾ÿäξÿåÏÁÿæÐÁÿæÑÃÿæÒÅÿçÓÅÿèÔÇÿèÕÈÿéÖÉÿé×ËÿêÙÌÿêÙÍÿêÛÏÿëÛÐÿìÜÒÿìÝÓÿíÞÔÿîßÖÿïá×ÿîáØÿðâÚÿïãÚÿðäÜÿðäÝÿñæÞÿñçßÿòèàÿóéâÿôêãÿôëäÿôëåÿôìæÿõíçÿöíéÿöîêÿöïêÿ÷ðìÿ÷ñìÿ÷ñîÿøòïÿøóðÿùôðÿúõñÿùõòÿúöóÿûöôÿúøõÿûøöÿüùöÿüúøÿüúøÿýûùÿýûúÿýüûÿþüüÿþüüÿþýýÿþýþÿþþþÿÿÿÿÿÿÿÿÿ¸}Tÿ·}Vÿ¸}Vÿ¸~Wÿ¸~Wÿ¹Xÿ¹Yÿ¹€ZÿºZÿº[ÿ¹€Zÿ¹€[ÿ¸[ÿ·]ÿ¶€\ÿ³€[ÿ±~[ÿ®{YÿªyYÿ¦wVÿ¢tUÿpTÿ—mQÿ’jOÿgLÿŠeKÿ‡dJÿ†cKÿ…bJÿ…cKÿ…bLÿ…dLÿ…dNÿ†eNÿ†eOÿ‡fPÿ‡fQÿ‡gRÿ‡hSÿˆiSÿˆiTÿ‰jUÿ‰kUÿ‰kWÿŠlWÿ‹mYÿŒoZÿq]ÿ‘s^ÿ—xdÿœ}hÿ¤„nÿ­‹tÿ·”|ÿ¿›‚ÿÄ †ÿÊ¥ŒÿͨÿÑ«’ÿÒ­“ÿÓ¯•ÿÓ¯—ÿÔ±™ÿÔ±šÿÕ²›ÿÕ´ÿÖµžÿ×¶Ÿÿ×·¡ÿظ¢ÿÙ¹¤ÿÚº¦ÿÙ»§ÿÛ¼¨ÿÛ¾©ÿÜ¿«ÿÜÀ¬ÿÝÀ­ÿݰÿÞðÿßIJÿàųÿ߯µÿàȶÿáȸÿâɹÿâʺÿã̼ÿãͽÿäοÿåÏÁÿåÐÁÿæÑÃÿæÒÄÿçÓÆÿèÔÇÿèÕÈÿéÖÉÿé×ËÿêØÌÿëÙÎÿëÚÏÿëÜÑÿìÜÑÿìÞÓÿíÞÔÿîßÕÿîà×ÿïáØÿïâÙÿðãÚÿðäÜÿñåÝÿñåÞÿòçßÿòçáÿòèáÿóéãÿôêäÿôìåÿõìæÿõíçÿöîèÿõîéÿöïêÿ÷ðëÿ÷ñíÿøñîÿøòîÿùóïÿøôñÿùõñÿùõóÿúöóÿú÷ôÿû÷ôÿûøöÿûù÷ÿüù÷ÿüúøÿüúùÿýûúÿýûûÿýüûÿýüûÿþþýÿþýýÿÿþþÿÿÿþÿÿÿÿÿ·}Tÿ·}Vÿ¸~Vÿ¸~Wÿ¹Wÿ¹Xÿ¹€Yÿ¹€Yÿ¹Zÿº[ÿ¹[ÿ¹\ÿ¸€[ÿ¶€[ÿµ[ÿ²~[ÿ¯|YÿªyXÿ¦xWÿ¡tUÿœpSÿ–lPÿhLÿ‰cIÿƒ`Gÿ€]Fÿ|[DÿzZCÿyYDÿyZEÿxYEÿy[Fÿz[Gÿz\Gÿy[Gÿz\Hÿz]Iÿ{^Jÿ{^Jÿ|_Lÿ{_Lÿ|`Mÿ|aMÿ}aOÿ}bOÿ~cPÿcQÿ‚gTÿ…jWÿŒo\ÿ“uaÿœ~iÿ§†pÿ°xÿ»˜€ÿž…ÿȤŠÿ̧ŽÿЪ‘ÿѬ”ÿÒ¯–ÿÔ°—ÿÓ±™ÿÕ²šÿÕ³œÿÖ´œÿÖµŸÿ×µŸÿØ·¡ÿظ¢ÿع¤ÿÙº¥ÿÚ»¦ÿÛ¼¨ÿÛ¾©ÿÛ¿«ÿÜ¿¬ÿÜÀ®ÿݯÿÞñÿßųÿßųÿàÆµÿàǶÿáÈ·ÿáɹÿâË»ÿã˼ÿä̽ÿäοÿåÏÁÿåÐÂÿæÑÃÿæÒÄÿæÓÅÿçÔÇÿèÕÈÿéÖÊÿé×ËÿêØÍÿëÙÎÿëÛÏÿëÛÐÿìÜÒÿíÝÓÿíÞÔÿíàÕÿîàÖÿïâØÿïâÚÿïãÚÿðäÛÿñäÝÿñæÞÿñæßÿóèàÿóèâÿóêãÿôëäÿõëåÿôìæÿõíèÿöîéÿõîêÿöðëÿ÷ðìÿ÷ðìÿøòíÿøòîÿùôïÿøôðÿùôòÿúõòÿúöóÿú÷ôÿú÷õÿüøöÿüøöÿüùøÿýúøÿýûùÿýûúÿýûûÿýüûÿýýüÿýýüÿþþýÿÿþþÿÿþþÿÿÿÿÿ·}Uÿ·}Uÿ·}Vÿ¸~Vÿ¸~Wÿ¸Xÿ¹€Xÿ¹€Yÿ¹€Zÿº[ÿ¹[ÿ·[ÿ¸€\ÿ¶€[ÿµ€[ÿ±}Zÿ®|Yÿ©yXÿ¤uUÿŸrSÿ˜nPÿ‘hNÿŠdJÿƒ_Gÿ}[DÿyYBÿtUAÿsU@ÿqT@ÿrT@ÿqT@ÿqTAÿrUBÿrUCÿrUCÿsWDÿsWDÿsXFÿtXFÿtYGÿsYGÿtZHÿt[Iÿu[Jÿv\Jÿv]Kÿx^Mÿ{aPÿeSÿ†jWÿŒp]ÿ—zfÿ£ƒnÿ®vÿ¹–~ÿÁ„ÿÈ£Šÿ̦ÿϪ‘ÿѬ“ÿÒ®•ÿÓ°—ÿÔ±˜ÿÕ²šÿÕ³œÿÕ³ÿ×µžÿÖ¶Ÿÿ×·¡ÿظ¢ÿع¤ÿÙ»¥ÿÚ»¦ÿÚ½¨ÿÛ¾©ÿÜ¿«ÿÝÀ­ÿÜÀ®ÿÞ°ÿÞðÿßijÿàÅ´ÿàÆµÿàȶÿáɸÿáɹÿâÊ»ÿã˼ÿä̽ÿäοÿåÏÀÿåÐÂÿæÑÃÿæÒÄÿçÓÆÿèÔÇÿèÕÈÿéÖÉÿé×ËÿêØÌÿêÚÍÿëÛÏÿëÜÑÿìÜÑÿíÝÒÿíÞÔÿîßÖÿîà×ÿîáØÿïâÙÿðãÚÿðäÛÿðåÝÿñæÞÿòæßÿòçáÿóéâÿóéãÿóëäÿôëåÿõìæÿõíçÿõîéÿöîêÿöïêÿöðìÿ÷ñìÿøñîÿøòîÿùóïÿøôðÿùôòÿùöóÿúöóÿú÷ôÿú÷õÿûøöÿüø÷ÿüù÷ÿüúøÿýúùÿýûùÿþüúÿýüûÿþüüÿýýüÿþþýÿÿþþÿÿÿþÿÿÿÿÿ·|Tÿ·|Uÿ¸~Vÿ¸~Wÿ¹~Wÿ¹Xÿ¹€Xÿ¹€Yÿ¹€Zÿº[ÿ¸€Zÿ·€Zÿ·€\ÿµ[ÿ³[ÿ°|Yÿ¬zYÿ§vVÿ¢sUÿœpRÿ•kOÿfJÿ…aGÿ}[DÿvVAÿrT?ÿnP=ÿlO<ÿiN;ÿiN;ÿiO<ÿjO=ÿjP>ÿjP>ÿjP>ÿkQ?ÿkQ@ÿkRAÿkRAÿkSBÿlSBÿmTCÿmUDÿmUDÿmVEÿnVFÿpXGÿt[Kÿw^MÿeTÿ‡lYÿ’uaÿŸkÿ¬Štÿ·”}ÿ¿›ƒÿÇ¢‰ÿ̧ÿϪ‘ÿѬ“ÿÓ¯•ÿÓ¯—ÿÓ±˜ÿÔ²šÿÕ³›ÿÕ´ÿÖ´žÿ×µŸÿØ·¡ÿظ£ÿع¤ÿÙº¥ÿÚ»§ÿÚ¼¨ÿÛ¾©ÿÜ¿ªÿÝÀ­ÿÝÀ®ÿݰÿÞðÿÞIJÿßųÿ߯´ÿàǶÿáȸÿáʹÿâÊ»ÿã̼ÿä̾ÿäοÿåÏÀÿåÐÁÿæÑÃÿæÒÅÿçÓÅÿçÔÇÿèÕÈÿéÖÉÿéØËÿéÙÍÿêÚÎÿëÚÏÿìÛÑÿëÜÒÿìÞÓÿíÞÔÿîßÕÿîàÖÿïáØÿïâÚÿðãÚÿñäÜÿðåÝÿñæÞÿñçßÿòèáÿòèâÿóêãÿôêäÿôëåÿõìæÿõíçÿõíèÿöîéÿöïêÿ÷ðìÿ÷ñíÿøñíÿøòïÿøóïÿùóñÿùôñÿùöòÿúöóÿú÷ôÿûøõÿüøöÿûøöÿüù÷ÿýúøÿüúùÿüûùÿþûûÿþüûÿþüüÿþýýÿþþýÿþþýÿÿÿþÿÿÿÿÿ·}Uÿ·}Uÿ¸}Vÿ¸~Vÿ¸~Wÿ¸Xÿ¹€Yÿ¹€YÿºZÿº[ÿ¸€[ÿ·Zÿ·[ÿµ€[ÿ³~Yÿ°|Yÿ¬yXÿ¦vVÿ¡sTÿšnQÿ”jNÿ‹eJÿƒ^Fÿ{YCÿsS?ÿoQ=ÿjM:ÿiM:ÿgL:ÿfL:ÿfL:ÿfL;ÿfM;ÿgM<ÿfM<ÿhN=ÿgO>ÿhO>ÿhO?ÿiQ@ÿiP@ÿiRAÿiQAÿiRBÿjSCÿkTDÿmUEÿpYHÿs\Kÿ|cRÿƒiXÿt`ÿ~iÿª‰tÿ·”}ÿ¾›‚ÿÇ¢‰ÿ̦ÿϪ‘ÿѬ”ÿÓ®–ÿÓ¯—ÿÔ°™ÿÕ²šÿÕ³›ÿÖ´ÿ×´Ÿÿ×¶ ÿØ·¡ÿظ£ÿÙ¹¤ÿÙº¥ÿÚ¼§ÿÛ½¨ÿÛ½©ÿÛ¾«ÿÜÀ­ÿÝÀ®ÿÞ¯ÿÞñÿßIJÿßųÿàÆµÿáȶÿáÉ·ÿâʹÿâÊ»ÿã̼ÿã;ÿäοÿåÏÀÿåÐÁÿæÑÃÿæÒÅÿçÓÆÿçÔÇÿèÕÈÿèÖÊÿé×ËÿêØÌÿêÙÎÿêÛÏÿìÛÐÿìÜÑÿíÞÓÿíÞÔÿîßÖÿîàÖÿïáØÿïâÙÿðãÛÿðäÜÿðåÝÿñåÞÿñçßÿòèáÿóéâÿóéãÿôëäÿôëåÿôìæÿõíçÿõîéÿöîéÿöïëÿ÷ðëÿ÷ñìÿøñîÿøòîÿøóïÿùôðÿùôòÿúõòÿúöóÿú÷õÿú÷õÿûøöÿüùöÿüùøÿüúøÿüûùÿýûúÿýûûÿýüûÿþýüÿþýýÿþýýÿþþþÿÿÿÿÿÿÿÿÿ·}Uÿ¸}Uÿ·~Vÿ¸~Vÿ¹~Wÿ¹Xÿ¹€Xÿº€Yÿ¹Zÿº[ÿ¹€[ÿ·€[ÿ·€[ÿµ\ÿ³~ZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmVFÿpYJÿx`Oÿ€fUÿŽq_ÿ›}iÿ¨ˆrÿ¶”|ÿ¿›‚ÿÇ¢‰ÿ˦ÿÏ©‘ÿѬ“ÿÓ®–ÿÓ¯—ÿÔ±™ÿÕ²šÿÕ³›ÿÕ´ÿÖµžÿ×¶ŸÿØ·¡ÿظ¢ÿÙ¹¤ÿÙº¥ÿÙ¼¦ÿÚ¼¨ÿÛ¾©ÿÜ¿«ÿÜÀ¬ÿÜÁ®ÿݯÿÞñÿÞIJÿßÅ´ÿàÆµÿàǶÿáȸÿâɹÿâË»ÿã˼ÿãͽÿäοÿäÏÀÿåÐÁÿæÑÃÿæÒÄÿçÓÆÿèÔÇÿèÕÈÿèÖÉÿé×ËÿéØÌÿêÙÎÿëÚÏÿìÛÐÿìÜÑÿìÝÓÿíÞÔÿíßÖÿîá×ÿîáØÿïâÙÿðãÛÿðäÛÿðäÝÿòåÞÿòçßÿòçáÿóéáÿóéãÿôëäÿôëåÿôìæÿõìçÿõíèÿöîéÿöïêÿöðëÿ÷ñìÿøñíÿøòïÿùóïÿùôðÿùôñÿùöóÿúöóÿû÷ôÿû÷õÿûøöÿüùöÿüù÷ÿüúùÿýûùÿýûùÿýûúÿýüüÿþüûÿþýüÿÿþþÿþþýÿÿþÿÿÿÿÿÿ·}Uÿ·}Vÿ·~Vÿ¸~Wÿ¹~Wÿ¹Xÿ¹€Yÿ¹€YÿºZÿºZÿ¸€Zÿ¸[ÿ·€\ÿµ~[ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿlUFÿpXIÿx_Oÿ€fUÿŽq_ÿ›|gÿ¨ˆrÿµ“{ÿ¾›ƒÿÇ¢‰ÿ˦ÿϪ‘ÿÒ¬”ÿÓ®–ÿÓ°—ÿÔ°™ÿÔ±šÿÕ³›ÿÕ´œÿ×µžÿ×µ ÿ×·¡ÿظ£ÿÙ¹¤ÿÙº¦ÿÚ»§ÿÚ¼¨ÿÛ¾©ÿܾ«ÿÝ¿¬ÿÝÁ®ÿÞ¯ÿÞðÿßIJÿßųÿàÆµÿàǶÿàȸÿâɹÿâ˺ÿã˼ÿä;ÿäοÿåÎÀÿåÐÂÿæÑÃÿæÒÅÿçÓÅÿçÔÇÿèÕÈÿé×Êÿé×ËÿêØÌÿêÙÎÿêÚÏÿëÛÑÿìÜÒÿíÝÓÿíÞÔÿîßÕÿîà×ÿïáØÿïâÙÿïãÚÿðäÜÿñäÝÿòåÞÿòçßÿòçáÿòèâÿóéãÿôêäÿôëåÿôìæÿõíèÿöíèÿöïéÿ÷ïëÿ÷ðìÿ÷ñìÿ÷ñîÿøòïÿøóïÿùôðÿùôñÿúõòÿúöóÿú÷ôÿûøõÿûøöÿüùöÿüùøÿüùùÿýûùÿýúúÿýûûÿþüûÿýýüÿþýýÿþþýÿþþþÿÿÿþÿÿÿÿÿ·|Tÿ¸}Uÿ·~Vÿ¸~Vÿ¹~Wÿ¹Xÿ¸Xÿ¹€Zÿº€Zÿº[ÿ¸€[ÿ¸€Zÿ·€[ÿµ[ÿ³}Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿjTEÿoWHÿw_NÿfTÿŒq^ÿš|hÿ§‡qÿµ’|ÿ¾›‚ÿÇ¢‰ÿ˦ÿЪ‘ÿѬ“ÿÓ¯•ÿÓ°—ÿÓ°˜ÿÕ²šÿÖ²›ÿÕ³ÿ×µžÿ×¶ ÿØ·¡ÿظ¢ÿÙ¹£ÿÙ»¥ÿÚ»§ÿÚ½¨ÿÛ¾©ÿܾ«ÿÝÀ­ÿÝÁ®ÿݯÿÞñÿßIJÿßųÿàÆµÿáÇ·ÿáɸÿâʹÿâË»ÿã̼ÿãͽÿäÍ¿ÿåÏÀÿåÐÂÿåÑÃÿæÒÄÿçÓÅÿèÔÇÿèÕÈÿé×Éÿé×ËÿêØÌÿêÙÍÿêÛÏÿëÛÐÿìÜÑÿìÝÓÿíÞÕÿíàÖÿîàÖÿîáØÿïâÙÿðãÚÿðäÜÿðåÝÿñæÞÿòçßÿòçàÿòèâÿóéâÿôêãÿôëæÿôìæÿõíèÿõîèÿöîéÿöïêÿ÷ðìÿ÷ñìÿøñíÿøòïÿùóðÿøóðÿùõñÿùõóÿúöôÿú÷ôÿûøõÿûøöÿûø÷ÿüú÷ÿüúøÿüûùÿýûùÿýûûÿýüûÿýýüÿþýüÿþþýÿþþýÿÿþþÿÿÿÿÿ·|Tÿ¸}Uÿ¸~Vÿ¸~Vÿ¸~Wÿ¸Xÿ¹Yÿ¹€ZÿºZÿº‚[ÿ¸€[ÿ·€Zÿ·€[ÿµ~[ÿ²}Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿjTEÿoWIÿw_NÿfTÿŒq^ÿš|hÿ¨‡qÿµ’|ÿ½›ƒÿÇ¢‰ÿ˧ÿЪ‘ÿѬ“ÿÓ®–ÿÔ¯—ÿÔ°˜ÿÕ±šÿÕ²œÿÕ³œÿ×µžÿ×¶ ÿ×·¡ÿظ¢ÿÙ¹¤ÿÙº¥ÿÙ»§ÿÚ¼¨ÿÛ½©ÿÛ¿«ÿÜÀ¬ÿÜÁ®ÿݯÿÞñÿßIJÿ߯´ÿ߯µÿáÈ·ÿáÈ·ÿâɹÿâ˺ÿã̼ÿã;ÿäοÿåÏÀÿåÐÁÿæÑÃÿçÒÅÿçÓÅÿçÔÇÿèÕÈÿéÖÉÿé×ËÿêØÌÿêÙÎÿëÚÏÿëÛÐÿìÜÒÿìÝÓÿíÞÔÿíàÕÿîàÖÿïáØÿïâÙÿðãÛÿñäÜÿñåÝÿñæÞÿòæàÿòçàÿóéâÿóêâÿôêäÿôëåÿõìæÿõíèÿõíéÿöîéÿöïêÿ÷ðìÿ÷ñìÿ÷òíÿøòïÿùóïÿùôñÿùõòÿúöóÿúõóÿúöôÿú÷õÿûøöÿûù÷ÿüù÷ÿüùøÿýûùÿýûùÿýûûÿþüûÿþüüÿþýüÿþþýÿÿþþÿÿþþÿÿÿÿÿ·|Uÿ¸|Vÿ¸~Vÿ¸~Vÿ¸~Wÿ¸Wÿ¹€Yÿ¹€YÿºZÿºZÿ¹[ÿ¸Zÿ·€[ÿ¶~[ÿ³}Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿkTEÿoXIÿw_NÿfTÿq^ÿš|gÿ¨‡qÿµ’{ÿ¾›‚ÿÇ¢‰ÿ˦ÿϪ‘ÿѬ”ÿÒ¯–ÿÓ¯—ÿÔ°˜ÿÔ±šÿÕ²œÿÖ´ÿÖµžÿ×¶ ÿ×·¡ÿظ¢ÿغ£ÿÙº¥ÿÚ¼¦ÿÚ¼¨ÿÛ¾ªÿÜ¿ªÿÜÀ¬ÿÝÁ®ÿÞ¯ÿÞðÿßIJÿßųÿàÆµÿáÇ·ÿáɸÿáɹÿâÊ»ÿâ̼ÿä;ÿã;ÿäÏÀÿåÐÁÿåÑÃÿæÒÄÿçÓÆÿèÔÇÿèÕÈÿéÖÊÿé×ËÿêØÍÿêÙÍÿêÚÏÿìÛÐÿëÝÒÿìÝÓÿíÞÔÿíßÕÿîà×ÿïáØÿïâÙÿðãÛÿðäÜÿðåÝÿñæÞÿòçßÿòçàÿóéâÿóéãÿôêãÿôëåÿõìæÿõíèÿõîéÿöïéÿöïëÿ÷ðìÿøñìÿøòîÿøóîÿøóïÿùôðÿùõñÿúöòÿúõôÿû÷ôÿûøõÿûøõÿûù÷ÿûù÷ÿüúøÿüûùÿüûúÿýûûÿýüûÿþýüÿþýüÿþþýÿþþþÿÿþþÿÿÿÿÿ·}Tÿ·}Uÿ¸}Vÿ¸~Vÿ¸Wÿ¹Xÿ¹Xÿ¹€Zÿ¹ZÿºZÿ¸€Zÿ·€Zÿ·€[ÿ¶~[ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿÿÿÿÿkTEÿoXHÿw^NÿfTÿŒq^ÿš|hÿ¨ˆrÿµ“|ÿ¾›ƒÿÇ¢‰ÿ˦ÿϪÿѬ“ÿÒ®–ÿÔ°˜ÿÔ±˜ÿÔ²šÿÕ³œÿÖ´ÿÖµžÿ×¶ ÿØ·¡ÿظ£ÿع¤ÿÙº¥ÿÚ¼§ÿÛ¼¨ÿÛ¾ªÿÛ¿«ÿÜÀ¬ÿÜÁ®ÿÞ¯ÿÞñÿÞIJÿßÅ´ÿàÆµÿàȶÿáȸÿâʹÿâË»ÿã˼ÿãͽÿäοÿäÎÁÿåÐÁÿåÑÃÿçÒÄÿçÓÅÿèÔÆÿèÕÈÿèÖÊÿé×ËÿéØÌÿêÙÍÿëÚÏÿìÛÐÿëÝÒÿíÝÓÿíÞÔÿîßÖÿîà×ÿïáØÿðâÚÿïãÚÿðäÛÿðåÝÿñæÞÿñçàÿòèàÿòèáÿóéâÿôêäÿôëåÿõìæÿõíèÿõîéÿöîêÿöïêÿ÷ðëÿ÷ñíÿ÷òíÿøóîÿøóïÿùôñÿúôòÿùõóÿúöóÿú÷ôÿû÷õÿüøöÿüùöÿüù÷ÿüùøÿüûùÿýûúÿýüúÿþüûÿþüüÿþýüÿþþýÿþþþÿÿÿÿÿÿÿÿÿ·}Uÿ¸}Vÿ¸}Vÿ¹~Wÿ¸~Wÿ¹Wÿ¹€Yÿ¹€Yÿ¹Zÿº[ÿ¸€Zÿ·€[ÿ·€[ÿµ[ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿÿÿÿÿjTEÿnWGÿv^NÿdTÿq^ÿš|hÿ¨ˆrÿµ“{ÿ¾›ƒÿÇ¢‰ÿ˧ÿΩ‘ÿѬ“ÿÓ¯•ÿÓ¯—ÿÔ°™ÿÕ±šÿÕ³›ÿÕ³ÿ×µžÿ×¶ ÿ×·¡ÿظ¢ÿع¤ÿÙº¦ÿÚ¼¦ÿÚ½¨ÿÛ¾©ÿÛ¿«ÿÜÀ­ÿÜÁ®ÿݯÿÞðÿÞIJÿ߯³ÿàÆµÿàǶÿáɸÿâʹÿâ˺ÿã̼ÿäͽÿäοÿåÏÁÿåÐÁÿæÑÂÿæÒÄÿçÓÆÿèÔÇÿèÕÈÿéÖÊÿê×ËÿéØÌÿêÙÍÿêÚÏÿëÛÐÿëÜÒÿìÞÓÿíÞÔÿíßÖÿîà×ÿîáØÿïâÙÿðãÛÿðäÜÿñåÝÿñæÞÿñçßÿóèáÿòéáÿóêãÿóêäÿôëåÿõìæÿõíçÿõîéÿöîéÿ÷ðëÿ÷ðìÿ÷ñíÿøòîÿøòîÿøóðÿøôñÿùõòÿùöóÿúöóÿú÷ôÿû÷õÿûøöÿüøöÿüúøÿüùøÿýûùÿýûúÿýûúÿýüûÿýüüÿþýýÿþþýÿþþþÿÿÿÿÿÿÿÿÿ·|Uÿ·}Uÿ¸}Uÿ¸~Vÿ¸Xÿ¹Xÿ¹Yÿ¹€YÿºZÿ¹[ÿ¸€[ÿ¸[ÿ·€[ÿµ[ÿ²~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿÿÿÿÿjTEÿoXHÿw^NÿfTÿp^ÿš{hÿ¨ˆrÿµ“|ÿ¾›‚ÿÇ¢‰ÿ˦ÿЪ‘ÿѬ“ÿÒ®•ÿÔ¯—ÿÔ±™ÿÔ±šÿÕ²œÿÕ´ÿÖµžÿ×¶ ÿØ·¡ÿظ¢ÿÙ¹¤ÿÙ»¥ÿÚ»¦ÿÛ½©ÿÛ½©ÿÛ¾«ÿÜÀ­ÿÝÀ®ÿݯÿÞñÿßIJÿßÅ´ÿàǵÿàÈ·ÿáȸÿâʹÿã˺ÿã˼ÿã;ÿäοÿåÎÀÿæÐÂÿæÑÃÿæÒÅÿçÓÆÿçÔÇÿèÕÉÿèÖÉÿé×ËÿêØÍÿêÙÎÿëÚÏÿëÛÐÿìÜÑÿìÝÓÿíÞÕÿîßÖÿîà×ÿïáØÿïâÚÿïãÚÿðäÜÿñåÝÿñæÞÿòçßÿòèáÿóéâÿóéãÿóêãÿôëåÿõìæÿõìçÿöîéÿöîéÿöïêÿ÷ðëÿøðìÿ÷ñîÿøóïÿùóïÿùôñÿùõòÿúõòÿúöôÿú÷ôÿú÷õÿûøöÿüø÷ÿüù÷ÿüúùÿüûùÿýûúÿýûúÿþüûÿýüüÿþýüÿþýýÿþþþÿÿÿþÿÿÿÿÿ·|Uÿ¸}Uÿ¸}Vÿ¸~Wÿ¸~Wÿ¹Xÿ¹Xÿ¹€Yÿº€Zÿº[ÿ¸€Zÿ¸Zÿ·[ÿ¶[ÿ²~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿÿÿÿÿjTEÿnXHÿw^NÿfTÿŒq^ÿš|hÿ¨‡rÿµ’{ÿ¾›ƒÿÇ¢‰ÿ˦ÿϪ‘ÿѬ“ÿÒ¯–ÿÔ¯—ÿÔ±˜ÿÔ²šÿÕ³›ÿÖ³ÿÖµžÿ×µŸÿ×·¡ÿظ¢ÿÙ¹¤ÿÙº¥ÿÚ¼§ÿÚ½¨ÿÛ¾ªÿÛ¾«ÿÜÀ­ÿÝÁ®ÿÞ¯ÿÞðÿÞIJÿßųÿàÆµÿàȶÿáȸÿâʹÿã˺ÿã˼ÿãͽÿäοÿäÏÀÿåÐÂÿæÑÃÿçÒÄÿçÓÆÿçÔÆÿèÕÉÿéÖÉÿéØËÿêØÌÿêÙÍÿëÚÏÿëÜÐÿìÜÒÿíÞÓÿíßÔÿîßÕÿîà×ÿïáØÿïâÚÿïãÚÿðãÜÿñåÝÿòæÞÿòçßÿòèàÿóèáÿóéãÿóêäÿôëåÿõìæÿõìèÿõîèÿöïéÿöðêÿ÷ðìÿ÷ñìÿ÷òíÿøòîÿùóïÿùôðÿùôñÿúõòÿúõóÿú÷ôÿû÷õÿûøõÿûø÷ÿüù÷ÿüúøÿüûùÿýûúÿýüûÿýüûÿýüüÿþýýÿÿþýÿþþþÿÿÿþÿÿÿÿÿ·|Tÿ¸}Uÿ¸}Uÿ¸~Wÿ¸Wÿ¹Xÿ¹Xÿ¹€Yÿº€Zÿº[ÿ¸Zÿ·Zÿ·€[ÿµ~[ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿÿÿÿÿkTEÿoXHÿw_NÿfTÿq^ÿš{hÿ¨‡rÿµ’{ÿ¾›ƒÿÇ¢‰ÿ˦ÿϪÿѬ“ÿÓ®–ÿÓ¯—ÿÔ°˜ÿÔ²šÿÕ³œÿÖ´ÿÖµžÿ×¶ ÿØ·¡ÿظ£ÿÙ¹¤ÿÙ»¥ÿÙ»§ÿÛ¼¨ÿÛ¾ªÿܾªÿÝ¿­ÿÝÁ­ÿÞÁ¯ÿÞñÿÞIJÿßųÿàǵÿàÇ·ÿáȸÿáʺÿãË»ÿã̼ÿãͽÿäοÿåÏÁÿåÐÂÿæÑÃÿæÒÄÿçÓÆÿçÔÇÿèÕÈÿéÖÉÿéØËÿéØÍÿëÙÎÿëÛÏÿëÛÐÿìÝÒÿìÞÓÿíÞÔÿîßÕÿîà×ÿîá×ÿïâÙÿðãÛÿðãÜÿñäÜÿòåÞÿñçßÿòèàÿóéâÿóéãÿóêäÿôìåÿõìæÿõíçÿöíèÿöîéÿöïêÿ÷ðìÿ÷ñìÿøñíÿøòîÿùóðÿøôðÿúõòÿúõòÿúöóÿû÷ôÿûøõÿûøöÿüøöÿüù÷ÿýúøÿüúùÿýûúÿýüúÿýüûÿþüüÿþýýÿþþýÿÿþýÿþÿÿÿÿÿÿÿ¸|Uÿ¸}Vÿ¸~Vÿ¸~Vÿ¸~Wÿ¹~Xÿ¹€Yÿ¹€YÿºZÿº‚[ÿ¸€Zÿ·€[ÿ·€\ÿµ\ÿ²~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿÿÿÿÿjTEÿnXHÿw^NÿfTÿŒq^ÿš|hÿ§‡qÿµ’{ÿ½›ƒÿÇ£‰ÿ˦ÿЪ‘ÿѬ”ÿÓ¯•ÿÓ¯—ÿÔ±˜ÿÔ±šÿÕ³›ÿÕ³ÿÖµžÿ×µ ÿ×·¡ÿظ¢ÿÙ¹¤ÿÙ»¥ÿÚ»¦ÿÛ¼¨ÿÛ¾©ÿÛ¾«ÿÜ¿¬ÿÝÁ®ÿݯÿÞðÿÞIJÿßųÿàÆµÿàǶÿáÉ·ÿâʹÿâË»ÿã̼ÿãͽÿäξÿäÎÀÿåÐÂÿåÑÃÿæÒÅÿçÓÆÿçÔÇÿèÕÉÿéÖÊÿé×ËÿéÙÌÿëÙÎÿêÚÏÿìÜÐÿìÝÑÿìÝÓÿíßÔÿíßÕÿîà×ÿîáØÿïâÙÿðãÚÿðãÛÿñåÝÿñæÞÿòçàÿòçáÿóéâÿóéãÿóêäÿôëåÿõìæÿõíçÿöíèÿöïéÿöïêÿöðëÿ÷ñíÿøòíÿøòïÿøóïÿùóðÿùôñÿùõòÿúöôÿúöôÿûøõÿûøöÿûø÷ÿüùøÿüúùÿüúùÿýûúÿýûûÿþüûÿýýüÿþýýÿÿýýÿÿþþÿÿÿþÿÿÿÿÿ·}Tÿ·}Uÿ¸}Vÿ¹~Wÿ¸~Wÿ¹Xÿ¹Xÿ¹€Yÿ¹Zÿº[ÿ¸€[ÿ¸[ÿ·€[ÿ¶[ÿ³Yÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿkTEÿoXHÿw_NÿfTÿŒq^ÿš|hÿ¨ˆrÿµ“{ÿ¾›ƒÿÇ¢‰ÿ˦ÿЪ‘ÿѬ”ÿÓ®•ÿÓ¯—ÿÔ°™ÿÕ²šÿÕ³œÿÖ´ÿÖ´žÿ×¶ ÿØ· ÿظ¢ÿÙ¹¤ÿÙº¦ÿÚ»§ÿÚ¼¨ÿÛ¾©ÿÜ¿«ÿÜÀ¬ÿÝÁ®ÿݯÿÞñÿßIJÿàÆ³ÿàÆ´ÿáǶÿáɸÿáɹÿãʺÿã̼ÿä;ÿäξÿåÏÀÿåÏÂÿæÑÃÿæÒÄÿçÓÆÿçÔÇÿèÖÈÿéÖÊÿéØËÿêØÌÿêÚÎÿëÚÏÿëÛÐÿìÝÒÿíÝÒÿíßÔÿîßÖÿîà×ÿîáØÿïãÙÿðãÚÿðäÜÿðåÜÿñåÞÿòæßÿóçáÿóéâÿóéãÿôëäÿôìåÿôëæÿõíçÿõîéÿöîéÿöïêÿ÷ðëÿ÷ñìÿøñíÿøòïÿùóïÿùôðÿúõòÿúõòÿúöóÿú÷ôÿû÷õÿûøõÿüùöÿüù÷ÿüúùÿýûùÿýûúÿýüûÿýüûÿþüüÿþýüÿÿþýÿþþýÿÿþÿÿÿÿÿÿ¸|Uÿ¸}Uÿ¸}Uÿ¸~Wÿ¹~Wÿ¸Xÿ¹€Xÿ¹€Zÿ¹Zÿº[ÿ¸€[ÿ¸€Zÿ·€\ÿµ[ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿjTEÿnWGÿv^NÿdTÿŒq^ÿš|gÿ¨ˆsÿµ“{ÿ¾›‚ÿÇ£‰ÿ˦ÿÏ©‘ÿѬ“ÿÓ®–ÿÓ¯—ÿÓ±™ÿÕ²šÿÕ³›ÿÖ³ÿÖµžÿÖ¶ ÿØ·¡ÿظ¢ÿÙº¤ÿÙº¥ÿÚ¼¦ÿÚ½¨ÿÛ½©ÿÛ¿«ÿÜ¿¬ÿÜÁ®ÿÞ¯ÿÞñÿßIJÿ߯´ÿàÆµÿáǶÿáȸÿâɹÿãÊ»ÿãÌ»ÿãͽÿäοÿäÏÀÿåÐÂÿåÑÂÿæÒÄÿçÓÆÿçÔÇÿèÕÈÿèÖÉÿé×ËÿêØÌÿëÙÍÿëÚÏÿëÛÐÿìÜÒÿíÝÓÿíßÕÿîßÖÿîà×ÿîáØÿïâÙÿïãÛÿðäÜÿñåÜÿñåÞÿñçßÿòçáÿóèâÿóéãÿôëäÿôëåÿôìæÿõíçÿöîèÿöïéÿöïêÿöðëÿ÷ñíÿ÷òîÿøóîÿùóïÿùôñÿúõòÿúõòÿúöôÿû÷ôÿû÷õÿû÷õÿüù÷ÿüù÷ÿýúøÿüûùÿýûúÿýûûÿýüüÿþüüÿþýüÿþþýÿÿþþÿÿÿþÿÿÿÿÿ·}Tÿ·}Uÿ¸~Vÿ¸~Wÿ¹~Wÿ¹Xÿ¹€Xÿº€Yÿ¹€Zÿº[ÿ¸€[ÿ¸€Zÿ·€\ÿ¶~[ÿ²~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿjTEÿoXHÿw_NÿeTÿŒp^ÿš|gÿ¨ˆrÿµ“{ÿ¾›ƒÿÇ¢‰ÿ˦ÿϪ‘ÿѬ“ÿÓ®–ÿÓ¯—ÿÔ±˜ÿÔ²šÿÕ²›ÿÖ³œÿÖµžÿ×¶ŸÿØ·¡ÿظ¢ÿع¤ÿÙ»¦ÿÚ»§ÿÛ¼¨ÿÛ½©ÿÛ¾«ÿÜÀ¬ÿÝÁ®ÿݯÿÞñÿÞIJÿßųÿàÆ´ÿàÇ·ÿáɸÿáʹÿâË»ÿã˼ÿã̽ÿäÍ¿ÿäÏÀÿåÐÂÿæÑÃÿæÒÄÿçÓÆÿçÔÇÿèÕÈÿèÖÊÿé×ËÿêØÌÿêÚÎÿëÚÏÿëÛÐÿìÜÒÿíÝÓÿíÞÕÿîßÕÿîà×ÿïáØÿïâÙÿðãÛÿðäÜÿðåÜÿòåÞÿòæßÿòèàÿóéâÿóéãÿóêäÿõëåÿôìçÿõíçÿöíèÿõîêÿ÷ïêÿ÷ñìÿ÷ñìÿ÷ñîÿøòîÿøóðÿøôñÿùôòÿúõòÿúöóÿû÷ôÿûøõÿûøöÿûù÷ÿüú÷ÿüúøÿüúùÿýûúÿýüûÿþüûÿýýüÿþýüÿþýýÿþþýÿÿÿþÿÿÿÿÿ·|Uÿ·}Vÿ¸}Vÿ¸~Wÿ¸Xÿ¸Xÿ¸Yÿ¹€Yÿ¹€Zÿº[ÿ¸€[ÿ·€Zÿ·€[ÿ¶\ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿjTEÿoXIÿw_NÿfTÿq^ÿ›|hÿ¨‡qÿµ’{ÿ½›ƒÿÇ¢‰ÿ˦ÿЪ‘ÿѬ”ÿÒ®•ÿÓ°—ÿÔ°˜ÿÔ±šÿÕ²œÿÕ³ÿÖµžÿ×¶Ÿÿ×·¡ÿظ¢ÿÙ¹¤ÿÚº¥ÿÚ¼¦ÿÚ½¨ÿÛ¾©ÿÛ¾«ÿÜÀ¬ÿÜÁ­ÿݯÿÞðÿßIJÿßųÿàǵÿàȶÿáÉ·ÿâɹÿâ˺ÿã˼ÿä;ÿäÍ¿ÿåÏÀÿåÐÁÿæÑÃÿæÒÅÿçÓÆÿçÔÇÿèÕÈÿè×Éÿé×ËÿéÙÌÿêÙÎÿëÚÏÿìÜÐÿìÝÒÿìÝÓÿíÞÕÿîßÕÿîà×ÿïáØÿïâÚÿïãÛÿñãÜÿðäÝÿñæÞÿñçßÿòèáÿóèáÿóéãÿôêãÿôìåÿôìæÿõíçÿõîéÿõïéÿöïëÿ÷ðëÿ÷ðíÿøñîÿøòïÿøóïÿùóðÿúõñÿùõóÿúöóÿû÷ôÿû÷õÿûøöÿûøöÿüú÷ÿüúøÿüúùÿýûùÿýüûÿþüüÿþüüÿþýüÿÿýýÿÿþþÿÿÿþÿÿÿÿÿ·|Uÿ¸}Uÿ¸~Vÿ¸~Wÿ¸Wÿ¸Xÿ¹Yÿ¹€Yÿ¹€Zÿº[ÿ¸€[ÿ·[ÿ·€[ÿµ[ÿ³}Zÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿjTEÿnXHÿw_NÿfTÿŒq^ÿš|hÿ¨‡rÿµ’{ÿ¾›‚ÿÇ¢‰ÿ˦ÿϪ‘ÿѬ“ÿÒ®–ÿÓ¯—ÿÔ°˜ÿÔ±™ÿÕ²œÿÕ´ÿ×µžÿ×¶ ÿ×·¡ÿظ¢ÿÙ¹¤ÿÚ»¥ÿÚ»§ÿÚ½¨ÿÛ½©ÿÜ¿«ÿÜÀ­ÿÝÁ®ÿݯÿÞñÿÞIJÿßųÿàÆµÿàȶÿáɸÿáɹÿâÊ»ÿã̼ÿãͽÿäοÿäÏÀÿæÐÁÿåÑÃÿæÒÄÿæÓÆÿçÔÇÿèÕÉÿèÖÊÿé×ËÿêØÍÿêÙÎÿëÚÏÿëÛÐÿìÜÒÿíÞÓÿíÞÔÿíßÕÿîà×ÿîáØÿïâÙÿðãÛÿðäÜÿñåÝÿñæÞÿòçßÿòçáÿòèâÿóéãÿôëäÿôëåÿõëæÿõíçÿöîèÿöïéÿöïêÿ÷ðìÿ÷ñìÿøòîÿøòîÿøóïÿùóðÿùõñÿùõòÿúöóÿú÷ôÿû÷õÿûøöÿüùöÿüù÷ÿüùøÿýúùÿýûúÿýûûÿýüûÿýýüÿþýýÿþþýÿþþþÿÿþþÿÿÿÿÿ¸|Tÿ·|Uÿ¸~Uÿ¸~Vÿ¸~Wÿ¸Xÿ¹€Yÿ¹€Yÿ¹Zÿº[ÿ¸€Zÿ·€Zÿ·€[ÿµ[ÿ³}Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿjTEÿoXIÿw_NÿeTÿp^ÿš|hÿ¨‡qÿµ’{ÿ½›ƒÿÇ¢‰ÿ˦ÿϪ‘ÿѬ“ÿÒ¯–ÿÓ¯—ÿÔ±™ÿÔ±šÿÕ²›ÿÕ´ÿÖµžÿ×¶ ÿØ·¡ÿظ¢ÿÙ¹£ÿÙº¥ÿÚ¼§ÿÛ¼¨ÿÛ½ªÿÜ¿«ÿÜÀ¬ÿÝÁ®ÿÞÁ¯ÿÞðÿßIJÿßÅ´ÿàÆµÿàÇ·ÿáȸÿáʹÿâ˺ÿã̼ÿãͽÿäοÿåÎÀÿåÐÁÿæÑÃÿæÒÄÿçÓÆÿèÔÇÿèÕÈÿéÖÉÿé×ËÿéØÌÿêÙÍÿëÚÏÿìÛÐÿìÝÒÿìÞÓÿíÞÕÿîßÖÿîàÖÿîáØÿïãÚÿðãÛÿðäÜÿðåÝÿñåÞÿòæßÿòèáÿòèáÿóéãÿôêãÿôëåÿôìçÿõíçÿöîèÿöïéÿöðêÿ÷ðëÿ÷ñíÿøòíÿøòîÿøôïÿùóñÿúôòÿùõòÿúöóÿú÷õÿû÷ôÿûøöÿûùöÿüù÷ÿüúøÿýúùÿýûúÿýüûÿþüüÿýüüÿþýýÿþþýÿþþþÿþÿþÿÿÿÿÿ·}Tÿ·}Uÿ¸}Uÿ¸~Vÿ¸~Wÿ¸~Xÿ¹€Xÿ¹€YÿºZÿº[ÿ¸€[ÿ¸Zÿ·€[ÿµ[ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿkUEÿoXHÿx_Oÿ€fUÿq_ÿ›|gÿ¨ˆrÿµ“{ÿ½›ƒÿÇ¢‰ÿ˧ÿϪ‘ÿѬ“ÿÒ®–ÿÔ°—ÿÔ°˜ÿÔ±šÿÕ²›ÿÖ´ÿ×µžÿ×¶Ÿÿ×¶¡ÿظ¢ÿÙ¹¤ÿÙº¥ÿÚ¼¦ÿÛ½¨ÿÛ½©ÿÜ¿ªÿÜÀ­ÿÝÁ®ÿݰÿÞðÿßIJÿßÅ´ÿàÆ´ÿáǶÿáÈ·ÿâɹÿâË»ÿã̼ÿã̾ÿäοÿäÏÀÿåÏÁÿæÑÃÿæÒÄÿæÓÆÿçÔÇÿèÕÈÿéÖÉÿé×ËÿêØÌÿêÙÎÿëÚÏÿëÛÐÿìÜÑÿìÞÓÿíÞÔÿîßÕÿîàÖÿïáØÿïãÙÿïãÛÿðäÜÿñåÝÿòæÞÿòçßÿòèàÿóéáÿóéãÿóêãÿôëåÿôìçÿõíèÿöíéÿöïéÿöïêÿöðëÿøñíÿøñîÿøòîÿùóïÿùóðÿùõñÿùõóÿúöóÿû÷ôÿû÷õÿüøöÿüùöÿûù÷ÿüúøÿüûùÿýûúÿýûúÿþüüÿþýüÿþýýÿþþýÿþþýÿÿþþÿÿÿÿÿ·}Uÿ¸}Uÿ¸~Vÿ¸~Vÿ¸~Wÿ¹Xÿ¹€Xÿº€Zÿº[ÿº‚[ÿ¸€[ÿ¸€[ÿ·€[ÿµ[ÿ²~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿlUFÿpXIÿx_Nÿ€fUÿq_ÿ›|hÿ¨ˆrÿµ“|ÿ½›‚ÿÇ¢Šÿ˦ÿΪ‘ÿѬ”ÿÒ®–ÿÓ¯—ÿÔ°™ÿÔ²šÿÕ²›ÿÖ³ÿÖµžÿ×µ ÿØ·¡ÿظ¢ÿÙº¤ÿÚº¥ÿÚ»§ÿÛ½¨ÿÛ½©ÿܾ«ÿÜÀ¬ÿÝÀ®ÿݯÿÞñÿßIJÿßÅ´ÿàǵÿáǶÿáɸÿâʹÿãÊ»ÿã˼ÿäͽÿäÍ¿ÿåÏÀÿåÐÂÿæÐÃÿæÒÄÿçÔÆÿèÔÇÿèÕÈÿéÖÊÿé×ËÿéÙÌÿêÚÎÿêÚÏÿëÛÐÿìÜÑÿíÝÓÿíÞÔÿîßÖÿîà×ÿîáØÿïâÙÿðãÚÿðäÛÿñåÝÿñæÞÿòçßÿòèàÿòéâÿóéâÿôêäÿôëåÿõëæÿõíçÿöíèÿöïéÿöïêÿ÷ðëÿ÷ñìÿøòîÿøóïÿøóïÿùôðÿúõòÿúõòÿúõóÿû÷ôÿû÷õÿûøõÿûøöÿüú÷ÿüùøÿüûùÿýûúÿþûúÿýüüÿýýüÿþýüÿþþýÿþþþÿÿÿÿÿÿÿÿÿ¸|Uÿ·}Uÿ¸}Vÿ¸~Wÿ¸~Wÿ¸Xÿ¹Yÿ¹€Yÿ¹€ZÿºZÿ¸€Zÿ·€Zÿ·€[ÿµ~[ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿnWGÿqZJÿ{aPÿ‚gVÿr`ÿœ~iÿ©ˆrÿ¶”}ÿ¾›ƒÿÇ¢‰ÿ̦ÿϪÿѬ”ÿÓ¯–ÿÓ¯—ÿÔ°˜ÿÕ²™ÿÕ²›ÿÖ´ÿÖµžÿ×¶ŸÿØ·¡ÿظ¢ÿع£ÿÚº¥ÿÚ»§ÿÚ½¨ÿÛ½ªÿÛ¾«ÿÝÀ¬ÿÝÁ®ÿݯÿÞñÿßIJÿßųÿ߯´ÿàȶÿáÈ·ÿâɹÿâÊ»ÿã̼ÿã̽ÿäξÿäÏÀÿåÐÁÿåÑÃÿæÒÄÿçÓÅÿçÔÇÿèÕÈÿèÖÊÿéØËÿêØÌÿëÙÎÿëÚÏÿëÛÑÿìÜÑÿìÝÓÿíÞÔÿîßÕÿîà×ÿîáØÿïâÚÿðãÚÿðäÜÿðåÝÿñæÞÿòçßÿòèàÿóéâÿóêãÿóêäÿôëåÿôëçÿõíçÿõîèÿöîéÿöïêÿ÷ðìÿ÷ñíÿ÷ñíÿøóîÿùóðÿùóðÿúôñÿùõòÿúöóÿú÷ôÿûøõÿûøöÿûø÷ÿûù÷ÿüúøÿüúùÿýûúÿýüúÿþüûÿþýüÿþýýÿþýýÿÿþþÿÿþÿÿÿÿÿÿ·|Uÿ¸}Uÿ·~Vÿ¸~Wÿ¸~Wÿ¸Wÿ¹€Xÿº€YÿºZÿ¹‚[ÿ¸€Zÿ·Zÿ·€[ÿ¶~[ÿ³~Zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿpYHÿt\Lÿ|cQÿ„iXÿtaÿ~jÿª‰sÿ¶”|ÿ¿›ƒÿÇ¢‰ÿ̦ÿϪ‘ÿѬ”ÿÓ¯•ÿÓ¯—ÿÔ°˜ÿÕ²šÿÕ²›ÿÕ³œÿÖ´ŸÿÖ¶ ÿض¡ÿظ¢ÿÙ¹¤ÿÚº¥ÿÚ»§ÿÛ¼¨ÿÛ½©ÿܾ«ÿÜÀ¬ÿÝÁ®ÿÞ°ÿÞñÿßIJÿàÅ´ÿàÆµÿàǶÿáȸÿâɹÿâË»ÿã̼ÿãͽÿäοÿåÏÀÿåÏÂÿåÑÃÿæÒÅÿæÓÆÿèÔÇÿèÕÈÿèÖÊÿé×ËÿéÙÌÿêÚÍÿêÚÏÿìÛÑÿìÜÒÿìÞÓÿìÞÔÿîßÕÿîà×ÿïâØÿïâÚÿðãÛÿðäÜÿñåÝÿñæÞÿòçßÿòèàÿóéáÿóêãÿôêäÿôëåÿôìæÿõìèÿõíèÿöîêÿ÷ïêÿ÷ðìÿøðíÿøòíÿøòîÿøôïÿùôðÿúôñÿùõòÿúöóÿû÷ôÿû÷õÿûøõÿûù÷ÿüùøÿüúøÿüúùÿýûúÿýûúÿýüûÿþýûÿþýüÿþþýÿþþþÿþÿþÿÿÿÿÿ¸|Tÿ¸}Vÿ¸}Vÿ¸~Vÿ¸~Wÿ¹Xÿ¹€Xÿ¹€Yÿ¹€ZÿºZÿº[ÿ¸[ÿ¸€\ÿ¶€[ÿ³~[ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿu]Lÿy`Oÿ€fTÿˆmZÿ“wcÿŸ€kÿ¬‹tÿ¸•}ÿÀœƒÿÇ£Šÿ̦ÿЪ‘ÿѬ“ÿÒ®–ÿÓ¯—ÿÔ±™ÿÕ±šÿÕ²›ÿÖ´œÿÖ´žÿ×µ ÿØ·¡ÿظ£ÿÙ¹¤ÿÙ»¥ÿÚ»§ÿÛ¼¨ÿÛ¾©ÿÛ¾«ÿÝ¿¬ÿÝÁ®ÿݯÿÞñÿÞIJÿàÅ´ÿàǵÿàÇ·ÿáɸÿáɹÿâʺÿã̼ÿäͽÿäÍ¿ÿäÏÀÿåÐÁÿæÑÃÿæÒÄÿçÓÆÿèÔÇÿèÕÈÿèÖÊÿé×ËÿêØÍÿêÙÎÿëÚÏÿëÛÐÿìÝÑÿíÝÓÿíÞÕÿîßÕÿîáÖÿïáØÿïâÙÿðãÚÿðäÛÿñåÝÿñåÞÿñçßÿóèáÿóéâÿóéãÿôëäÿôìåÿôìçÿõíçÿõîèÿöïéÿöïêÿ÷ðìÿøñìÿøòîÿøóîÿøóðÿùôñÿùõñÿúõóÿúöóÿú÷ôÿúøõÿüøöÿüù÷ÿüúøÿüùøÿüûùÿüûúÿþûûÿþüûÿþýüÿþýüÿþþýÿÿþþÿÿÿÿÿÿÿÿÿ·}Tÿ¸}Uÿ¸~Vÿ¸~Vÿ¹~Wÿ¸Xÿ¹Xÿ¹€Yÿ¹ZÿºZÿº€Zÿ·Zÿ¸€[ÿµ€[ÿ³~[ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿz`Oÿ~dRÿ†jWÿŒp]ÿ—yeÿ£ƒmÿ®Œvÿº–~ÿÀ„ÿÈ£Šÿ̦ÿϪ‘ÿѬ”ÿÒ®–ÿÓ¯˜ÿÔ°˜ÿÔ²šÿÕ²›ÿÕ´ÿÖµžÿÖ¶Ÿÿ×·¡ÿظ£ÿع¤ÿÚ»¥ÿÚ»§ÿÚ¼¨ÿÛ½©ÿÛ¿«ÿÜÀ­ÿÝÁ­ÿݯÿÞñÿßijÿßÅ´ÿàÆµÿáÇ·ÿáÈ·ÿâʹÿâʺÿâ˼ÿãͽÿãÍ¿ÿäÏÀÿåÐÁÿæÑÃÿæÒÅÿçÓÆÿçÕÇÿèÕÈÿè×Éÿê×ËÿêØÌÿêÚÍÿëÚÏÿìÛÑÿìÜÒÿìÝÓÿíÞÔÿíßÕÿîàÖÿîáØÿïâÚÿðâÛÿðäÜÿðåÝÿñæÞÿñçßÿòçáÿòéáÿóéâÿôêäÿôëåÿôìçÿõíèÿõíèÿöïéÿ÷ïêÿ÷ðëÿ÷ðíÿ÷ñíÿùòïÿøóïÿùôðÿùôñÿúõóÿúöóÿúöôÿû÷õÿüøõÿûø÷ÿûù÷ÿüúøÿýúùÿýûúÿýûúÿýüûÿþüûÿþýýÿþþýÿþþþÿÿÿÿÿÿÿÿÿ·}Tÿ¸}Uÿ¸~Vÿ¸~Wÿ¸~Wÿ¹Xÿ¹€Yÿ¹€Yÿº€Zÿº[ÿº[ÿ¸[ÿ·€[ÿ¶€[ÿ¶\ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿ„gUÿ†jWÿŒp\ÿ“uaÿœ~iÿ§†pÿ²xÿ¼˜ÿž†ÿʤ‹ÿ˧ÿЪ‘ÿѬ“ÿÓ®–ÿÔ¯—ÿÔ°˜ÿÕ±šÿÕ²›ÿÖ´ÿÖµžÿ×¶ŸÿØ·¡ÿع£ÿع£ÿÚº¥ÿÚ»§ÿÚ¼¨ÿÛ¾ªÿÜ¿ªÿÜÀ­ÿÝÁ­ÿÞ¯ÿÞñÿßIJÿßÅ´ÿàÆµÿàǶÿáȸÿáɹÿâʺÿã̼ÿãͽÿäÍ¿ÿåÏÀÿåÐÁÿæÑÃÿæÒÅÿçÓÆÿèÔÇÿèÕÈÿèÖÊÿé×ËÿêØÌÿêÙÎÿëÚÏÿëÛÐÿìÜÒÿìÝÓÿíÞÔÿîàÕÿîàÖÿîáØÿïâÙÿðãÛÿñäÛÿñåÝÿòæÞÿòçßÿòèàÿóéâÿóéãÿóêäÿõëåÿôìæÿõíçÿõíèÿöîêÿöïêÿ÷ðìÿ÷ñíÿ÷òíÿøòîÿøôðÿùôñÿùôñÿúõòÿúöôÿú÷ôÿû÷ôÿûøöÿûùöÿûù÷ÿüúøÿüúùÿüûúÿýüúÿýüûÿþüüÿþýüÿþþýÿþþþÿþþþÿÿÿÿÿ·}Tÿ¸|Uÿ·~Vÿ¸~Wÿ¸~Wÿ¸Xÿ¹€Yÿ¹€YÿºZÿ¹‚[ÿ¹Zÿ¸€[ÿ·[ÿ¸\ÿµ€\ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿ‹nZÿq]ÿ”vaÿ˜zeÿ¢‚lÿ¬‰sÿ´’zÿ¾šÿÄŸ‡ÿÊ¥ŒÿͨŽÿϪ‘ÿѬ“ÿÒ¯–ÿÓ¯—ÿÔ±™ÿÔ²šÿÕ³›ÿÖ´ÿ×µžÿ×¶ ÿ×·¡ÿظ¢ÿÙ¹¤ÿÙº¥ÿÚ»¦ÿÚ¼¨ÿÛ½©ÿܾ«ÿÝÀ­ÿÜÁ®ÿݯÿÞñÿÞIJÿßųÿàǵÿàǶÿáȸÿâʹÿâ˺ÿã̼ÿã̾ÿäοÿäÎÀÿåÐÂÿæÑÃÿæÒÄÿæÓÅÿçÔÇÿèÖÈÿé×Êÿé×ËÿéÙÍÿêÙÎÿëÚÏÿëÜÑÿìÝÒÿíÝÓÿíÞÔÿíßÖÿîà×ÿîáØÿïâÙÿïãÚÿðäÛÿñåÝÿñæÞÿñçàÿòèàÿóèâÿóêãÿôêäÿôëåÿõìæÿõíçÿöîéÿöïêÿöðëÿ÷ðìÿ÷ñíÿøòíÿøóïÿùóïÿùôðÿùôòÿùõòÿúöóÿú÷ôÿû÷õÿûøöÿüù÷ÿüùøÿüúøÿüûùÿýûúÿýûúÿýüûÿýüüÿþýýÿþþýÿþþþÿÿþþÿÿÿÿÿ·|Tÿ¸}Uÿ·}Vÿ¸~Vÿ¸~Xÿ¸Xÿ¹€Yÿ¹€YÿºZÿ¹[ÿºZÿ¹€[ÿ¸‚[ÿ¸€]ÿ·€\ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿ”v`ÿ—wbÿœ|gÿ kÿ¨‡qÿ°Žwÿ¸•~ÿœƒÿÆ¡ˆÿ˦ŒÿͨÿЬ’ÿѬ“ÿÓ®–ÿÓ°—ÿÔ±™ÿÔ²šÿÕ³œÿÕ´ÿÖµžÿ×¶Ÿÿ×¶¡ÿظ¢ÿÙ¹£ÿÚº¥ÿÚ»¦ÿÛ¼¨ÿÛ½©ÿÜ¿«ÿÜ¿¬ÿÜÁ®ÿݯÿÞðÿßIJÿ߯´ÿàÆµÿàǶÿáȸÿáɹÿã˺ÿã̼ÿãͽÿäοÿåÏÀÿåÏÂÿåÑÃÿæÒÅÿçÓÆÿçÔÇÿèÕÉÿéÖÉÿéØËÿéØÌÿêÙÎÿëÚÏÿëÛÐÿìÜÑÿíÞÓÿíÞÕÿîßÕÿîà×ÿîáØÿïâÙÿðãÚÿðäÜÿðåÝÿñæÞÿòçàÿòçáÿóèâÿóéâÿóêäÿôëåÿõìæÿõíçÿõîèÿöîêÿöïêÿ÷ðëÿøðíÿ÷ñîÿøòîÿùóïÿùôðÿùôñÿùöòÿúöóÿû÷ôÿû÷õÿüøõÿûù÷ÿüù÷ÿüúøÿüûùÿýûúÿýûúÿýüûÿýüüÿþýýÿþþýÿÿþþÿÿÿþÿÿÿÿÿ·}Uÿ·|Uÿ¸~Vÿ¸}Wÿ¹Wÿ¹~Xÿ¹Xÿ¹€Zÿ¹€Zÿº[ÿ¹Zÿº‚[ÿ¹\ÿ¹€]ÿ·‚]ÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿž}gÿ iÿ¤ƒkÿ¨‡pÿ¯uÿµ’zÿ½˜ÿž…ÿÇ¢‰ÿ̧ÿÍ©ÿÑ«’ÿѬ“ÿÓ¯–ÿÓ¯—ÿÔ°™ÿÔ±šÿÕ³›ÿÕ³ÿÖµžÿ×¶ ÿ×·¡ÿظ¢ÿغ£ÿÚº¥ÿÚ»§ÿÚ¼¨ÿÛ½ªÿÛ¿«ÿÜÀ¬ÿÝÁ®ÿݯÿÞðÿßIJÿßųÿàÆµÿàǶÿáȸÿáʹÿâ˺ÿã˼ÿäͽÿäξÿåÏÀÿåÐÁÿæÐÃÿæÒÄÿçÓÅÿçÔÇÿèÕÉÿéÖÊÿé×ËÿêØÍÿëÙÎÿëÚÏÿëÛÐÿìÜÒÿíÝÓÿíÞÔÿîßÕÿîà×ÿïáØÿïâÙÿðãÚÿðäÜÿñåÝÿñæÞÿòçßÿòèàÿóéâÿóêãÿóêäÿõëåÿôìæÿõíçÿöíèÿöïéÿ÷ïêÿ÷ðìÿ÷ñìÿøòîÿøòïÿùóïÿùôðÿúõñÿúöòÿúöóÿú÷ôÿú÷õÿûøõÿûù÷ÿüúøÿüúùÿýûùÿýûùÿýûûÿýüûÿþýüÿþýýÿÿýýÿþþþÿÿþþÿÿÿÿÿ·}Uÿ·}Vÿ¸}Uÿ¸~Vÿ¹~Wÿ¸Xÿ¹Yÿ¹€Yÿº€Zÿ¹[ÿº‚[ÿ¹[ÿ¹]ÿ¹‚\ÿ¹]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿÿÿÿÿ¦ƒkÿ§…mÿ¬‡qÿ¯Œtÿ´xÿº•|ÿÀ›‚ÿÅ ‡ÿÈ£Šÿ̧ŽÿΨÿЬ’ÿÒ­”ÿÒ®•ÿÓ°—ÿÔ°˜ÿÔ²šÿÕ³›ÿÖ´ÿ×µžÿ×¶ŸÿØ·¡ÿظ£ÿÙ¹¤ÿÚº¥ÿÚ»§ÿÚ½¨ÿÛ¾©ÿÜ¿«ÿÜ¿¬ÿÜÁ­ÿݯÿÞñÿÞijÿàųÿßǵÿáȶÿáÈ·ÿâʹÿâ˺ÿã̼ÿã;ÿäοÿåÎÁÿåÐÁÿæÑÃÿçÒÄÿçÓÅÿèÔÇÿèÕÉÿèÖÊÿê×ËÿêØÌÿêÙÎÿëÚÏÿëÜÐÿëÝÒÿìÝÓÿìÞÔÿíßÖÿîà×ÿïáØÿïâÙÿïãÛÿðãÜÿðäÝÿòæÞÿñçàÿòçàÿòéâÿóêãÿôëäÿôëåÿôìçÿõíçÿöíèÿöîéÿöðëÿöðìÿ÷ñìÿøñíÿøòïÿøóïÿùóñÿùôñÿúöòÿúöóÿûöôÿû÷ôÿûøöÿûùöÿüùøÿüúøÿýûùÿýûúÿýûúÿþüûÿþýüÿþýýÿÿþýÿÿþýÿÿÿþÿÿÿÿÿ·|Uÿ¸}Uÿ¸}Uÿ¸~Wÿ¸Wÿ¸Xÿ¹Xÿ¹€Yÿ¹€Zÿº[ÿ»\ÿº‚[ÿ¹\ÿ¹‚\ÿ¸]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®‰pÿ¯‹sÿ±uÿ´xÿ¹“{ÿ½˜ÿÁƒÿÆ¡‡ÿɤŠÿͧÿÏ©ÿЫ’ÿÒ­”ÿÓ®•ÿÔ¯—ÿÓ±™ÿÕ²šÿÕ³›ÿÕ´ÿÖµžÿ×¶Ÿÿ×·¡ÿظ£ÿÙ¹¤ÿÚº¥ÿÚ¼§ÿÚ½¨ÿÛ½©ÿÛ¾«ÿÝÀ­ÿÜÁ­ÿݯÿÞðÿßIJÿàųÿàǵÿàȶÿáÈ·ÿâʹÿâ˺ÿã˼ÿã̽ÿäοÿåÏÀÿåÐÁÿåÑÂÿæÒÄÿæÓÆÿçÔÇÿèÕÈÿéÖÊÿê×ËÿêØÌÿêÙÎÿëÚÏÿìÛÑÿìÜÑÿíÞÓÿíÞÕÿîßÖÿîà×ÿîáØÿïâÙÿïãÛÿðäÜÿñåÜÿñæÞÿòçßÿòçàÿòéáÿóêãÿóëäÿõëåÿôìæÿõíçÿõîèÿöîéÿöïëÿ÷ðìÿ÷ñìÿ÷òîÿøòîÿøóïÿùôñÿùõñÿúõòÿúöóÿûöôÿû÷õÿûøöÿüùöÿüú÷ÿüúùÿüúùÿýûúÿýüúÿýüûÿþýüÿþýýÿþýþÿÿþþÿþÿÿÿÿÿÿÿ·}Tÿ·}Uÿ¸~Vÿ¸}Wÿ¸~Wÿ¹Xÿ¹€Xÿ¹€Yÿº€Zÿº[ÿº‚[ÿº‚\ÿº‚\ÿ¹‚]ÿ¹‚]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³Žtÿ³uÿ·’yÿ¸“{ÿ¼˜~ÿÁ›‚ÿÄŸ…ÿÈ¢‰ÿË¥ŒÿΨŽÿЪ‘ÿÒ¬“ÿÒ­”ÿÒ¯–ÿÔ°—ÿÔ±™ÿÕ²šÿÕ³›ÿÖ³œÿÖµžÿ×¶ ÿ×·¡ÿظ£ÿÙ¹¤ÿÙº¦ÿÚ¼§ÿÚ¼¨ÿÛ¾©ÿÜ¿«ÿÜÀ­ÿÜÀ®ÿݯÿÞñÿÞIJÿßųÿ߯´ÿáȶÿáȸÿáɹÿâÊ»ÿã˼ÿäͽÿäÍ¿ÿåÏÀÿåÐÂÿåÑÃÿçÒÄÿçÓÆÿçÔÇÿèÕÈÿéÖÊÿé×ËÿêØÌÿêÙÍÿëÚÏÿìÜÐÿìÜÒÿíÝÓÿíÞÔÿîßÖÿîà×ÿïáØÿïâÙÿïãÛÿðäÜÿñåÝÿñæÞÿòçßÿòèàÿóéáÿóéâÿóëãÿôëåÿôìæÿõíçÿõíéÿöîéÿöðêÿ÷ðìÿ÷ñìÿøòíÿøòîÿøóïÿøôðÿùôòÿúõòÿúöóÿûöôÿû÷õÿü÷öÿûùöÿüù÷ÿüúøÿýúùÿýûúÿþüûÿýüûÿýýüÿþýýÿÿþýÿþÿþÿÿþþÿÿÿÿÿ·|Uÿ¸}Vÿ¸~Vÿ¸~Vÿ¸~Wÿ¹Xÿ¹€Xÿº€Zÿ¹Zÿº[ÿº‚\ÿº‚\ÿº‚\ÿ»‚]ÿºƒ^ÿÿÿÿÿÿÿÿÿÿÿÿÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹“xÿ»“zÿ¼–|ÿ¾˜~ÿÀ›€ÿÄž„ÿÇ¡‡ÿÊ£‰ÿ̦‹ÿΨÿЪ‘ÿÒ¬“ÿÒ®”ÿÒ®–ÿÓ°—ÿÔ°˜ÿÔ²šÿÕ²›ÿÖ´ÿÖµžÿ×¶ŸÿØ· ÿظ£ÿع¤ÿÙº¥ÿÙ»¦ÿÚ¼¨ÿÛ½©ÿÛ¿«ÿÜÀ¬ÿÜÁ­ÿݯÿÞñÿßIJÿßÅ´ÿàÆµÿáȶÿáȸÿáɹÿâË»ÿâ̼ÿã̽ÿäοÿåÏÀÿåÐÂÿæÑÃÿæÒÅÿçÓÆÿçÔÇÿèÕÉÿèÖÊÿê×ËÿêØÍÿêÙÎÿëÚÏÿëÛÑÿìÜÑÿìÝÓÿíÞÕÿîßÕÿîà×ÿîáØÿïâÙÿïãÛÿðäÜÿðåÝÿñåÞÿòçßÿòçàÿóèáÿóéãÿóêäÿôëåÿôìæÿõíçÿõíéÿöïéÿ÷ðêÿ÷ðëÿ÷ðíÿ÷òíÿøóîÿøóïÿùóðÿùôñÿúõòÿúöóÿú÷ôÿû÷õÿû÷öÿûùöÿüúøÿüúøÿýúùÿýûúÿýüûÿþüûÿþýüÿþýýÿþýýÿÿþþÿÿþÿÿÿÿÿÿ¸|Uÿ·}Uÿ·}Vÿ¸~Wÿ¸~Wÿ¹Wÿ¹€Xÿ¹€YÿºZÿº[ÿº‚[ÿºƒ\ÿ»ƒ]ÿº‚]ÿº‚^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿•|ÿ¿—|ÿÀ™~ÿ›ÿăÿÆ …ÿÊ£ˆÿË¥‹ÿͧÿÏ©ÿЪÿÒ­’ÿÒ­”ÿÓ¯–ÿÓ¯—ÿÔ°˜ÿÕ²™ÿÕ³œÿÕ´ÿ×µžÿ×¶ ÿØ·¡ÿظ¢ÿÙ¹¤ÿÙº¦ÿÙ»¦ÿÚ¼¨ÿÛ½ªÿܾ«ÿÜ¿­ÿÝÁ­ÿÞ¯ÿÞñÿßIJÿàųÿàÆµÿàǶÿáÈ·ÿáʹÿâË»ÿã˼ÿãͽÿäοÿåÎÀÿæÐÂÿæÐÃÿçÒÅÿçÓÆÿèÔÇÿèÕÈÿéÖÊÿé×ËÿêØÌÿêÙÎÿëÛÏÿëÛÐÿìÜÒÿìÝÓÿíÞÔÿîàÕÿîá×ÿïáØÿïâÚÿïâÛÿðäÜÿñåÝÿñæÞÿòçßÿóçáÿóéáÿóêãÿóêãÿôëåÿõìæÿõíçÿöíèÿöîêÿöïêÿ÷ðëÿøñíÿ÷ñíÿøóîÿùóïÿùôñÿùôñÿúõòÿúöôÿû÷ôÿû÷õÿûøöÿûø÷ÿüù÷ÿüúùÿýúùÿüûúÿýüúÿþüüÿýýüÿþýüÿþþýÿÿþýÿÿþÿÿÿÿÿÿ·|Uÿ·}Uÿ¸}Uÿ¸~Wÿ¸Wÿ¹Xÿ¹Xÿ¹€Zÿ¹€Zÿº[ÿ»‚\ÿ»‚]ÿ»ƒ]ÿº‚]ÿºƒ^ÿº„_ÿº„_ÿº„`ÿº„aÿº…aÿº…bÿ¹…bÿ¹‡dÿ¹†dÿ¸†dÿ¸†dÿ·†fÿ¸‡gÿ¹ˆhÿ¹‰iÿ¸Šiÿ¹Šjÿ¹‹kÿ»Œmÿ»Žnÿ¼oÿ»Žpÿ»rÿ½sÿ¾’tÿ¾“uÿ¿”vÿ¿”xÿ¿•yÿÀ–yÿÁ˜{ÿ™}ÿ™~ÿÄ›ÿÅ‚ÿÅžƒÿÈ †ÿÉ¢‡ÿʤŠÿ̦ŒÿͧŒÿÏ©ÿЪÿÒ¬“ÿÒ­”ÿÓ¯–ÿÓ°—ÿÔ°˜ÿÔ±šÿÕ²›ÿÖ³ÿÖ´žÿ×¶ ÿØ·¡ÿظ¢ÿÙ¹£ÿÚº¥ÿÚ»¦ÿÚ¼¨ÿÛ¾ªÿÜ¿ªÿÜ¿¬ÿÜÁ­ÿݯÿÞðÿßIJÿàÅ´ÿàÆµÿáȶÿáȸÿâɹÿâË»ÿã̼ÿä̽ÿäξÿåÎÀÿåÐÁÿåÑÃÿæÒÄÿçÓÅÿçÔÇÿèÖÈÿèÖÊÿé×ËÿéÙÌÿêÙÎÿêÚÏÿëÛÑÿìÜÒÿíÝÓÿíßÔÿíßÕÿîà×ÿîáØÿïâÙÿïãÛÿðäÛÿðåÝÿòæÞÿòçßÿòçàÿóèâÿóêâÿóëäÿôëåÿõìæÿõìçÿõíèÿöîéÿ÷ðêÿöðìÿ÷ñìÿøòîÿøòîÿùóïÿùóñÿùõñÿùõòÿúöôÿúöôÿû÷õÿüøõÿüø÷ÿüù÷ÿüúùÿüúùÿýûúÿýûúÿþüûÿýýüÿýþüÿþýýÿÿþþÿÿÿþÿÿÿÿÿ·}Uÿ¸}Uÿ¸~Vÿ¸~Wÿ¸~Wÿ¸Xÿ¹€Xÿ¹€Yÿ¹Zÿ¹[ÿº‚\ÿ»ƒ]ÿ»ƒ]ÿ»„^ÿºƒ^ÿ»„_ÿ»…_ÿ»„aÿº…aÿ»†aÿ»†bÿ»‡dÿ»‡dÿº‡dÿºˆeÿº‰gÿºˆgÿºŠgÿ»Šhÿ»‹jÿ¼Œkÿ»Œmÿ½Žmÿ¼Žoÿ½oÿ¾pÿ¾‘rÿ¿’tÿ¿“tÿÀ”vÿÁ•wÿÁ–yÿÁ–zÿ˜zÿÙ{ÿÙ|ÿÚ}ÿÄšÿÆ‚ÿÆž‚ÿÈŸ„ÿÈ¡‡ÿÊ£ˆÿˤŠÿͦŒÿϨŽÿÏ©ÿÑ«’ÿÒ¬“ÿÒ­”ÿÒ¯–ÿÔ°—ÿÓ°™ÿÕ±šÿÕ²›ÿÖ³ÿÖ´žÿ×µŸÿØ·¡ÿظ£ÿÙ¹¤ÿÙº¥ÿÚ»¦ÿÛ¼¨ÿÛ½ªÿÛ¿«ÿÜÀ¬ÿÝÀ®ÿݯÿÞñÿÞIJÿßÅ´ÿàÆµÿáÇ·ÿáÈ·ÿáɹÿâ˺ÿâ˼ÿãͽÿäοÿäÏÀÿåÐÂÿæÑÃÿçÒÄÿçÓÅÿçÔÇÿèÕÈÿéÖÊÿé×ËÿêØÍÿëÙÎÿëÚÏÿìÛÑÿìÜÑÿìÝÓÿíßÕÿîßÕÿîà×ÿïáØÿïâÚÿïãÚÿðäÛÿðåÝÿñæÞÿòæßÿóçàÿóèáÿóéãÿóêäÿôëåÿõìæÿõìèÿõîèÿöïêÿöïëÿ÷ðëÿøñìÿøòíÿøóîÿøóðÿùôðÿúôñÿùöóÿúöóÿú÷ôÿûøõÿûøõÿûø÷ÿûù÷ÿýúøÿýúùÿýûúÿýüûÿýüüÿþüüÿþýýÿÿýþÿþþþÿÿÿþÿÿÿÿÿ·|Tÿ¸|Uÿ¸~Vÿ¸~Vÿ¸Xÿ¹Wÿ¹Xÿ¹€Yÿ¹€ZÿºZÿº‚[ÿ»ƒ\ÿ»ƒ]ÿ»ƒ^ÿ¼„_ÿ¼…`ÿ¼…`ÿ¼…aÿ»…bÿ¼†cÿ¼‡cÿ¼‡cÿ¼ˆdÿ¼ˆfÿ¼‰gÿ¼Šhÿ½Šhÿ½Œhÿ½Œjÿ¾kÿ¿lÿ¿Žmÿ¿nÿÀ‘pÿÀ’qÿÁ’rÿÁ“sÿ”tÿ•vÿÖwÿÄ–xÿÄ–yÿÄ—{ÿŘ|ÿÆ™}ÿÆ›ÿÇœ€ÿÇÿÈž‚ÿÈ ƒÿÉ¡…ÿÊ£‡ÿ̤ˆÿÍ¥ŠÿΧÿϨŽÿЫÿÑ«’ÿѬ“ÿÒ­”ÿÓ¯•ÿÓ°—ÿÔ°˜ÿÔ±šÿÕ²›ÿÖ³œÿÖµŸÿ×¶ ÿ×·¡ÿظ£ÿÙ¹£ÿÙº¥ÿÚ»§ÿÛ¼¨ÿÛ½©ÿÛ¾«ÿÜÀ¬ÿÝÁ®ÿݯÿÞðÿÞIJÿßųÿàÆµÿàǶÿáȸÿâɹÿãË»ÿã̼ÿã̽ÿäξÿäÏÁÿåÏÂÿæÑÃÿæÒÅÿçÓÅÿçÔÇÿèÕÈÿè×Éÿé×ËÿéØÌÿëÙÍÿëÛÏÿìÛÐÿìÜÑÿíÝÓÿíßÔÿîßÖÿîà×ÿîáØÿïâÙÿðãÛÿðäÛÿðåÝÿòæÞÿòçßÿòçáÿóèáÿóéãÿôêäÿôìåÿôìæÿõìçÿõîéÿöîêÿöïêÿ÷ðìÿ÷ñìÿøñîÿøóîÿøóïÿùôðÿúõñÿúöòÿúöóÿú÷ôÿûøõÿûøöÿüøöÿüúøÿýúøÿüûùÿýûúÿýûúÿþüûÿþýüÿþýýÿþþýÿþþýÿÿÿÿÿÿÿÿÿ·}Uÿ·}Uÿ¸}Vÿ¸~Wÿ¹~Wÿ¸Xÿ¹€Yÿº€Yÿ¹[ÿº‚[ÿº‚\ÿºƒ\ÿ»ƒ]ÿ»„^ÿ»„_ÿ¼…`ÿ¼…aÿ»…`ÿ¼†aÿ¼‡bÿ½ˆcÿ¼‡eÿ¼ˆeÿ¾‰fÿ½Šfÿ½‹hÿ¾‹hÿ¾jÿ¾kÿ¿Žlÿ¿mÿÀnÿÀ‘oÿÁ‘qÿÁ“rÿ”sÿÔtÿÕuÿÖvÿÄ–xÿŘyÿÅ™{ÿÆ™|ÿÆš|ÿÇœÿÈ€ÿÇžÿÈŸƒÿÉ ƒÿÉ¡…ÿË¢†ÿÌ£‡ÿÍ¥‰ÿΦ‹ÿΧŒÿЩÿЪÿЫ‘ÿÒ¬“ÿÒ­•ÿÓ®–ÿÓ¯—ÿÔ±˜ÿÔ±™ÿÕ³›ÿÕ´ÿ×´žÿ×¶ ÿ×·¡ÿظ¢ÿع¤ÿÙº¥ÿÙ»§ÿÚ¼¨ÿÛ½ªÿÛ¿«ÿÝÀ­ÿÝÁ­ÿݯÿÞñÿÞIJÿ߯´ÿàÆµÿáÇ·ÿáÈ·ÿáɹÿâʺÿâ˼ÿã̽ÿäξÿäÎÁÿåÐÂÿæÑÃÿæÒÄÿçÓÅÿèÔÇÿèÖÈÿéÖÊÿé×ËÿêØÌÿêÙÍÿëÚÏÿìÛÐÿìÜÒÿìÝÓÿíÞÔÿîßÕÿîà×ÿîáØÿðâÙÿïãÛÿðäÜÿñåÝÿñæÞÿñæßÿòçàÿóéáÿóéãÿôêäÿôëåÿôìæÿõíèÿõîéÿöîéÿöïëÿ÷ðëÿ÷ñìÿøñíÿøòîÿøóïÿùôðÿùõòÿúöóÿúöóÿúöôÿú÷õÿûøöÿûøöÿüù÷ÿüúøÿüúùÿýûùÿýüûÿýüûÿþüüÿþýýÿþþýÿþþýÿþþþÿÿÿÿÿ·}Uÿ¸}Uÿ¸}Vÿ¸~Vÿ¸Wÿ¸Wÿ¸€Yÿ¹€Yÿ¹Zÿº[ÿº‚[ÿ»‚\ÿºƒ]ÿ»„^ÿ¼…_ÿ¼…`ÿ¼†aÿ½†bÿ½‡bÿ½ˆdÿ½‡dÿ½ˆdÿ¾Šeÿ¿Šfÿ¾‹gÿ¿‹iÿ¿Œjÿ¿Œkÿ¿lÿÀŽmÿÀnÿÀoÿ‘pÿÂ’rÿÂ’rÿÓtÿÔuÿÄ•vÿÄ–wÿÅ—xÿƘzÿÆ™|ÿÆš}ÿÇ›}ÿÈœ~ÿÈ€ÿÉžÿÉŸ‚ÿÊ ƒÿË¢…ÿÌ£‡ÿ̤ˆÿÍ¥ŠÿΧŒÿϨÿЩÿЫÿÑ«’ÿѬ“ÿÒ­•ÿÒ¯•ÿÓ¯˜ÿÓ±˜ÿÕ²šÿÕ³›ÿÖ³œÿÖµžÿ×¶Ÿÿ×·¡ÿظ¢ÿع¤ÿÙº¥ÿÙ»¦ÿÛ½¨ÿÛ½©ÿܾ«ÿÜÀ­ÿÝÁ®ÿݯÿÞðÿßIJÿßųÿàǵÿàÈ·ÿáȸÿáʹÿâÊ»ÿã̼ÿãͽÿäοÿäÏÀÿæÐÂÿæÑÃÿæÒÄÿæÓÆÿçÔÇÿèÕÉÿèÖÊÿê×ËÿéÙÌÿëÚÎÿêÚÏÿìÜÐÿìÜÒÿìÝÓÿíßÔÿîßÖÿîà×ÿïáØÿïâÙÿðãÚÿðäÜÿðåÝÿñæÞÿòæàÿòèáÿóéáÿóéãÿôêäÿôëåÿôìæÿõíçÿöîéÿöïêÿ÷ðëÿ÷ðëÿ÷ñìÿøñíÿøòïÿøóïÿùôñÿùôñÿùõòÿúöóÿú÷ôÿûøõÿû÷õÿüù÷ÿüùøÿüùøÿüúùÿýûúÿýüúÿýüûÿþüüÿþýýÿþþýÿþþþÿÿÿþÿÿÿÿÿ·}Tÿ·}Uÿ¸}Vÿ¸~Vÿ¸Xÿ¸Xÿ¹Yÿº€Zÿ¹€ZÿºZÿº‚\ÿ»‚]ÿ»ƒ]ÿ¼ƒ^ÿ»„_ÿ¼…`ÿ¼†`ÿ¼†bÿ½‡bÿ¾ˆcÿ½‰dÿ¿Šeÿ¾ŠgÿÀ‹hÿ¿‹iÿÀŒjÿÀkÿÁŽlÿÂmÿÂnÿÑoÿÃ’qÿÄ’qÿÄ“sÿÄ”tÿÅ•uÿÅ–vÿƘwÿƘyÿÆ™zÿÇš{ÿÈ›|ÿÉœ~ÿÉ~ÿÊžÿËŸ‚ÿË ƒÿË¡„ÿÌ¢…ÿÍ£‡ÿÍ£‰ÿÎ¥ŠÿΦ‹ÿϦŒÿϨÿЩÿѪÿÑ«’ÿѬ“ÿÒ­•ÿÓ®–ÿÓ¯—ÿÔ°˜ÿÔ±šÿÕ²œÿÖ´ÿÖµžÿ×¶Ÿÿ×·¡ÿظ¢ÿÙ¹¤ÿÚº¥ÿÚ»§ÿÛ¼¨ÿÛ¾ªÿÛ¿«ÿÜ¿­ÿÜÁ­ÿÞ¯ÿÞðÿßIJÿßÅ´ÿàÆµÿàÈ·ÿáÉ·ÿâʹÿâÊ»ÿã̼ÿäͽÿäοÿåÏÀÿåÐÂÿåÑÃÿçÒÄÿçÓÆÿèÔÇÿèÕÉÿèÖÊÿé×ËÿêØÍÿëÙÎÿëÚÏÿìÜÐÿìÜÑÿíÝÒÿíßÔÿíßÖÿîà×ÿîáØÿïâÙÿðãÛÿðãÛÿñåÝÿòæÞÿòçàÿòçàÿóèáÿóéãÿóêäÿôëåÿõìæÿõìçÿõíèÿöïêÿöðëÿöðëÿ÷ðìÿ÷ñîÿøòïÿùóïÿùôñÿúõñÿúõòÿúõóÿúöôÿûøõÿûøöÿüù÷ÿüù÷ÿüùøÿüûùÿýûúÿýûûÿýüûÿþüüÿþýýÿþýýÿÿþþÿÿÿÿÿÿÿÿÿ·}Uÿ¸|Uÿ¸}Vÿ¸~Vÿ¸~Wÿ¹~Xÿ¹Xÿ¹€ZÿºZÿº[ÿº‚[ÿºƒ]ÿ»„^ÿ¼„^ÿ»…^ÿ¼†`ÿ½†aÿ¼‡bÿ½ˆcÿ½‡dÿ¾ˆeÿ¾Šfÿ¾Šfÿ¿‹gÿ¿ŒhÿÁjÿÁŽkÿÁŽlÿÁmÿÂnÿÑoÿÂ’pÿÓqÿÄ“rÿÅ•tÿÅ•uÿÆ–vÿÆ—wÿǘyÿÇ™zÿÈš{ÿÈ›}ÿÉœ~ÿÉ~ÿÊž€ÿÊŸÿË ‚ÿË „ÿÌ¢…ÿÍ£‡ÿͤˆÿÍ¥‰ÿΦ‹ÿΧŒÿШÿЩÿЪÿÑ«‘ÿÑ­“ÿÒ­•ÿÒ®•ÿÓ¯—ÿÓ°˜ÿÕ±šÿÕ³œÿÖ´ÿÖ´Ÿÿ×¶ŸÿØ·¡ÿظ¢ÿÙ¹£ÿÚº¥ÿÚ»§ÿÚ¼¨ÿÛ¾ªÿÜ¿ªÿÝÀ¬ÿÝÁ­ÿݯÿÞñÿÞIJÿßÅ´ÿ߯µÿáǶÿáÈ·ÿâʹÿâË»ÿã̼ÿäͽÿäÍ¿ÿäÏÁÿåÐÁÿæÑÃÿçÒÄÿæÓÅÿçÔÇÿèÕÉÿèÖÊÿéØËÿéØÌÿêÙÍÿëÚÏÿëÛÐÿìÜÒÿìÝÓÿíÞÔÿîßÕÿîàÖÿïáØÿïâÙÿðãÛÿðäÜÿñåÝÿòæÞÿñçßÿòçáÿòèáÿóéâÿóêäÿôëåÿõìæÿõìçÿöíèÿõïéÿöïêÿ÷ðëÿ÷ñìÿøòíÿøòîÿùóðÿùôðÿùôñÿùöòÿúöóÿúöôÿú÷õÿûøõÿûø÷ÿüú÷ÿüùøÿüúùÿýûúÿýûúÿýüûÿþüüÿþýýÿþýýÿÿþþÿÿÿÿÿÿÿÿÿ·}Uÿ·}Uÿ·}Vÿ¸~Wÿ¸Wÿ¹Xÿ¹€Yÿº€Zÿº€Zÿº‚Zÿº‚[ÿ»‚\ÿ»ƒ]ÿ»„^ÿ»…_ÿ¼…`ÿ¼†aÿ¼†aÿ½‡bÿ¾ˆcÿ¾ˆeÿ¿Šeÿ¿Šgÿ¿‹hÿÀŒhÿÀŒiÿÁjÿÁŽlÿÁlÿÂnÿÑoÿÃ’pÿÄ“qÿÄ“sÿÄ”tÿÅ•uÿÅ–vÿÆ—wÿƘxÿÇ™zÿÇš{ÿÈ›|ÿÈœ}ÿÉÿÉž€ÿÊž‚ÿË ‚ÿË¡„ÿÌ¢…ÿÌ£†ÿͤ‰ÿΤ‰ÿÎ¥‹ÿΧŒÿШÿЪŽÿЪÿÑ«‘ÿÒ¬“ÿÒ­”ÿÓ®•ÿÔ¯—ÿÔ±™ÿÔ²šÿÖ²›ÿÕ´ÿÖµŸÿ×¶Ÿÿض¡ÿظ£ÿÙ¹¤ÿÙ»¥ÿÚ¼¦ÿÛ½¨ÿÛ½ªÿܾ«ÿÜÀ­ÿÝÁ­ÿݯÿÞñÿßIJÿßųÿàÆµÿàȶÿáÈ·ÿâʹÿãË»ÿã̼ÿã̾ÿäοÿåÏÀÿåÐÂÿæÐÃÿçÒÄÿæÓÅÿèÔÇÿèÕÈÿéÖÊÿé×ËÿéØÌÿêÙÎÿëÚÏÿëÛÑÿìÜÒÿìÝÓÿíÞÔÿíßÕÿîà×ÿïáØÿïâÙÿïãÚÿñäÛÿñäÝÿñæÞÿòçàÿòçàÿóèâÿóêãÿôêäÿôëåÿõìæÿõíèÿöîéÿöîéÿöðêÿ÷ðëÿ÷ñíÿ÷òíÿøòîÿøóïÿùôðÿúôñÿúõòÿúöôÿû÷ôÿúøõÿûøõÿüù÷ÿüùøÿüúøÿýûùÿüûúÿþûûÿýüûÿþýûÿþýüÿþþýÿþþþÿÿþþÿÿÿÿÿ·}Tÿ¸|Uÿ¸}Vÿ¸~Wÿ¸Wÿ¹Xÿ¹Yÿº€Yÿ¹Zÿ¹Zÿº‚\ÿ»‚]ÿ»ƒ]ÿ»ƒ^ÿ»…_ÿ¼…`ÿ¼…`ÿ½†bÿ½‡cÿ¾ˆcÿ¾‰dÿ¾Šfÿ¿‹gÿ¿‹hÿ¿‹iÿÀjÿÀjÿÁŽlÿÂmÿÂnÿÃoÿÃ’qÿÓrÿÄ“rÿÅ”tÿÅ•uÿÆ–vÿÆ—wÿƘyÿǘzÿÇš{ÿÈ›|ÿÉœ}ÿÉœÿÊžÿÊžÿË ‚ÿË¡„ÿË¢…ÿÌ£‡ÿ̤ˆÿÎ¥ŠÿΦŠÿϧŒÿϨŽÿЩÿѪÿÑ«‘ÿѬ“ÿÒ­”ÿÒ®•ÿÓ°—ÿÔ°™ÿÔ±šÿÕ²›ÿÕ³œÿÖ´žÿ×¶ ÿ×·¡ÿظ¢ÿع¤ÿÙº¥ÿÚ»§ÿÛ¼¨ÿÛ¾ªÿܾ«ÿÜÀ¬ÿÝÁ®ÿݯÿÞñÿßIJÿßųÿ߯µÿàǶÿáȸÿáʹÿâ˺ÿâ̼ÿã;ÿäοÿåÏÀÿåÐÁÿæÐÃÿæÒÄÿçÓÆÿçÔÇÿèÕÉÿèÖÊÿéØËÿêØÍÿêÙÎÿëÚÏÿìÛÑÿìÜÒÿìÝÒÿìÞÔÿîßÖÿîà×ÿîáØÿïâÙÿðãÚÿðäÛÿñåÝÿñåÞÿòçßÿòèàÿòèâÿóéâÿôêäÿôëåÿõìæÿõíçÿöíèÿöïêÿöïëÿöðëÿ÷ñìÿøñíÿùóîÿøóïÿøôðÿúõñÿúõóÿúöóÿú÷ôÿû÷ôÿûøöÿüù÷ÿüù÷ÿüúøÿüúùÿýûúÿþüûÿýüûÿþýüÿþýüÿÿþþÿÿþþÿþþþÿÿÿÿÿ·|Uÿ¸}Uÿ¸}Vÿ¸~Wÿ¹Wÿ¹Xÿ¹€Yÿ¹€Yÿ¹Zÿº[ÿº‚[ÿ»‚\ÿ»ƒ]ÿ»„_ÿ¼„_ÿ¼…`ÿ¼…aÿ¼‡aÿ½ˆcÿ¾ˆdÿ¾‰dÿ¿‰fÿ¿Šfÿ¿‹gÿ¿‹hÿÁjÿÀŽkÿÁŽlÿÁmÿÂnÿ‘oÿÃ’pÿÃ’qÿÄ”rÿÅ”tÿÄ–uÿÆ–vÿÆ—wÿǘyÿÆ™zÿÇ™{ÿÈ›|ÿÉœ~ÿÉÿÊž€ÿÊŸÿË ƒÿË¡„ÿÌ¢…ÿÌ£‡ÿͤˆÿͤ‰ÿΦ‹ÿϦŒÿϧÿЩÿЪÿѬ’ÿѬ“ÿÒ­”ÿÓ®–ÿÓ°—ÿÔ±˜ÿÕ±šÿÕ³œÿÖ³ÿ×´žÿ×¶ ÿ×·¡ÿظ¢ÿÙ¹£ÿÚ»¥ÿÚ¼§ÿÚ¼¨ÿÛ½©ÿÜ¿«ÿÝÀ¬ÿÝÁ­ÿݯÿÞñÿßIJÿ߯´ÿàÆµÿàǶÿáȸÿâɹÿâÊ»ÿã̼ÿä̽ÿãοÿäÏÀÿåÐÂÿæÑÃÿæÒÄÿçÓÆÿçÔÇÿèÕÉÿéÖÉÿê×ËÿêØÌÿêÙÎÿëÚÏÿëÛÐÿìÜÑÿìÝÓÿíßÔÿîàÖÿîà×ÿîáØÿïâÙÿðãÛÿðäÜÿñäÝÿñæÞÿñçßÿòèáÿóéâÿóêâÿóêäÿôëåÿôìæÿõíçÿöíéÿõîêÿöïêÿ÷ðëÿ÷ðìÿøñíÿøòïÿùóðÿùôðÿùôòÿùöòÿúöóÿú÷ôÿû÷õÿü÷õÿûù÷ÿüù÷ÿüúøÿüûùÿüûúÿýûûÿýüüÿýýüÿþýýÿþþýÿÿþþÿÿþÿÿÿÿÿÿ·|Uÿ¸}Uÿ¸~Uÿ¸~Wÿ¸~Wÿ¸~Xÿ¹Xÿº€ZÿºZÿº[ÿº\ÿºƒ\ÿ»ƒ]ÿ»ƒ^ÿ¼„_ÿ¼…`ÿ½†aÿ½‡bÿ½ˆbÿ¾ˆdÿ¾ˆeÿ¾Šfÿ¿Šgÿ¿‹gÿÀŒhÿÀŒjÿÁŽkÿÁlÿÁmÿÂnÿÑpÿÃ’pÿÃ’rÿÄ”rÿÅ”tÿÄ•uÿÆ–vÿÆ—wÿƘyÿÇ™zÿÈš{ÿÈ›|ÿÈœ}ÿÉÿÊž€ÿÊŸ‚ÿË ‚ÿË¡„ÿÌ¢†ÿÍ£†ÿͤˆÿÎ¥‰ÿΦ‹ÿΧŒÿШÿÏ©ŽÿЪÿÑ«’ÿѬ“ÿÒ­”ÿÒ¯–ÿÓ¯—ÿÔ±˜ÿÔ±šÿÕ³›ÿÕ³ÿ×µžÿ×¶ ÿ×·¡ÿظ£ÿع¤ÿÙ»¦ÿÚ»§ÿÚ¼¨ÿÛ½ªÿÜ¿«ÿÜÀ­ÿÝÁ®ÿݯÿÞðÿÞIJÿßųÿàÆµÿàǶÿáȸÿâʹÿâË»ÿâÌ»ÿãͽÿäξÿäÏÀÿåÐÂÿæÑÃÿçÒÄÿçÓÆÿèÔÇÿèÕÉÿéÖÊÿé×ËÿêØÍÿêÙÎÿëÚÏÿëÜÐÿìÜÑÿìÝÒÿíÞÔÿíßÖÿîà×ÿîáØÿðâÙÿïãÚÿðäÜÿðåÝÿñåÞÿòçßÿòçáÿòéáÿôéãÿôêäÿôëåÿõìæÿõíçÿõîéÿöîêÿöïêÿ÷ðìÿ÷ñìÿøòîÿøòïÿøóïÿøôñÿùõñÿúöóÿúöóÿû÷ôÿû÷õÿûøöÿûøöÿüùøÿýùøÿüúùÿüûúÿýüûÿýüûÿýüûÿþýýÿþýýÿþþýÿÿÿþÿÿÿÿÿejabberd-16.01/win32/CheckReqs1.ini0000644000232200023220000000113312645157216017230 0ustar debalancedebalance[Settings] NumFields=3 [Field 1] Type=label Left=0 Right=-1 Top=10 Bottom=70 Text="OpenSLL 0.9.7i or newer is not found on your computer.\r\n\r\nTo use SSL and TLS encryption you need an SSL certificate. You can create a selfsigned certificate with OpenSSL.\r\n\r\nOpenSLL installer can be downloaded from" [Field 2] Type=link Left=0 Right=-1 Top=74 Bottom=88 State=http://www.slproweb.com/products/Win32OpenSSL.html Text=http://www.slproweb.com/products/Win32OpenSSL.html [Field 3] Type=label Left=0 Right=-1 Top=93 Bottom=-10 Text="If you want to continue installing Ejabberd anyway, click Next." ejabberd-16.01/win32/ejabberd.ico0000644000232200023220000000427612645157216017043 0ustar debalancedebalance ¨( @„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿejabberd-16.01/win32/CheckService.ini0000644000232200023220000000046612645157216017645 0ustar debalancedebalance[Settings] NumFields=2 [Field 1] Type=label Left=0 Right=-1 Top=10 Bottom=50 Text="You are installing Ejabberd as Administrator.\r\n\r\nEjabberd will be installed as a Windows service." [Field 2] Type=checkbox Left=0 Right=-1 Top=50 Bottom=62 Text="Configure ejabberd service to start automatically" State=1 ejabberd-16.01/win32/CheckReqs1H.ini0000644000232200023220000000114012645157216017336 0ustar debalancedebalance[Settings] NumFields=3 [Field 1] Type=label Left=0 Right=-1 Top=10 Bottom=70 Text="OpenSLL 0.9.7i or newer is not found on your computer.\r\n\r\nTo use SSL and TLS encryption you need an SSL certificate. You can create a selfsigned certificate with OpenSSL.\r\n\r\nOpenSLL installer can be downloaded from" [Field 2] Type=link Left=0 Right=-1 Top=74 Bottom=88 State=http://www.slproweb.com/products/Win32OpenSSL.html Text=http://www.slproweb.com/products/Win32OpenSSL.html [Field 3] Type=checkbox Left=0 Right=-1 Top=93 Bottom=105 Text="I want to continue installing Ejabberd anyway" State=0 Flags=NOTIFY ejabberd-16.01/win32/CheckReqs.ini0000644000232200023220000000071512645157216017154 0ustar debalancedebalance[Settings] NumFields=2 [Field 1] Type=label Left=0 Right=-1 Top=10 Bottom=70 Text="Erlang OTP R10B-7 (version 5.4.9) or newer is required to install Ejabberd.\r\n\r\nIt is not found on your computer.\r\n\r\nPlease install Erlang OTP R10B-7 or newer before installing Ejabberd.\r\n\r\nIts installer can be downloaded from" [Field 2] Type=link Left=0 Right=-1 Top=74 Bottom=88 State=http://www.erlang.org/download.html Text=http://www.erlang.org/download.html ejabberd-16.01/win32/inetrc0000644000232200023220000000002312645157216016002 0ustar debalancedebalance{registry, win32}. ejabberd-16.01/win32/ejabberd.nsi0000644000232200023220000004064412645157216017061 0ustar debalancedebalance; NSIS Modern User Interface ; Ejabberd installation script ;-------------------------------- ;Include Modern UI !include "MUI.nsh" !include "ejabberd.nsh" ; All release specific parameters come from this ;-------------------------------- ;General ;Name and file !define PRODUCT "Ejabberd" Name ${PRODUCT} OutFile "${OUTFILEDIR}\${PRODUCT}-${VERSION}.exe" ShowInstDetails show ShowUninstDetails show !define MUI_ICON "ejabberd.ico" !define MUI_UNICON "ejabberd.ico" !define MUI_HEADERIMAGE !define MUI_HEADERIMAGE_BITMAP "ejabberd_header.bmp" !define MUI_WELCOMEFINISHPAGE_BITMAP "ejabberd_intro.bmp" ;-------------------------------- ;Configuration SetCompressor lzma ;-------------------------------- ;Reserve Files ReserveFile "ejabberd.ico" ReserveFile "ejabberd.ico" ReserveFile "ejabberd_header.bmp" ReserveFile "ejabberd_intro.bmp" !ifdef HACKED_INSTALLOPTIONS ReserveFile "CheckUserH.ini" ReserveFile "CheckReqs1H.ini" !else ReserveFile "CheckUser.ini" ReserveFile "CheckReqs1.ini" !endif ReserveFile "CheckReqs.ini" ReserveFile "CheckService.ini" !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS ;-------------------------------- ;Variables Var MUI_TEMP Var STARTMENU_FOLDER Var ADMIN Var ENABLE_SERVICE Var ERLANG_PATH Var ERLANG_VERSION Var REQUIRED_ERLANG_VERSION Var OPENSSL_PATH Var OPENSSL_VERSION Var REQUIRED_OPENSSL_VERSION Var ERLSRV ;---------------------------------------------------------- ;.onInit uses UserInfo plugin, so it's as high as possible Function .onInit StrCpy $REQUIRED_ERLANG_VERSION "5.4.9" StrCpy $REQUIRED_OPENSSL_VERSION "0.9.7c" ;Default installation folder StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCT}" ;Get installation folder from registry if available ClearErrors ReadRegStr $0 HKLM "SOFTWARE\${PRODUCT}" "" IfErrors 0 copydir ReadRegStr $0 HKCU "SOFTWARE\${PRODUCT}" "" IfErrors skipdir copydir: StrCpy $INSTDIR "$0" skipdir: ;Extract InstallOptions INI files !ifdef HACKED_INSTALLOPTIONS !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckUserH.ini" !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckReqs1H.ini" !else !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckUser.ini" !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckReqs1.ini" !endif !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckReqs.ini" !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckService.ini" ClearErrors UserInfo::GetName IfErrors admin Pop $0 UserInfo::GetAccountType Pop $1 StrCmp $1 "Admin" admin user admin: StrCpy $ADMIN 1 Goto skip user: StrCpy $ADMIN 0 skip: FunctionEnd ;-------------------------------- ;Interface Settings !define MUI_ABORTWARNING ;-------------------------------- ;Installer/Uninstaller pages !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "..\..\COPYING" Page custom CheckReqs LeaveCheckReqs Page custom CheckReqs1 LeaveCheckReqs1 Page custom CheckUser LeaveCheckUser Page custom CheckService LeaveCheckService ;!insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_STARTMENU ${PRODUCT} $STARTMENU_FOLDER !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ;-------------------------------- ;Languages !insertmacro MUI_LANGUAGE "English" ;-------------------------------- ;Language Strings ;Description LangString DESC_SecEjabberd ${LANG_ENGLISH} "Erlang jabber server." ;-------------------------------- ;Installer Sections Section "Ejabberd" SecEjabberd SectionIn 1 RO SetOutPath "$INSTDIR" File /r "${TESTDIR}\doc" File /r "${TESTDIR}\ebin" File /r "${TESTDIR}\msgs" File /r "${TESTDIR}\win32" File "${TESTDIR}\*.dll" File "${TESTDIR}\inetrc" File /oname=ejabberd.cfg.example "${TESTDIR}\ejabberd.cfg" SetOverwrite off File "${TESTDIR}\ejabberd.cfg" SetOverwrite on ;File /r "${TESTDIR}\src" CreateDirectory "$INSTDIR\log" ;The startmenu stuff !insertmacro MUI_STARTMENU_WRITE_BEGIN ${PRODUCT} ;Create shortcuts StrCpy $0 "$SMPROGRAMS\$STARTMENU_FOLDER" CreateDirectory "$0" CreateShortCut "$0\Start Ejabberd.lnk" "$ERLANG_PATH\bin\werl.exe" \ '-sname ejabberd -pa ebin \ -env EJABBERD_LOG_PATH log/ejabberd.log \ -s ejabberd -kernel inetrc \"./inetrc\" -mnesia dir \"spool\" \ -sasl sasl_error_logger {file,\"log/erlang.log\"}' \ $INSTDIR\win32\ejabberd.ico CreateShortCut "$0\Edit Config.lnk" "%SystemRoot%\system32\notepad.exe" \ "$INSTDIR\ejabberd.cfg" CreateShortCut "$0\Read Docs.lnk" "$INSTDIR\doc\guide.html" CreateShortCut "$0\Uninstall.lnk" "$INSTDIR\Uninstall.exe" !insertmacro MUI_STARTMENU_WRITE_END ;Create Windows service StrCmp $ADMIN 1 0 skipservice StrCpy $ERLSRV "" Push $ERLANG_PATH Push erlsrv.exe GetFunctionAddress $0 FFCallback Push $0 Call FindFiles StrCmp $ERLSRV "" skipservice nsExec::Exec '"$ERLSRV" list ejabberd' Pop $0 StrCmp $0 "error" skipservice StrCmp $0 "0" 0 installsrv nsExec::ExecToLog '"$ERLSRV" remove ejabberd' Pop $0 installsrv: nsExec::ExecToLog '"$ERLSRV" add ejabberd -stopaction "init:stop()." \ -onfail restart -workdir "$INSTDIR" \ -args "-s ejabberd -pa ebin \ -kernel inetrc \\\"./inetrc\\\" \ -env EJABBERD_LOG_PATH log/ejabberd.log \ -sasl sasl_error_logger {file,\\\"log/erlang.log\\\"} \ -mnesia dir \\\"spool\\\"" -d' Pop $0 StrCmp $ENABLE_SERVICE 0 0 skipservice nsExec::ExecToLog '"$ERLSRV" disable ejabberd' Pop $0 skipservice: ;Create uninstaller WriteUninstaller "$INSTDIR\Uninstall.exe" StrCpy $1 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT}" StrCmp $ADMIN 1 admin2 WriteRegStr HKCU "Software\${PRODUCT}" "" "$INSTDIR" WriteRegStr HKCU "$1" "DisplayName" "${PRODUCT} ${VERSION}" WriteRegStr HKCU "$1" "UninstallString" "$INSTDIR\Uninstall.exe" WriteRegDWORD HKCU "$1" "NoModify" 1 WriteRegDWORD HKCU "$1" "NoRepair" 1 Goto done2 admin2: WriteRegStr HKLM "Software\${PRODUCT}" "" "$INSTDIR" WriteRegStr HKLM "Software\${PRODUCT}" "Erlsrv" "$ERLSRV" WriteRegStr HKLM "$1" "DisplayName" "${PRODUCT} ${VERSION}" WriteRegStr HKLM "$1" "UninstallString" "$INSTDIR\Uninstall.exe" WriteRegDWORD HKLM "$1" "NoModify" 1 WriteRegDWORD HKLM "$1" "NoRepair" 1 done2: SectionEnd ; SecEjabberd Function FFCallback Exch $0 StrCpy $ERLSRV $0 Pop $0 Push "stop" FunctionEnd ;-------------------------------- ;Descriptions !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecEjabberd} $(DESC_SecEjabberd) !insertmacro MUI_FUNCTION_DESCRIPTION_END ;-------------------------------- ;Uninstaller Section Section "Uninstall" ClearErrors UserInfo::GetName IfErrors admin Pop $0 UserInfo::GetAccountType Pop $1 StrCmp $1 "Admin" admin StrCpy $ADMIN 0 Goto skipservice admin: StrCpy $ADMIN 1 ReadRegStr $ERLSRV HKLM "Software\${PRODUCT}" "Erlsrv" nsExec::Exec '"$ERLSRV" list ejabberd' Pop $0 StrCmp $0 "error" skipservice StrCmp $0 "0" 0 skipservice nsExec::ExecToLog '"$ERLSRV" remove ejabberd' Pop $0 skipservice: RMDir /r "$INSTDIR\doc" RMDir /r "$INSTDIR\ebin" RMDir /r "$INSTDIR\msgs" RMDir /r "$INSTDIR\win32" ;RMDir /r "$INSTDIR\src" RMDir /r "$INSTDIR\log" Delete "$INSTDIR\*.dll" Delete "$INSTDIR\inetrc" Delete "$INSTDIR\ejabberd.cfg.example" Delete "$INSTDIR\Uninstall.exe" RMDir "$INSTDIR" !insertmacro MUI_STARTMENU_GETFOLDER ${PRODUCT} $MUI_TEMP Delete "$SMPROGRAMS\$MUI_TEMP\Start Ejabberd.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\Edit Config.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\Read Docs.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" ;Delete empty start menu parent diretories StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" startMenuDeleteLoop: RMDir $MUI_TEMP GetFullPathName $MUI_TEMP "$MUI_TEMP\.." IfErrors startMenuDeleteLoopDone StrCmp $MUI_TEMP $SMPROGRAMS startMenuDeleteLoopDone startMenuDeleteLoop startMenuDeleteLoopDone: StrCpy $1 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT}" StrCmp $ADMIN 1 admin1 DeleteRegKey HKCU "Software\${PRODUCT}" DeleteRegKey HKCU $1 Goto done admin1: DeleteRegKey HKLM "Software\${PRODUCT}" DeleteRegKey HKLM $1 done: SectionEnd LangString TEXT_CU_TITLE ${LANG_ENGLISH} "Checking User Privileges" LangString TEXT_CU_SUBTITLE ${LANG_ENGLISH} "Checking user privileged required to install Ejabberd." Function CheckUser StrCmp $ADMIN 1 0 showpage Abort showpage: !insertmacro MUI_HEADER_TEXT $(TEXT_CU_TITLE) $(TEXT_CU_SUBTITLE) !ifdef HACKED_INSTALLOPTIONS !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckUserH.ini" !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckUserH.ini" "Field 2" "State" GetDlgItem $1 $HWNDPARENT 1 EnableWindow $1 $0 !else !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckUser.ini" !endif !insertmacro MUI_INSTALLOPTIONS_SHOW FunctionEnd Function LeaveCheckUser !ifdef HACKED_INSTALLOPTIONS !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckUserH.ini" "Settings" "State" StrCmp $0 0 validate ;Next button? StrCmp $0 2 checkbox ;checkbox? Abort ;Return to the page checkbox: !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckUserH.ini" "Field 2" "State" GetDlgItem $1 $HWNDPARENT 1 EnableWindow $1 $0 Abort validate: !endif FunctionEnd LangString TEXT_CU_TITLE ${LANG_ENGLISH} "Configuring Ejabberd Service" LangString TEXT_CU_SUBTITLE ${LANG_ENGLISH} "Configuring Ejabberd Service." Function CheckService StrCmp $ADMIN 0 0 showpage Abort showpage: !insertmacro MUI_HEADER_TEXT $(TEXT_CU_TITLE) $(TEXT_CU_SUBTITLE) !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckService.ini" !insertmacro MUI_INSTALLOPTIONS_SHOW FunctionEnd Function LeaveCheckService !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckService.ini" "Field 2" "State" StrCmp $0 0 0 autostart StrCpy $ENABLE_SERVICE 0 Goto endfun autostart: StrCpy $ENABLE_SERVICE 1 endfun: FunctionEnd LangString TEXT_CR_TITLE ${LANG_ENGLISH} "Unsatisfied Requirements" LangString TEXT_CR_SUBTITLE ${LANG_ENGLISH} "Unsatisfied Ejabberd requirements found." Function CheckReqs Push "HKLM" Call FindErlang Pop $ERLANG_PATH Pop $ERLANG_VERSION StrCmp $ERLANG_PATH "" 0 abort Push "HKCU" Call FindErlang Pop $ERLANG_PATH Pop $ERLANG_VERSION StrCmp $ERLANG_PATH "" 0 abort !insertmacro MUI_HEADER_TEXT $(TEXT_CR_TITLE) $(TEXT_CR_SUBTITLE) !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckReqs.ini" GetDlgItem $R0 $HWNDPARENT 1 EnableWindow $R0 0 !insertmacro MUI_INSTALLOPTIONS_SHOW abort: Abort FunctionEnd Function LeaveCheckReqs Abort FunctionEnd Function CheckReqs1 Push "HKLM" Call FindOpenSSL Pop $OPENSSL_PATH Pop $OPENSSL_VERSION StrCmp $OPENSSL_PATH "" 0 abort Push "HKCU" Call FindOpenSSL Pop $OPENSSL_PATH Pop $OPENSSL_VERSION StrCmp $OPENSSL_PATH "" 0 abort !insertmacro MUI_HEADER_TEXT $(TEXT_CR_TITLE) $(TEXT_CR_SUBTITLE) !ifdef HACKED_INSTALLOPTIONS !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckReqs1H.ini" !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckReqs1H.ini" "Field 3" "State" GetDlgItem $1 $HWNDPARENT 1 EnableWindow $1 $0 !else !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckReqs1.ini" !endif !insertmacro MUI_INSTALLOPTIONS_SHOW abort: Abort FunctionEnd Function LeaveCheckReqs1 !ifdef HACKED_INSTALLOPTIONS !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckReqs1H.ini" "Settings" "State" StrCmp $0 0 validate ;Next button? StrCmp $0 3 checkbox ;checkbox? Abort ;Return to the page checkbox: !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckReqs1H.ini" "Field 3" "State" GetDlgItem $1 $HWNDPARENT 1 EnableWindow $1 $0 Abort validate: !endif FunctionEnd Function FindErlang Exch $R0 Push $R1 Push $R2 Push $R3 Push $R4 Push $R5 StrCpy $R1 0 StrCpy $R2 "SOFTWARE\Ericsson\Erlang" loop: StrCmp $R0 HKLM h1 EnumRegKey $R3 HKCU $R2 $R1 Goto l1 h1: EnumRegKey $R3 HKLM $R2 $R1 l1: IntOp $R1 $R1 + 1 StrCmp $R3 "" endloop ClearErrors StrCmp $R0 HKLM h2 ReadRegStr $R4 HKCU "$R2\$R3" "" Goto l2 h2: ReadRegStr $R4 HKLM "$R2\$R3" "" l2: IfFileExists "$R4\bin\erl.exe" 0 loop Push $REQUIRED_ERLANG_VERSION Push $R3 Call CompareVersions Pop $R5 StrCmp $R5 1 get Goto loop endloop: StrCpy $R4 "" get: StrCpy $R0 $R4 StrCpy $R1 $R3 Pop $R5 Pop $R4 Pop $R3 Pop $R2 Exch $R1 Exch Exch $R0 FunctionEnd Function FindOpenSSL Exch $R0 Push $R1 Push $R2 Push $R3 Push $R4 Push $R5 StrCpy $R1 0 StrCpy $R2 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenSSL_is1" StrCmp $R0 HKLM h1 ReadRegStr $R3 HKCU "$R2" "DisplayName" ReadRegStr $R4 HKCU "$R2" "Inno Setup: App Path" Goto l1 h1: ReadRegStr $R3 HKLM "$R2" "DisplayName" ReadRegStr $R4 HKLM "$R2" "Inno Setup: App Path" l1: IfFileExists "$R4\bin\openssl.exe" 0 notfound Goto get ; TODO check version ;Push $REQUIRED_OPENSSL_VERSION ;Push $R3 ;Call CompareVersions ;Pop $R5 ;StrCmp $R5 1 get notfound: StrCpy $R4 "" get: StrCpy $R0 $R4 StrCpy $R1 $R3 Pop $R5 Pop $R4 Pop $R3 Pop $R2 Exch $R1 Exch Exch $R0 FunctionEnd ;---------------------------------------------------------------------- ; CompareVersions ; input: ; top of stack = existing version ; top of stack-1 = needed version ; output: ; top of stack = 1 if current version => neded version, else 0 ; version is a string in format "xx.xx.xx.xx" (number of interger sections ; can be different in needed and existing versions) Function CompareVersions ; stack: existing ver | needed ver Exch $R0 Exch Exch $R1 ; stack: $R1|$R0 Push $R1 Push $R0 ; stack: e|n|$R1|$R0 ClearErrors loop: IfErrors VersionNotFound Strcmp $R0 "" VersionTestEnd Call ParseVersion Pop $R0 Exch Call ParseVersion Pop $R1 Exch IntCmp $R1 $R0 +1 VersionOk VersionNotFound Pop $R0 Push $R0 goto loop VersionTestEnd: Pop $R0 Pop $R1 Push $R1 Push $R0 StrCmp $R0 $R1 VersionOk VersionNotFound VersionNotFound: StrCpy $R0 "0" Goto end VersionOk: StrCpy $R0 "1" end: ; stack: e|n|$R1|$R0 Exch $R0 Pop $R0 Exch $R0 ; stack: res|$R1|$R0 Exch ; stack: $R1|res|$R0 Pop $R1 ; stack: res|$R0 Exch Pop $R0 ; stack: res FunctionEnd ;----------------------------------------------------------------------- ; ParseVersion ; input: ; top of stack = version string ("xx.xx.xx.xx") ; output: ; top of stack = first number in version ("xx") ; top of stack-1 = rest of the version string ("xx.xx.xx") Function ParseVersion Exch $R1 ; version Push $R2 Push $R3 StrCpy $R2 1 loop: StrCpy $R3 $R1 1 $R2 StrCmp $R3 "." loopend StrLen $R3 $R1 IntCmp $R3 $R2 loopend loopend IntOp $R2 $R2 + 1 Goto loop loopend: Push $R1 StrCpy $R1 $R1 $R2 Exch $R1 StrLen $R3 $R1 IntOp $R3 $R3 - $R2 IntOp $R2 $R2 + 1 StrCpy $R1 $R1 $R3 $R2 Push $R1 Exch 2 Pop $R3 Exch 2 Pop $R2 Exch 2 Pop $R1 FunctionEnd Function FindFiles Exch $R5 # callback function Exch Exch $R4 # file name Exch 2 Exch $R0 # directory Push $R1 Push $R2 Push $R3 Push $R6 Push $R0 # first dir to search StrCpy $R3 1 nextDir: Pop $R0 IntOp $R3 $R3 - 1 ClearErrors FindFirst $R1 $R2 "$R0\*.*" nextFile: StrCmp $R2 "." gotoNextFile StrCmp $R2 ".." gotoNextFile StrCmp $R2 $R4 0 isDir Push "$R0\$R2" Call $R5 Pop $R6 StrCmp $R6 "stop" 0 isDir loop: StrCmp $R3 0 done Pop $R0 IntOp $R3 $R3 - 1 Goto loop isDir: IfFileExists "$R0\$R2\*.*" 0 gotoNextFile IntOp $R3 $R3 + 1 Push "$R0\$R2" gotoNextFile: FindNext $R1 $R2 IfErrors 0 nextFile done: FindClose $R1 StrCmp $R3 0 0 nextDir Pop $R6 Pop $R3 Pop $R2 Pop $R1 Pop $R0 Pop $R5 Pop $R4 FunctionEnd ejabberd-16.01/win32/CheckUserH.ini0000644000232200023220000000053612645157216017271 0ustar debalancedebalance[Settings] NumFields=2 [Field 1] Type=label Left=0 Right=-1 Top=10 Bottom=50 Text="Administrator privileges are recommended for Ejabberd install.\r\n\r\nOtherwise installing Ejabberd as a service will be impossible." [Field 2] Type=checkbox Left=0 Right=-1 Top=50 Bottom=62 Text="I want to continue installing Ejabberd anyway" State=0 Flags=NOTIFY ejabberd-16.01/ejabberd.yml.example0000644000232200023220000003677512645157216017573 0ustar debalancedebalance### ###' ejabberd configuration file ### ### ### The parameters used in this configuration file are explained in more detail ### in the ejabberd Installation and Operation Guide. ### Please consult the Guide in case of doubts, it is included with ### your copy of ejabberd, and is also available online at ### http://www.process-one.net/en/ejabberd/docs/ ### The configuration file is written in YAML. ### Refer to http://en.wikipedia.org/wiki/YAML for the brief description. ### However, ejabberd treats different literals as different types: ### ### - unquoted or single-quoted strings. They are called "atoms". ### Example: dog, 'Jupiter', '3.14159', YELLOW ### ### - numeric literals. Example: 3, -45.0, .0 ### ### - quoted or folded strings. ### Examples of quoted string: "Lizzard", "orange". ### Example of folded string: ### > Art thou not Romeo, ### and a Montague? ###. ======= ###' LOGGING ## ## loglevel: Verbosity of log files generated by ejabberd. ## 0: No ejabberd log at all (not recommended) ## 1: Critical ## 2: Error ## 3: Warning ## 4: Info ## 5: Debug ## loglevel: 4 ## ## rotation: Describe how to rotate logs. Either size and/or date can trigger ## log rotation. Setting count to N keeps N rotated logs. Setting count to 0 ## does not disable rotation, it instead rotates the file and keeps no previous ## versions around. Setting size to X rotate log when it reaches X bytes. ## To disable rotation set the size to 0 and the date to "" ## Date syntax is taken from the syntax newsyslog uses in newsyslog.conf. ## Some examples: ## $D0 rotate every night at midnight ## $D23 rotate every day at 23:00 hr ## $W0D23 rotate every week on Sunday at 23:00 hr ## $W5D16 rotate every week on Friday at 16:00 hr ## $M1D0 rotate on the first day of every month at midnight ## $M5D6 rotate on every 5th day of the month at 6:00 hr ## log_rotate_size: 10485760 log_rotate_date: "" log_rotate_count: 1 ## ## overload protection: If you want to limit the number of messages per second ## allowed from error_logger, which is a good idea if you want to avoid a flood ## of messages when system is overloaded, you can set a limit. ## 100 is ejabberd's default. log_rate_limit: 100 ## ## watchdog_admins: Only useful for developers: if an ejabberd process ## consumes a lot of memory, send live notifications to these XMPP ## accounts. ## ## 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 ## ## hosts: Domains served by ejabberd. ## You can define one or several, for example: ## hosts: ## - "example.net" ## - "example.com" ## - "example.org" ## hosts: - "localhost" ## ## route_subdomains: Delegate subdomains to other XMPP servers. ## For example, if this ejabberd serves example.org and you want ## to allow communication with an XMPP server called im.example.org. ## ## route_subdomains: s2s ###. =============== ###' LISTENING PORTS ## ## listen: The ports ejabberd will listen on, which service each is handled ## by and what options to start it with. ## listen: - port: 5222 module: ejabberd_c2s ## ## If TLS is compiled in and you installed a SSL ## certificate, specify the full path to the ## file and uncomment these lines: ## ## certfile: "/path/to/ssl.pem" ## starttls: true ## ## To enforce TLS encryption for client connections, ## use this instead of the "starttls" option: ## ## starttls_required: true ## ## Custom OpenSSL options ## ## protocol_options: ## - "no_sslv3" ## - "no_tlsv1" max_stanza_size: 65536 shaper: c2s_shaper access: c2s - port: 5269 module: ejabberd_s2s_in ## ## ejabberd_service: Interact with external components (transports, ...) ## ## - ## port: 8888 ## module: ejabberd_service ## access: all ## shaper_rule: fast ## ip: "127.0.0.1" ## hosts: ## "icq.example.org": ## password: "secret" ## "sms.example.org": ## password: "secret" ## ## ejabberd_stun: Handles STUN Binding requests ## ## - ## port: 3478 ## transport: udp ## module: ejabberd_stun ## ## To handle XML-RPC requests that provide admin credentials: ## ## - ## port: 4560 ## module: ejabberd_xmlrpc ## access_commands: {} - port: 5280 module: ejabberd_http request_handlers: "/websocket": ejabberd_http_ws ## "/pub/archive": mod_http_fileserver web_admin: true http_bind: true ## register: true captcha: true ###. ================== ###' S2S GLOBAL OPTIONS ## ## s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections. ## Allowed values are: false optional required required_trusted ## You must specify a certificate file. ## ## s2s_use_starttls: optional ## ## s2s_certfile: Specify a certificate file. ## ## s2s_certfile: "/path/to/ssl.pem" ## Custom OpenSSL options ## ## s2s_protocol_options: ## - "no_sslv3" ## - "no_tlsv1" ## ## domain_certfile: Specify a different certificate for each served hostname. ## ## host_config: ## "example.org": ## domain_certfile: "/path/to/example_org.pem" ## "example.com": ## domain_certfile: "/path/to/example_com.pem" ## ## S2S whitelist or blacklist ## ## Default s2s policy for undefined hosts. ## ## s2s_access: s2s ## ## Outgoing S2S options ## ## Preferred address families (which to try first) and connect timeout ## in milliseconds. ## ## outgoing_s2s_families: ## - ipv4 ## - ipv6 ## outgoing_s2s_timeout: 10000 ###. ============== ###' AUTHENTICATION ## ## auth_method: Method used to authenticate the users. ## The default method is the internal. ## If you want to use a different method, ## comment this line and enable the correct ones. ## auth_method: internal ## ## Store the plain passwords or hashed for SCRAM: ## auth_password_format: plain ## auth_password_format: scram ## ## Define the FQDN if ejabberd doesn't detect it: ## fqdn: "server3.example.com" ## ## Authentication using external script ## Make sure the script is executable by ejabberd. ## ## auth_method: external ## extauth_program: "/path/to/authentication/script" ## ## Authentication using ODBC ## Remember to setup a database in the next section. ## ## auth_method: odbc ## ## Authentication using PAM ## ## auth_method: pam ## pam_service: "pamservicename" ## ## Authentication using LDAP ## ## auth_method: ldap ## ## List of LDAP servers: ## ldap_servers: ## - "localhost" ## ## Encryption of connection to LDAP servers: ## ldap_encrypt: none ## ldap_encrypt: tls ## ## Port to connect to on LDAP servers: ## ldap_port: 389 ## ldap_port: 636 ## ## LDAP manager: ## ldap_rootdn: "dc=example,dc=com" ## ## Password of LDAP manager: ## ldap_password: "******" ## ## Search base of LDAP directory: ## ldap_base: "dc=example,dc=com" ## ## LDAP attribute that holds user ID: ## ldap_uids: ## - "mail": "%u@mail.example.org" ## ## LDAP filter: ## ldap_filter: "(objectClass=shadowAccount)" ## ## Anonymous login support: ## auth_method: anonymous ## anonymous_protocol: sasl_anon | login_anon | both ## allow_multiple_connections: true | false ## ## host_config: ## "public.example.org": ## auth_method: anonymous ## allow_multiple_connections: false ## anonymous_protocol: sasl_anon ## ## To use both anonymous and internal authentication: ## ## host_config: ## "public.example.org": ## auth_method: ## - internal ## - anonymous ###. ============== ###' DATABASE SETUP ## ejabberd by default uses the internal Mnesia database, ## so you do not necessarily need this section. ## This section provides configuration examples in case ## you want to use other database backends. ## Please consult the ejabberd Guide for details on database creation. ## ## MySQL server: ## ## odbc_type: mysql ## odbc_server: "server" ## odbc_database: "database" ## odbc_username: "username" ## odbc_password: "password" ## ## If you want to specify the port: ## odbc_port: 1234 ## ## PostgreSQL server: ## ## odbc_type: pgsql ## odbc_server: "server" ## odbc_database: "database" ## odbc_username: "username" ## odbc_password: "password" ## ## If you want to specify the port: ## odbc_port: 1234 ## ## If you use PostgreSQL, have a large database, and need a ## faster but inexact replacement for "select count(*) from users" ## ## pgsql_users_number_estimate: true ## ## SQLite: ## ## odbc_type: sqlite ## odbc_database: "/path/to/database.db" ## ## ODBC compatible or MSSQL server: ## ## odbc_type: odbc ## odbc_server: "DSN=ejabberd;UID=ejabberd;PWD=ejabberd" ## ## Number of connections to open to the database for each virtual host ## ## odbc_pool_size: 10 ## ## Interval to make a dummy SQL request to keep the connections to the ## database alive. Specify in seconds: for example 28800 means 8 hours ## ## odbc_keepalive_interval: undefined ###. =============== ###' TRAFFIC SHAPERS shaper: ## ## The "normal" shaper limits traffic speed to 1000 B/s ## normal: 1000 ## ## The "fast" shaper limits traffic speed to 50000 B/s ## fast: 50000 ## ## This option specifies the maximum number of elements in the queue ## of the FSM. Refer to the documentation for details. ## max_fsm_queue: 1000 ###. ==================== ###' ACCESS CONTROL LISTS acl: ## ## The 'admin' ACL grants administrative privileges to XMPP accounts. ## You can put here as many accounts as you want. ## ## admin: ## user: ## - "aleksey": "localhost" ## - "ermine": "example.org" ## ## Blocked users ## ## blocked: ## user: ## - "baduser": "example.org" ## - "test" ## Local users: don't modify this. ## local: user_regexp: "" ## ## More examples of ACLs ## ## jabberorg: ## server: ## - "jabber.org" ## aleksey: ## user: ## - "aleksey": "jabber.ru" ## test: ## user_regexp: "^test" ## user_glob: "test*" ## ## Loopback network ## loopback: ip: - "127.0.0.0/8" ## ## Bad XMPP servers ## ## bad_servers: ## server: ## - "xmpp.zombie.org" ## - "xmpp.spam.com" ## ## Define specific ACLs in a virtual host. ## ## host_config: ## "localhost": ## acl: ## admin: ## user: ## - "bob-local": "localhost" ###. ============ ###' ACCESS RULES access: ## Maximum number of simultaneous sessions allowed for a single user: max_user_sessions: all: 10 ## Maximum number of offline messages that users can have: max_user_offline_messages: admin: 5000 all: 100 ## This rule allows access only for local users: local: local: allow ## Only non-blocked users can use c2s connections: c2s: blocked: deny all: allow ## For C2S connections, all users except admins use the "normal" shaper c2s_shaper: admin: none all: normal ## All S2S connections use the "fast" shaper s2s_shaper: all: fast ## Only admins can send announcement messages: announce: admin: allow ## Only admins can use the configuration interface: configure: admin: allow ## Admins of this server are also admins of the MUC service: muc_admin: admin: allow ## Only accounts of the local ejabberd server can create rooms: muc_create: local: allow ## All users are allowed to use the MUC service: muc: all: allow ## Only accounts on the local ejabberd server can create Pubsub nodes: pubsub_createnode: local: allow ## In-band registration allows registration of any possible username. ## To disable in-band registration, replace 'allow' with 'deny'. register: all: allow ## Only allow to register from localhost trusted_network: loopback: allow ## Do not establish S2S connections with bad servers ## s2s: ## bad_servers: deny ## all: allow ## By default the frequency of account registrations from the same IP ## is limited to 1 account every 10 minutes. To disable, specify: infinity ## registration_timeout: 600 ## ## Define specific Access Rules in a virtual host. ## ## host_config: ## "localhost": ## access: ## c2s: ## admin: allow ## all: deny ## register: ## all: deny ###. ================ ###' DEFAULT LANGUAGE ## ## language: Default language used for server messages. ## language: "en" ## ## Set a different default language in a virtual host. ## ## host_config: ## "localhost": ## language: "ru" ###. ======= ###' CAPTCHA ## ## Full path to a script that generates the image. ## ## captcha_cmd: "/lib/ejabberd/priv/bin/captcha.sh" ## ## Host for the URL and port where ejabberd listens for CAPTCHA requests. ## ## captcha_host: "example.org:5280" ## ## Limit CAPTCHA calls per minute for JID/IP to avoid DoS. ## ## captcha_limit: 5 ###. ======= ###' MODULES ## ## Modules enabled in all ejabberd virtual hosts. ## modules: mod_adhoc: {} ## mod_admin_extra: {} mod_announce: # recommends mod_adhoc access: announce mod_blocking: {} # requires mod_privacy mod_caps: {} mod_carboncopy: {} mod_client_state: {} mod_configure: {} # requires mod_adhoc mod_disco: {} ## mod_echo: {} mod_irc: {} mod_http_bind: {} ## mod_http_fileserver: ## docroot: "/var/www" ## accesslog: "/var/log/ejabberd/access.log" mod_last: {} mod_muc: ## host: "conference.@HOST@" access: muc access_create: muc_create access_persistent: muc_create access_admin: muc_admin ## mod_muc_log: {} ## mod_multicast: {} mod_offline: access_max_user_messages: max_user_offline_messages mod_ping: {} ## mod_pres_counter: ## count: 5 ## interval: 60 mod_privacy: {} mod_private: {} ## mod_proxy65: {} mod_pubsub: access_createnode: pubsub_createnode ## reduces resource comsumption, but XEP incompliant ignore_pep_from_offline: true ## XEP compliant, but increases resource comsumption ## ignore_pep_from_offline: false last_item_cache: false plugins: - "flat" - "hometree" - "pep" # pep requires mod_caps mod_register: ## ## Protect In-Band account registrations with CAPTCHA. ## ## captcha_protected: true ## ## Set the minimum informational entropy for passwords. ## ## 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. ## ## When a user registers, send a notification to ## these XMPP accounts. ## ## registration_watchers: ## - "admin1@example.org" ## ## Only clients in the server machine can register accounts ## ip_access: trusted_network ## ## Local c2s or remote s2s users cannot register accounts ## ## access_from: deny access: register mod_roster: {} mod_shared_roster: {} mod_stats: {} mod_time: {} mod_vcard: search: false mod_version: {} ## ## Enable modules with custom options in a specific virtual host ## ## host_config: ## "localhost": ## modules: ## mod_echo: ## host: "mirror.localhost" ## ## Enable modules management via ejabberdctl for installation and ## uninstallation of public/private contributed modules ## (enabled by default) ## allow_contrib_modules: true ###. ###' ### Local Variables: ### mode: yaml ### End: ### vim: set filetype=yaml tabstop=8 foldmarker=###',###. foldmethod=marker: ejabberd-16.01/ejabberdctl.cfg.example0000644000232200023220000001314412645157216020215 0ustar debalancedebalance# # In this file you can configure options that are passed by ejabberdctl # to the erlang runtime system when starting ejabberd # #' POLL: Kernel polling ([true|false]) # # The kernel polling option requires support in the kernel. # Additionally, you need to enable this feature while compiling Erlang. # # Default: true # #POLL=true #. #' SMP: SMP support ([enable|auto|disable]) # # Explanation in Erlang/OTP documentation: # enable: starts the Erlang runtime system with SMP support enabled. # This may fail if no runtime system with SMP support is available. # auto: starts the Erlang runtime system with SMP support enabled if it # is available and more than one logical processor are detected. # disable: starts a runtime system without SMP support. # # Default: auto # #SMP=auto #. #' ERL_MAX_PORTS: Maximum number of simultaneously open Erlang ports # # ejabberd consumes two or three ports for every connection, either # from a client or from another Jabber server. So take this into # account when setting this limit. # # Default: 32000 # Maximum: 268435456 # #ERL_MAX_PORTS=32000 #. #' FIREWALL_WINDOW: Range of allowed ports to pass through a firewall # # If Ejabberd is configured to run in cluster, and a firewall is blocking ports, # it's possible to make Erlang use a defined range of port (instead of dynamic # ports) for node communication. # # Default: not defined # Example: 4200-4210 # #FIREWALL_WINDOW= #. #' INET_DIST_INTERFACE: IP address where this Erlang node listens other nodes # # This communication is used by ejabberdctl command line tool, # and in a cluster of several ejabberd nodes. # # Default: 0.0.0.0 # #INET_DIST_INTERFACE=127.0.0.1 #. #' ERL_EPMD_ADDRESS: IP addresses where epmd listens for connections # # IMPORTANT: This option works only in Erlang/OTP R14B03 and newer. # # This environment variable may be set to a comma-separated # list of IP addresses, in which case the epmd daemon # will listen only on the specified address(es) and on the # loopback address (which is implicitly added to the list if it # has not been specified). The default behaviour is to listen on # all available IP addresses. # # Default: 0.0.0.0 # #ERL_EPMD_ADDRESS=127.0.0.1 #. #' ERL_PROCESSES: Maximum number of Erlang processes # # Erlang consumes a lot of lightweight processes. If there is a lot of activity # on ejabberd so that the maximum number of processes is reached, people will # experience greater latency times. As these processes are implemented in # Erlang, and therefore not related to the operating system processes, you do # not have to worry about allowing a huge number of them. # # Default: 250000 # Maximum: 268435456 # #ERL_PROCESSES=250000 #. #' ERL_MAX_ETS_TABLES: Maximum number of ETS and Mnesia tables # # The number of concurrent ETS and Mnesia tables is limited. When the limit is # reached, errors will appear in the logs: # ** Too many db tables ** # You can safely increase this limit when starting ejabberd. It impacts memory # consumption but the difference will be quite small. # # Default: 1400 # #ERL_MAX_ETS_TABLES=1400 #. #' ERL_OPTIONS: Additional Erlang options # # The next variable allows to specify additional options passed to erlang while # starting ejabberd. Some useful options are -noshell, -detached, -heart. When # ejabberd is started from an init.d script options -noshell and -detached are # added implicitly. See erl(1) for more info. # # It might be useful to add "-pa /usr/local/lib/ejabberd/ebin" if you # want to add local modules in this path. # # Default: "" # #ERL_OPTIONS="" #. #' ERLANG_NODE: Erlang node name # # The next variable allows to explicitly specify erlang node for ejabberd # It can be given in different formats: # ERLANG_NODE=ejabberd # Lets erlang add hostname to the node (ejabberd uses short name in this case) # ERLANG_NODE=ejabberd@hostname # Erlang uses node name as is (so make sure that hostname is a real # machine hostname or you'll not be able to control ejabberd) # ERLANG_NODE=ejabberd@hostname.domainname # The same as previous, but erlang will use long hostname # (see erl (1) manual for details) # # Default: ejabberd@localhost # #ERLANG_NODE=ejabberd@localhost #. #' EJABBERD_PID_PATH: ejabberd PID file # # Indicate the full path to the ejabberd Process identifier (PID) file. # If this variable is defined, ejabberd writes the PID file when starts, # and deletes it when stops. # Remember to create the directory and grant write permission to ejabberd. # # Default: don't write PID file # #EJABBERD_PID_PATH=/var/run/ejabberd/ejabberd.pid #. #' EJABBERD_CONFIG_PATH: ejabberd configuration file # # Specify the full path to the ejabberd configuration file. If the file name has # yml or yaml extension, it is parsed as a YAML file; otherwise, Erlang syntax is # expected. # # Default: $ETC_DIR/ejabberd.yml # #EJABBERD_CONFIG_PATH=/etc/ejabberd/ejabberd.yml #. #' CONTRIB_MODULES_PATH: contributed ejabberd modules path # # Specify the full path to the contributed ejabberd modules. If the path is not # defined, ejabberd will use ~/.ejabberd-modules in home of user running ejabberd. # # Default: $HOME/.ejabberd-modules # #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: ejabberd-16.01/m4/0000755000232200023220000000000012645157216014156 5ustar debalancedebalanceejabberd-16.01/m4/ax_lib_sqlite3.m40000644000232200023220000001177512645157216017335 0ustar debalancedebalance# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_lib_sqlite3.html # =========================================================================== # # SYNOPSIS # # AX_LIB_SQLITE3([MINIMUM-VERSION]) # # DESCRIPTION # # Test for the SQLite 3 library of a particular version (or newer) # # This macro takes only one optional argument, required version of SQLite # 3 library. If required version is not passed, 3.0.0 is used in the test # of existance of SQLite 3. # # If no intallation prefix to the installed SQLite library is given the # macro searches under /usr, /usr/local, and /opt. # # This macro calls: # # AC_SUBST(SQLITE3_CFLAGS) # AC_SUBST(SQLITE3_LDFLAGS) # AC_SUBST(SQLITE3_VERSION) # # And sets: # # HAVE_SQLITE3 # # LICENSE # # Copyright (c) 2008 Mateusz Loskot # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 14 AC_DEFUN([AX_LIB_SQLITE3], [ AC_ARG_WITH([sqlite3], AS_HELP_STRING( [--with-sqlite3=@<:@ARG@:>@], [use SQLite 3 library @<:@default=yes@:>@, optionally specify the prefix for sqlite3 library] ), [ if test "$withval" = "no"; then WANT_SQLITE3="no" elif test "$withval" = "yes"; then WANT_SQLITE3="yes" ac_sqlite3_path="" else WANT_SQLITE3="yes" ac_sqlite3_path="$withval" fi ], [WANT_SQLITE3="yes"] ) SQLITE3_CFLAGS="" SQLITE3_LDFLAGS="" SQLITE3_VERSION="" if test "x$WANT_SQLITE3" = "xyes"; then ac_sqlite3_header="sqlite3.h" sqlite3_version_req=ifelse([$1], [], [3.0.0], [$1]) sqlite3_version_req_shorten=`expr $sqlite3_version_req : '\([[0-9]]*\.[[0-9]]*\)'` sqlite3_version_req_major=`expr $sqlite3_version_req : '\([[0-9]]*\)'` sqlite3_version_req_minor=`expr $sqlite3_version_req : '[[0-9]]*\.\([[0-9]]*\)'` sqlite3_version_req_micro=`expr $sqlite3_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` if test "x$sqlite3_version_req_micro" = "x" ; then sqlite3_version_req_micro="0" fi sqlite3_version_req_number=`expr $sqlite3_version_req_major \* 1000000 \ \+ $sqlite3_version_req_minor \* 1000 \ \+ $sqlite3_version_req_micro` AC_MSG_CHECKING([for SQLite3 library >= $sqlite3_version_req]) if test "$ac_sqlite3_path" != ""; then ac_sqlite3_ldflags="-L$ac_sqlite3_path/lib" ac_sqlite3_cppflags="-I$ac_sqlite3_path/include" else for ac_sqlite3_path_tmp in /usr /usr/local /opt ; do if test -f "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header" \ && test -r "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header"; then ac_sqlite3_path=$ac_sqlite3_path_tmp ac_sqlite3_cppflags="-I$ac_sqlite3_path_tmp/include" ac_sqlite3_ldflags="-L$ac_sqlite3_path_tmp/lib" break; fi done fi ac_sqlite3_ldflags="$ac_sqlite3_ldflags -lsqlite3" saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $ac_sqlite3_cppflags" AC_LANG_PUSH(C) AC_COMPILE_IFELSE( [ AC_LANG_PROGRAM([[@%:@include ]], [[ #if (SQLITE_VERSION_NUMBER >= $sqlite3_version_req_number) /* Everything is okay */ #else # error SQLite version is too old #endif ]] ) ], [ AC_MSG_RESULT([yes]) success="yes" ], [ AC_MSG_RESULT([not found]) success="no" ] ) AC_LANG_POP(C) CPPFLAGS="$saved_CPPFLAGS" if test "$success" = "yes"; then SQLITE3_CFLAGS="$ac_sqlite3_cppflags" SQLITE3_LDFLAGS="$ac_sqlite3_ldflags" ac_sqlite3_header_path="$ac_sqlite3_path/include/$ac_sqlite3_header" dnl Retrieve SQLite release version if test "x$ac_sqlite3_header_path" != "x"; then ac_sqlite3_version=`cat $ac_sqlite3_header_path \ | grep '#define.*SQLITE_VERSION.*\"' | sed -e 's/.* "//' \ | sed -e 's/"//'` if test $ac_sqlite3_version != ""; then SQLITE3_VERSION=$ac_sqlite3_version else AC_MSG_WARN([Cannot find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!]) fi fi AC_SUBST(SQLITE3_CFLAGS) AC_SUBST(SQLITE3_LDFLAGS) AC_SUBST(SQLITE3_VERSION) AC_DEFINE([HAVE_SQLITE3], [], [Have the SQLITE3 library]) fi fi ]) ejabberd-16.01/m4/erlang-extra.m40000644000232200023220000000544712645157216017023 0ustar debalancedebalancednl erlang-extra.m4 AC_DEFUN([ERLANG_SUBST_LIB_VER], [AC_ERLANG_CHECK_LIB([$1]) ERLANG_LIB_VER_SUBST="$ERLANG_LIB_VER_SUBST -e 's,[@]ERLANG_LIB_VER_$1[@],\$(ERLANG_LIB_VER_$1),g'" AC_SUBST([ERLANG_LIB_VER_SUBST]) ]) # ERLANG_SUBST_LIB_VER AC_DEFUN([ERLANG_VERSION_CHECK], [ AC_MSG_CHECKING([Erlang/OTP version]) cat > conftest.erl < ERTS = erlang:system_info(version), RequiredMin = "$1", RequiredMax = "$2", Status = case {string:tokens(RequiredMin, " "), string:tokens(RequiredMax, " ")} of {[[MinStr | _]], [[MaxStr | _]]} -> case check(ERTS, {MinStr, MaxStr}) of less -> list_to_binary([[ERTS, " found, ", RequiredMin, " required"]]); greater -> list_to_binary([[ERTS, " found, ", RequiredMax, " or earlier required"]]); ok -> <<"ok">> end; _ -> list_to_binary([[ERTS, " found, ", RequiredMin, " required"]]) end, file:write_file("conftest.out", Status), halt(). check(CurStr, {MinStr, MaxStr}) -> Cur = parse(CurStr), Min = parse(MinStr), Max = parse(MaxStr), case {less_or_equal(Min, Cur), less_or_equal(Cur, Max)} of {false, true} -> less; {true, true} -> ok; {true, false} -> greater end. parse(Version) -> lists:map(fun(A) -> {Int,[[]]} = string:to_integer(A), Int end, string:tokens(Version, ".")). less_or_equal([[]], [[]]) -> true; less_or_equal([[]], _Any) -> true; less_or_equal(_Any, [[]]) -> false; less_or_equal([[Left| Rl]], [[Right| Rr]]) -> case {Left < Right, Left == Right} of {true, _} -> true; {false, false} -> false; {false, true} -> less_or_equal(Rl, Rr) end. EOF $ERLC conftest.erl || AC_MSG_ERROR(["Could not compile Erlang/OTP version check program using '$ERLC'"]) if ! $ERL -s conftest -noshell -o ! -f conftest.out ; then AC_MSG_ERROR(["Could not run Erlang/OTP version check program using '$ERL'"]) fi if test "x`cat conftest.out`" != "xok"; then AC_MSG_RESULT([failed]) X="`cat conftest.out`" if test "[$3]" == "warn"; then AC_MSG_WARN([$X]) else AC_MSG_FAILURE([$X]) fi else AC_MSG_RESULT([ok]) fi ]) dnl ERLANG_VERSION_CHECK AC_DEFUN([ERLANG_DEPRECATED_TYPES_CHECK], [ AC_MSG_CHECKING([whether Erlang is using deprecated types]) cat > conftest.erl < /dev/null 2>&1; then AC_MSG_RESULT([no]) AC_SUBST(erlang_deprecated_types, false) else AC_MSG_RESULT([yes]) AC_SUBST(erlang_deprecated_types, true) fi ]) ejabberd-16.01/ejabberdctl.template0000755000232200023220000003602512645157216017645 0ustar debalancedebalance#!/bin/bash # define default configuration POLL=true SMP=auto ERL_MAX_PORTS=32000 ERL_PROCESSES=250000 ERL_MAX_ETS_TABLES=1400 FIREWALL_WINDOW="" ERLANG_NODE=ejabberd@localhost # define default environment variables SCRIPT_DIR=`cd ${0%/*} && pwd` 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 EXEC_CMD="false" for GID in `id -G`; do if [ $GID -eq 0 ] ; then INSTALLUSER_HOME=$(getent passwd "$INSTALLUSER" | cut -d: -f6) if [ -n "$INSTALLUSER_HOME" ] && [ ! -d "$INSTALLUSER_HOME" ] ; then mkdir -p "$INSTALLUSER_HOME" chown "$INSTALLUSER" "$INSTALLUSER_HOME" fi EXEC_CMD="su $INSTALLUSER -c" fi done if [ `id -g` -eq `id -g $INSTALLUSER` ] ; then EXEC_CMD="sh -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" fi # parse command line parameters declare -a ARGS=() while [ $# -ne 0 ] ; do PARAM="$1" 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 ;; --ctl-config) EJABBERDCTL_CONFIG_PATH="$1" ; shift ;; --logs) LOGS_DIR="$1" ; shift ;; --spool) SPOOL_DIR="$1" ; shift ;; *) ARGS=("${ARGS[@]}" "$PARAM") ;; esac done # Define ejabberd variable if they have not been defined from the command line if [ "$ETC_DIR" = "" ] ; then ETC_DIR={{sysconfdir}}/ejabberd fi if [ "$EJABBERDCTL_CONFIG_PATH" = "" ] ; then EJABBERDCTL_CONFIG_PATH=$ETC_DIR/ejabberdctl.cfg fi if [ -f "$EJABBERDCTL_CONFIG_PATH" ] ; then . "$EJABBERDCTL_CONFIG_PATH" fi if [ "$EJABBERD_CONFIG_PATH" = "" ] ; then EJABBERD_CONFIG_PATH=$ETC_DIR/ejabberd.yml fi if [ "$LOGS_DIR" = "" ] ; then LOGS_DIR={{localstatedir}}/log/ejabberd fi if [ "$SPOOL_DIR" = "" ] ; then SPOOL_DIR={{localstatedir}}/lib/ejabberd fi if [ "$EJABBERD_DOC_PATH" = "" ] ; then EJABBERD_DOC_PATH={{docdir}} fi if [ "$ERLANG_NODE_ARG" != "" ] ; then ERLANG_NODE=$ERLANG_NODE_ARG NODE=${ERLANG_NODE%@*} fi if [ "{{release}}" != "true" ] ; then if [ "$EJABBERDDIR" = "" ] ; then EJABBERDDIR={{libdir}}/ejabberd 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 fi EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log 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" KERNEL_OPTS="" if [ "$FIREWALL_WINDOW" != "" ] ; then KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" fi if [ "$INET_DIST_INTERFACE" != "" ] ; then INET_DIST_INTERFACE2="$(echo $INET_DIST_INTERFACE | sed 's/\./,/g')" if [ "$INET_DIST_INTERFACE" != "$INET_DIST_INTERFACE2" ] ; then INET_DIST_INTERFACE2="{$INET_DIST_INTERFACE2}" fi KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_use_interface \"${INET_DIST_INTERFACE2}\"" fi if [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] ; then NAME="-sname" else NAME="-name" fi IEXNAME="-$NAME" # define ejabberd environment parameters 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) 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) 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 "$EJABBERD_OPTS" ] || EJABBERD_OPTS="-ejabberd ${EJABBERD_OPTS}" [ -d $SPOOL_DIR ] || $EXEC_CMD "mkdir -p $SPOOL_DIR" cd $SPOOL_DIR # export global variables export EJABBERD_CONFIG_PATH export EJABBERD_LOG_PATH export EJABBERD_BIN_PATH export EJABBERD_DOC_PATH export EJABBERD_PID_PATH export ERL_CRASH_DUMP export ERL_EPMD_ADDRESS export ERL_INETRC export ERL_MAX_PORTS export ERL_MAX_ETS_TABLES 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 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 debug() { debugwarning TTY=`tty | sed -e 's/.*\///g'` 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 iexdebug() { debugwarning TTY=`tty | sed -e 's/.*\///g'` # 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 \"$@\"\"" $EXEC_CMD "$CMD" } # start interactive server live() { livewarning 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 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 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() { if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then echo "--------------------------------------------------------------------" echo "" echo "IMPORTANT: we will attempt to attach an INTERACTIVE shell" echo "to an already running ejabberd node." echo "If an ERROR is printed, it means the connection was not successful." echo "You can interact with the ejabberd node if you know how to use it." echo "Please be extremely cautious with your actions," echo "and exit immediately if you are not completely sure." echo "" echo "To detach this shell from ejabberd, press:" echo " control+c, control+c" echo "" echo "--------------------------------------------------------------------" echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" echo " EJABBERD_BYPASS_WARNINGS=true" echo "Press return to continue" read foo echo "" fi } livewarning() { check_start if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then echo "--------------------------------------------------------------------" echo "" echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode." echo "All log messages will be shown in the command shell." echo "You can interact with the ejabberd node if you know how to use it." echo "Please be extremely cautious with your actions," echo "and exit immediately if you are not completely sure." echo "" echo "To exit this LIVE mode and stop ejabberd, press:" echo " q(). and press the Enter key" echo "" echo "--------------------------------------------------------------------" echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" echo " EJABBERD_BYPASS_WARNINGS=true" echo "Press return to continue" read foo echo "" fi } 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 \ $KERNEL_OPTS $ERLANG_OPTS \ -eval 'io:format(\"~p~n\",[net_adm:ping($1)])' \ -s erlang halt -output text -noinput" } 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 " 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" echo " --config file Config ejabberd: $EJABBERD_CONFIG_PATH" echo " --ctl-config file Config ejabberdctl: $EJABBERDCTL_CONFIG_PATH" echo " --logs dir Directory for logs: $LOGS_DIR" echo " --spool dir Database spool dir: $SPOOL_DIR" echo " --node nodename ejabberd node name: $ERLANG_NODE" echo "" } # common control function ctl() { # Control number of connections identifiers # using flock if available. Expects a linux-style # flock that can lock a file descriptor. MAXCONNID=100 CONNLOCKDIR={{localstatedir}}/lock/ejabberdctl FLOCK=/usr/bin/flock if [ ! -x "$FLOCK" ] || [ ! -d "$CONNLOCKDIR" ] ; then JOT=/usr/bin/jot if [ ! -x "$JOT" ] ; then # no flock or jot, simply invoke ctlexec() CTL_CONN="ctl-${ERLANG_NODE}" 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 "$@" result=$? fi else # we have flock so we get a lock # on one of a limited number of # conn names -- this allows # concurrent invocations using a bound # number of atoms for N in `seq 1 $MAXCONNID`; do CTL_CONN="ejabberdctl-$N" CTL_LOCKFILE="$CONNLOCKDIR/$CTL_CONN" ( exec 8>"$CTL_LOCKFILE" if flock --nb 8; then ctlexec $CTL_CONN "$@" ssresult=$? # segregate from possible flock exit(1) ssresult=`expr $ssresult \* 10` exit $ssresult else exit 1 fi ) result=$? if [ $result -eq 1 ] ; then # means we errored out in flock # rather than in the exec - stay in the loop # trying other conn names... badlock=1 else badlock="" break; fi done result=`expr $result / 10` fi if [ "$badlock" ] ;then echo "Ran out of connections to try. Your ejabberd processes" >&2 echo "may be stuck or this is a very busy server. For very" >&2 echo "busy servers, consider raising MAXCONNID in ejabberdctl">&2 exit 1; fi case $result in 0) :;; 1) :;; 2) help;; 3) help;; esac return $result } ctlexec() { CONN_NAME=$1; shift 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 stop_epmd() { $EPMD -names 2>/dev/null | grep -q name || $EPMD -kill >/dev/null } # make sure node not already running and node name unregistered check_start() { $EPMD -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && { ps ux | grep -v grep | grep -q " $ERLANG_NODE " && { echo "ERROR: The ejabberd node '$ERLANG_NODE' is already running." exit 4 } || { ps ux | grep -v grep | grep -q beam && { echo "ERROR: The ejabberd node '$ERLANG_NODE' is registered," echo " but no related beam process has been found." echo "Shutdown all other erlang nodes, and call 'epmd -kill'." exit 5 } || { $EPMD -kill >/dev/null } } } } # allow sync calls wait_for_status() { # args: status try delay # return: 0 OK, 1 KO timeout=$2 status=4 while [ $status -ne $1 ] ; do sleep $3 timeout=`expr $timeout - 1` [ $timeout -eq 0 ] && { status=$1 } || { ctl status > /dev/null status=$? } done [ $timeout -eq 0 ] && return 1 || return 0 } # main handler 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 ejabberd-16.01/configure.bat0000644000232200023220000000045712645157216016315 0ustar debalancedebalance @if "x%1"=="x--help" goto usage @set arg=dynamic @if "x%1"=="x--static" set arg=static @echo Configuring for %arg% build... erlc configure.erl erl -s configure -env arg %arg% -noshell @goto end :usage @echo Usage: configure.bat @echo or configure.bat --static @echo or configure.bat --help :end ejabberd-16.01/mix.exs0000644000232200023220000000706512645157216015164 0ustar debalancedebalancedefmodule Ejabberd.Mixfile do use Mix.Project def project do [app: :ejabberd, version: "16.01.0", elixir: "~> 1.1", elixirc_paths: ["lib"], compile_path: ".", compilers: [:asn1] ++ Mix.compilers, erlc_options: erlc_options, erlc_paths: ["asn1", "src"], package: package, deps: deps] end def application do [mod: {:ejabberd_app, []}, 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 # 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 [{: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_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 [licenses: ["GPLv2"], links: %{"Site" => "https://www.ejabberd.im", "Documentation" => "http://docs.ejabberd.im", "Source" => "https://github.com/processone/ejabberd"}] end end defmodule Mix.Tasks.Compile.Asn1 do use Mix.Task alias Mix.Compilers.Erlang @recursive true @manifest ".compile.asn1" def run(args) do {opts, _, _} = OptionParser.parse(args, switches: [force: :boolean]) project = Mix.Project.config source_paths = project[:asn1_paths] || ["asn1"] dest_paths = project[:asn1_target] || ["src"] mappings = Enum.zip(source_paths, dest_paths) options = project[:asn1_options] || [] Erlang.compile(manifest(), mappings, :asn1, :erl, opts[:force], fn input, output -> 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 end end) end def manifests, do: [manifest] defp manifest, do: Path.join(Mix.Project.manifest_path, @manifest) def clean, do: Erlang.clean(manifest()) end ejabberd-16.01/README0000644000232200023220000001333412645157216014522 0ustar debalancedebalanceejabberd Community Edition [![Build Status](https://travis-ci.org/processone/ejabberd.svg?branch=master)](https://travis-ci.org/processone/ejabberd) ========================================= ejabberd is a distributed, fault-tolerant technology that allows the creation of large-scale instant messaging applications. The server can reliably support thousands of simultaneous users on a single node and has been designed to provide exceptional standards of fault tolerance. As an open source technology, based on industry-standards, ejabberd can be used to build bespoke solutions very cost effectively. Key Features ------------ - **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 XMPP 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 and Mac OS X. - 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. - Fully XMPP-compliant. - XML-based protocol. - Many protocols supported. Additional Features ------------------- Moreover, ejabberd comes with a wide range of other state-of-the-art features: - **Modularity** - 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. - **Authentication** - Internal authentication. - PAM, LDAP and ODBC. - 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. - Support for web clients: HTTP Polling and HTTP Binding (BOSH). - IRC transport. - Component support: interface with networks such as AIM, ICQ and MSN. Quickstart guide ---------------- ### 0. Requirements To compile ejabberd you need: - GNU Make. - GCC. - Libexpat 1.95 or higher. - Libyaml 0.1.4 or higher. - Erlang/OTP 17.1 or higher. - OpenSSL 1.0.0 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). - GNU Iconv 1.8 or higher, for the IRC Transport (mod_irc). Optional. Not needed on systems with GNU Libc. - ImageMagick's Convert program. Optional. For CAPTCHA challenges. ### 1. Compile and install on *nix systems To compile ejabberd, execute the following commands. The first one is only necessary if your source tree didn't come with a `configure` script. ./autogen.sh ./configure make To install ejabberd, run this command with system administrator rights (root user): sudo make install These commands will: - Install the configuration files in `/etc/ejabberd/` - Install ejabberd binary, header and runtime files in `/lib/ejabberd/` - Install the administration script: `/sbin/ejabberdctl` - Install ejabberd documentation in `/share/doc/ejabberd/` - Create a spool directory: `/var/lib/ejabberd/` - Create a directory for log files: `/var/log/ejabberd/` ### 2. Start ejabberd You can use the `ejabberdctl` command line administration script to start and stop ejabberd. For example: ejabberdctl start For detailed information please refer to the ejabberd Installation and 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. 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 ----- - Documentation: http://docs.ejabberd.im - Community site: https://www.ejabberd.im - ejabberd commercial offering and support: https://www.process-one.net/en/ejabberd ejabberd-16.01/autogen.sh0000755000232200023220000000006412645157216015637 0ustar debalancedebalance# generate a new autoconf aclocal -I m4 autoconf -f ejabberd-16.01/configure.ac0000644000232200023220000002114612645403255016125 0ustar debalancedebalance# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.53) AC_INIT(ejabberd, 16.01, ejabberd@process-one.net, ejabberd) REQUIRE_ERLANG_MIN="6.1 (Erlang/OTP 17.1)" REQUIRE_ERLANG_MAX="9.0.0 (No Max)" AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. AC_PROG_MAKE_SET AC_PROG_INSTALL AC_PROG_SED if test "x$GCC" = "xyes"; then CFLAGS="$CFLAGS -Wall" fi # Checks Erlang runtime and compiler AC_ARG_WITH(erlang, AC_HELP_STRING([--with-erlang=dir], [search for erlang in dir]), [if test "$withval" = "yes" -o "$withval" = "no" -o "X$with_erlang" = "X"; then extra_erl_path="" else extra_erl_path="$with_erlang:$with_erlang/bin:" fi ]) AC_PATH_TOOL(ERL, erl, , [${extra_erl_path}$PATH]) AC_PATH_TOOL(ERLC, erlc, , [${extra_erl_path}$PATH]) AC_ERLANG_NEED_ERL AC_ERLANG_NEED_ERLC AC_ARG_ENABLE(erlang-version-check, [AC_HELP_STRING([--enable-erlang-version-check], [Check Erlang/OTP version @<:@default=yes@:>@])]) case "$enable_erlang_version_check" in yes|'') ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX]) ;; no) ERLANG_VERSION_CHECK([$REQUIRE_ERLANG_MIN],[$REQUIRE_ERLANG_MAX],[warn]) ;; esac # Checks and sets ERLANG_ROOT_DIR and ERLANG_LIB_DIR variable AC_ERLANG_SUBST_ROOT_DIR # AC_ERLANG_SUBST_LIB_DIR #locating escript AC_PATH_PROG([ESCRIPT], [escript], [], [$ERLANG_ROOT_DIR/bin]) #locating make AC_CHECK_PROG([MAKE], [make], [make], []) if test "x$ESCRIPT" = "x"; then AC_MSG_ERROR(['escript' was not found]) fi if test "x$MAKE" = "x"; then AC_MSG_ERROR(['make' was not found]) fi # Change default prefix AC_PREFIX_DEFAULT(/) AC_ARG_ENABLE(hipe, [AC_HELP_STRING([--enable-hipe], [compile natively with HiPE, not recommended (default: no)])], [case "${enableval}" in yes) hipe=true ;; no) hipe=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-hipe) ;; esac],[hipe=false]) AC_ARG_ENABLE(roster_gateway_workaround, [AC_HELP_STRING([--enable-roster-gateway-workaround], [turn on workaround for processing gateway subscriptions (default: no)])], [case "${enableval}" in yes) roster_gateway_workaround=true ;; no) roster_gateway_workaround=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-roster-gateway-workaround) ;; esac],[roster_gateway_workaround=false]) 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 yes) full_xml=true ;; no) full_xml=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-full-xml) ;; esac],[full_xml=false]) AC_ARG_ENABLE(mssql, [AC_HELP_STRING([--enable-mssql], [use Microsoft SQL Server database (default: no, requires --enable-odbc)])], [case "${enableval}" in yes) db_type=mssql ;; no) db_type=generic ;; *) AC_MSG_ERROR(bad value ${enableval} for --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)])], [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 ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) AC_ARG_ENABLE(tools, [AC_HELP_STRING([--enable-tools], [build development tools (default: no)])], [case "${enableval}" in yes) tools=true ;; no) tools=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-tools) ;; esac],[if test "x$tools" = "x"; then tools=false; fi]) AC_ARG_ENABLE(odbc, [AC_HELP_STRING([--enable-odbc], [enable pure ODBC support (default: no)])], [case "${enableval}" in yes) odbc=true ;; no) odbc=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-odbc) ;; esac],[if test "x$odbc" = "x"; then odbc=false; fi]) AC_ARG_ENABLE(mysql, [AC_HELP_STRING([--enable-mysql], [enable MySQL support (default: no)])], [case "${enableval}" in yes) mysql=true ;; no) mysql=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-mysql) ;; esac],[if test "x$mysql" = "x"; then mysql=false; fi]) AC_ARG_ENABLE(pgsql, [AC_HELP_STRING([--enable-pgsql], [enable PostgreSQL support (default: no)])], [case "${enableval}" in yes) pgsql=true ;; no) pgsql=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-pgsql) ;; esac],[if test "x$pgsql" = "x"; then pgsql=false; fi]) AC_ARG_ENABLE(sqlite, [AC_HELP_STRING([--enable-sqlite], [enable SQLite support (default: no)])], [case "${enableval}" in yes) sqlite=true ;; no) sqlite=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-sqlite) ;; esac],[if test "x$sqlite" = "x"; then sqlite=false; fi]) AC_ARG_ENABLE(pam, [AC_HELP_STRING([--enable-pam], [enable PAM support (default: no)])], [case "${enableval}" in yes) pam=true ;; no) pam=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-pam) ;; esac],[if test "x$pam" = "x"; then pam=false; fi]) AC_ARG_ENABLE(zlib, [AC_HELP_STRING([--enable-zlib], [enable Stream Compression (XEP-0138) using zlib (default: yes)])], [case "${enableval}" in yes) zlib=true ;; no) zlib=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-zlib) ;; esac],[if test "x$zlib" = "x"; then zlib=true; fi]) AC_ARG_ENABLE(riak, [AC_HELP_STRING([--enable-riak], [enable Riak support (default: no)])], [case "${enableval}" in yes) riak=true ;; no) riak=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-riak) ;; esac],[if test "x$riak" = "x"; then riak=false; fi]) AC_ARG_ENABLE(redis, [AC_HELP_STRING([--enable-redis], [enable Redis support (default: no)])], [case "${enableval}" in yes) redis=true ;; no) redis=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-redis) ;; esac],[if test "x$redis" = "x"; then redis=false; fi]) AC_ARG_ENABLE(elixir, [AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])], [case "${enableval}" in yes) elixir=true ;; no) elixir=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-elixir) ;; esac],[if test "x$elixir" = "x"; then elixir=false; fi]) AC_ARG_ENABLE(iconv, [AC_HELP_STRING([--enable-iconv], [enable iconv support (default: yes)])], [case "${enableval}" in yes) iconv=true ;; no) iconv=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-iconv) ;; esac],[if test "x$iconv" = "x"; then iconv=true; fi]) AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])], [case "${enableval}" in yes) debug=true ;; no) debug=false ;; *) 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 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]) ENABLEUSER="" AC_ARG_ENABLE(user, [AS_HELP_STRING([--enable-user[[[[=USER]]]]], [allow this system user to start ejabberd (default: no)])], [case "${enableval}" in yes) ENABLEUSER=`whoami` ;; no) ENABLEUSER="" ;; *) ENABLEUSER=$enableval esac], []) if test "$ENABLEUSER" != ""; then echo "allow this system user to start ejabberd: $ENABLEUSER" AC_SUBST([INSTALLUSER], [$ENABLEUSER]) fi ERLANG_DEPRECATED_TYPES_CHECK if test "$sqlite" = "true"; then AX_LIB_SQLITE3([3.6.19]) if test "x$SQLITE3_VERSION" = "x"; then AC_MSG_ERROR(SQLite3 library >= 3.6.19 was not found) fi fi AC_SUBST(hipe) AC_SUBST(roster_gateway_workaround) AC_SUBST(full_xml) AC_SUBST(db_type) AC_SUBST(odbc) AC_SUBST(mysql) AC_SUBST(pgsql) AC_SUBST(sqlite) AC_SUBST(pam) AC_SUBST(zlib) AC_SUBST(riak) 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) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) AC_OUTPUT ejabberd-16.01/inetrc0000644000232200023220000000015712645157216015050 0ustar debalancedebalance{lookup,["file","native"]}. {host,{127,0,0,1}, ["localhost","hostalias"]}. {file, resolv, "/etc/resolv.conf"}. ejabberd-16.01/lib/0000755000232200023220000000000012645157216014404 5ustar debalancedebalanceejabberd-16.01/lib/ejabberd/0000755000232200023220000000000012645157216016142 5ustar debalancedebalanceejabberd-16.01/lib/ejabberd/logger.ex0000644000232200023220000000066212645157216017763 0ustar debalancedebalancedefmodule Ejabberd.Logger do def critical(message, args \\ []), do: :lager.log(:critical, [], message, args) def error(message, args \\ []), do: :lager.log(:error, [], message, args) def warning(message, args \\ []), do: :lager.log(:warning, [], message, args) def info(message, args \\ []), do: :lager.log(:info, [], message, args) def debug(message, args \\ []), do: :lager.log(:debug, [], message, args) end ejabberd-16.01/lib/ejabberd/hooks.ex0000644000232200023220000000056312645157216017627 0ustar debalancedebalancedefmodule Ejabberd.Hooks do # Generic hook setting features def add(hook_name, host, module, function, priority) do :ejabberd_hooks.add(hook_name, host, module, function, priority) end # Should be named 'removed' def delete(hook_name, host, module, function, priority) do :ejabberd_hooks.delete(hook_name, host, module, function, priority) end end ejabberd-16.01/lib/ejabberd.ex0000644000232200023220000000003212645157216016473 0ustar debalancedebalancedefmodule Ejabberd do end ejabberd-16.01/lib/mod_presence_demo.ex0000644000232200023220000000112412645157216020407 0ustar debalancedebalancedefmodule ModPresenceDemo do import Ejabberd.Logger # this allow using info, error, etc for logging @behaviour :gen_mod def start(host, _opts) do info('Starting ejabberd module Presence Demo') Ejabberd.Hooks.add(:set_presence_hook, host, __ENV__.module, :on_presence, 50) :ok end def stop(host) do info('Stopping ejabberd module Presence Demo') Ejabberd.Hooks.delete(:set_presence_hook, host, __ENV__.module, :on_presence, 50) :ok end def on_presence(user, _server, _resource, _packet) do info('Receive presence for #{user}') :none end end ejabberd-16.01/aclocal.m40000644000232200023220000000125612645403255015477 0ustar debalancedebalance# generated automatically by aclocal 1.11.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, # Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_include([m4/ax_lib_sqlite3.m4]) m4_include([m4/erlang-extra.m4]) ejabberd-16.01/install-sh0000644000232200023220000003253712645157216015651 0ustar debalancedebalance#!/bin/sh # install - install a program, script, or datafile scriptversion=2009-04-28.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ejabberd-16.01/contrib/0000755000232200023220000000000012645157216015276 5ustar debalancedebalanceejabberd-16.01/contrib/extract_translations/0000755000232200023220000000000012645157216021551 5ustar debalancedebalanceejabberd-16.01/contrib/extract_translations/prepare-translation.sh0000755000232200023220000002174712645157216026115 0ustar debalancedebalance#!/bin/bash # Frontend for ejabberd's extract_translations.erl # by Badlop # How to create template files for a new language: # NEWLANG=zh # cp msgs/ejabberd.pot msgs/$NEWLANG.po # echo \{\"\",\"\"\}. > msgs/$NEWLANG.msg # ../../extract_translations/prepare-translation.sh -updateall prepare_dirs () { # Where is Erlang binary ERL=`which erl` EJA_SRC_DIR=$EJA_DIR/src/ EJA_MSGS_DIR=$EJA_DIR/priv/msgs/ EXTRACT_DIR=$EJA_DIR/contrib/extract_translations/ EXTRACT_ERL=$EXTRACT_DIR/extract_translations.erl EXTRACT_BEAM=$EXTRACT_DIR/extract_translations.beam SRC_DIR=$RUN_DIR/src EBIN_DIR=$RUN_DIR/ebin MSGS_DIR=$EJA_DIR/priv/msgs if !([[ -n $EJA_DIR ]]) then echo "ejabberd dir does not exist: $EJA_DIR" fi if !([[ -x $EXTRACT_BEAM ]]) then sh -c "cd $EXTRACT_DIR; $ERL -compile $EXTRACT_ERL" fi } extract_lang () { MSGS_FILE=$1 MSGS_FILE2=$MSGS_FILE.translate MSGS_PATH=$MSGS_DIR/$MSGS_FILE MSGS_PATH2=$MSGS_DIR/$MSGS_FILE2 echo -n "Extracting language strings for '$MSGS_FILE':" echo -n " new..." cd $SRC_DIR $ERL -pa $EXTRACT_DIR -noinput -noshell -s extract_translations -s init stop -extra . $MSGS_PATH >$MSGS_PATH.new sed -e 's/^% \.\//% /g;' $MSGS_PATH.new > $MSGS_PATH.new2 mv $MSGS_PATH.new2 $MSGS_PATH.new echo -n " old..." $ERL -pa $EXTRACT_DIR -noinput -noshell -s extract_translations -s init stop -extra -unused . $MSGS_PATH >$MSGS_PATH.unused find_unused_full $MSGS_FILE $MSGS_FILE.unused echo "" >$MSGS_PATH2 echo " ***** Translation file for ejabberd ***** " >>$MSGS_PATH2 echo "" >>$MSGS_PATH2 echo "" >>$MSGS_PATH2 echo " *** New strings: Can you please translate them? *** " >>$MSGS_PATH2 cat $MSGS_PATH.new >>$MSGS_PATH2 echo "" >>$MSGS_PATH2 echo "" >>$MSGS_PATH2 echo " *** Unused strings: They will be removed automatically *** " >>$MSGS_PATH2 cat $MSGS_PATH.unused.full >>$MSGS_PATH2 echo "" >>$MSGS_PATH2 echo "" >>$MSGS_PATH2 echo " *** Already translated strings: you can also modify any of them if you want *** " >>$MSGS_PATH2 echo "" >>$MSGS_PATH2 cat $MSGS_PATH.old_cleaned >>$MSGS_PATH2 echo " ok" rm $MSGS_PATH.new rm $MSGS_PATH.old_cleaned rm $MSGS_PATH.unused.full } extract_lang_all () { cd $MSGS_DIR for i in $( ls *.msg ) ; do extract_lang $i; done echo -e "File\tMissing\tLanguage\t\tLast translator" echo -e "----\t-------\t--------\t\t---------------" cd $MSGS_DIR for i in $( ls *.msg ) ; do MISSING=`cat $i.translate | grep "\", \"\"}." | wc -l` LANGUAGE=`grep "X-Language:" $i.translate | sed 's/% Language: //g'` LASTAUTH=`grep "Author:" $i.translate | head -n 1 | sed 's/% Author: //g'` echo -e "$i\t$MISSING\t$LANGUAGE\t$LASTAUTH" done cd $MSGS_DIR REVISION=`git describe --always` zip $HOME/ejabberd-langs-$REVISION.zip *.translate; rm *.translate } find_unused_full () { DATFILE=$1 DATFILEI=$1.old_cleaned DELFILE=$2 cd msgs DATFILE1=$DATFILE.t1 DATFILE2=$DATFILE.t2 DELFILE1=$DELFILE.t1 DELFILE2=$DELFILE.t2 DELFILEF=$DATFILE.unused.full echo "" >$DELFILEF grep -v "\\\\" $DELFILE >$DELFILE2 echo ENDFILEMARK >>$DELFILE2 cp $DATFILE $DATFILEI cp $DATFILE $DATFILE2 cp $DELFILE2 $DELFILE1 STRING=`head -1 $DELFILE1` until [[ $STRING == ENDFILEMARK ]]; do cp $DELFILE2 $DELFILE1 cp $DATFILE2 $DATFILE1 STRING=`head -1 $DELFILE1` cat $DATFILE1 | grep "$STRING" >>$DELFILEF cat $DATFILE1 | grep -v "$STRING" >$DATFILE2 cat $DELFILE1 | grep -v "$STRING" >$DELFILE2 done mv $DATFILE2 $DATFILEI rm -f $MSGS_PATH.t1 rm $MSGS_PATH.unused rm -f $MSGS_PATH.unused.t1 rm $MSGS_PATH.unused.t2 cd .. } extract_lang_srcmsg2po () { LANG=$1 LANG_CODE=$LANG.$PROJECT MSGS_PATH=$MSGS_DIR/$LANG_CODE.msg PO_PATH=$MSGS_DIR/$LANG_CODE.po echo $MSGS_PATH cd $SRC_DIR $ERL -pa $EXTRACT_DIR -pa $EBIN_DIR -pa $EJA_SRC_DIR -pa /lib/ejabberd/include -noinput -noshell -s extract_translations -s init stop -extra -srcmsg2po . $MSGS_PATH >$PO_PATH.1 sed -e 's/ \[\]$/ \"\"/g;' $PO_PATH.1 > $PO_PATH.2 msguniq --sort-by-file $PO_PATH.2 --output-file=$PO_PATH rm $PO_PATH.* } extract_lang_src2pot () { LANG_CODE=$PROJECT MSGS_PATH=$MSGS_DIR/$LANG_CODE.msg POT_PATH=$MSGS_DIR/$LANG_CODE.pot echo -n "" >$MSGS_PATH echo "% Language: Language Name" >>$MSGS_PATH echo "% Author: Translator name and contact method" >>$MSGS_PATH echo "" >>$MSGS_PATH cd $SRC_DIR $ERL -pa $EXTRACT_DIR -pa $EBIN_DIR -pa $EJA_SRC_DIR -pa /lib/ejabberd/include -noinput -noshell -s extract_translations -s init stop -extra -srcmsg2po . $MSGS_PATH >$POT_PATH.1 sed -e 's/ \[\]$/ \"\"/g;' $POT_PATH.1 > $POT_PATH.2 #msguniq --sort-by-file $POT_PATH.2 $EJA_MSGS_DIR --output-file=$POT_PATH msguniq --sort-by-file $POT_PATH.2 --output-file=$POT_PATH rm $POT_PATH.* rm $MSGS_PATH # If the project is a specific module, not the main ejabberd if [[ $PROJECT != ejabberd ]] ; then # Remove from project.pot the strings that are already present in the general ejabberd EJABBERD_MSG_FILE=$EJA_MSGS_DIR/es.po # This is just some file with translated strings POT_PATH_TEMP=$POT_PATH.temp msgattrib --set-obsolete --only-file=$EJABBERD_MSG_FILE -o $POT_PATH_TEMP $POT_PATH mv $POT_PATH_TEMP $POT_PATH fi } extract_lang_popot2po () { LANG_CODE=$1 PO_PATH=$MSGS_DIR/$LANG_CODE.po POT_PATH=$MSGS_DIR/$PROJECT.pot msgmerge $PO_PATH $POT_PATH >$PO_PATH.translate 2>/dev/null mv $PO_PATH.translate $PO_PATH } extract_lang_po2msg () { LANG_CODE=$1 PO_PATH=$LANG_CODE.po MS_PATH=$PO_PATH.ms MSGID_PATH=$PO_PATH.msgid MSGSTR_PATH=$PO_PATH.msgstr MSGS_PATH=$LANG_CODE.msg cd $MSGS_DIR # Check PO has correct ~ # Let's convert to C format so we can use msgfmt PO_TEMP=$LANG_CODE.po.temp cat $PO_PATH | sed 's/%/perc/g' | sed 's/~/%/g' | sed 's/#:.*/#, c-format/g' >$PO_TEMP msgfmt $PO_TEMP --check-format result=$? rm $PO_TEMP if [ $result -ne 0 ] ; then exit 1 fi msgattrib $PO_PATH --translated --no-fuzzy --no-obsolete --no-location --no-wrap | grep "^msg" | tail --lines=+3 >$MS_PATH grep "^msgid" $PO_PATH.ms | sed 's/^msgid //g' >$MSGID_PATH grep "^msgstr" $PO_PATH.ms | sed 's/^msgstr //g' >$MSGSTR_PATH echo "%% -*- coding: latin-1 -*-" >$MSGS_PATH paste $MSGID_PATH $MSGSTR_PATH --delimiter=, | awk '{print "{" $0 "}."}' | sort -g >>$MSGS_PATH rm $MS_PATH rm $MSGID_PATH rm $MSGSTR_PATH } extract_lang_updateall () { echo "Generating POT" extract_lang_src2pot cd $MSGS_DIR echo "" echo -e "File Missing Language Last translator" echo -e "---- ------- -------- ---------------" for i in $( ls *.msg ) ; do LANG_CODE=${i%.msg} echo -n $LANG_CODE | awk '{printf "%-6s", $1 }' # Convert old MSG file to PO PO=$LANG_CODE.po [ -f $PO ] || extract_lang_srcmsg2po $LANG_CODE extract_lang_popot2po $LANG_CODE extract_lang_po2msg $LANG_CODE MISSING=`msgfmt --statistics $PO 2>&1 | awk '{printf "%5s", $4 }'` echo -n " $MISSING" LANGUAGE=`grep "X-Language:" $PO | sed 's/\"X-Language: //g' | sed 's/\\\\n\"//g' | awk '{printf "%-12s", $1}'` echo -n " $LANGUAGE" LASTAUTH=`grep "Last-Translator" $PO | sed 's/\"Last-Translator: //g' | sed 's/\\\\n\"//g'` echo " $LASTAUTH" done echo "" rm messages.mo cd .. } translation_instructions () { echo "" echo " A new file has been created for you, with the current, the new and the deprecated strings:" echo " $MSGS_PATH2" echo "" echo " At the end of that file you will find the strings you must update:" echo " - Untranslated strings are like this: {"March", ""}." echo " To translate the string, add the text inside the commas. Example:" echo " {"March", "Marzo"}." echo " - Old strings that are not used: "Woowoa"" echo " Search the entire file for those strings and remove them" echo "" echo " Once you have translated all the strings and removed all the old ones," echo " rename the file to overwrite the previous one:" echo " $MSGS_PATH" } EJA_DIR=`pwd` RUN_DIR=`pwd` PROJECT=ejabberd while [ $# -ne 0 ] ; do PARAM=$1 shift case $PARAM in --) break ;; -project) PROJECT=$1 shift ;; -ejadir) EJA_DIR=$1 shift ;; -rundir) RUN_DIR=$1 shift ;; -lang) LANGU=$1 prepare_dirs extract_lang $LANGU shift ;; -langall) prepare_dirs extract_lang_all ;; -srcmsg2po) LANG_CODE=$1 prepare_dirs extract_lang_srcmsg2po $LANG_CODE shift ;; -popot2po) LANG_CODE=$1 prepare_dirs extract_lang_popot2po $LANG_CODE shift ;; -src2pot) prepare_dirs extract_lang_src2pot ;; -po2msg) LANG_CODE=$1 prepare_dirs extract_lang_po2msg $LANG_CODE shift ;; -updateall) prepare_dirs extract_lang_updateall ;; *) echo "Options:" echo " -langall" echo " -lang LANGUAGE_FILE" echo " -srcmsg2po LANGUAGE Construct .msg file using source code to PO file" echo " -src2pot Generate template POT file from source code" echo " -popot2po LANGUAGE Update PO file with template POT file" echo " -po2msg LANGUAGE Export PO file to MSG file" echo " -updateall Generate POT and update all PO" echo "" echo "Example:" echo " ./prepare-translation.sh -lang es.msg" exit 0 ;; esac done ejabberd-16.01/contrib/extract_translations/extract_translations.erl0000644000232200023220000001757412645157216026546 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : extract_translations.erl %%% Author : Sergei Golovan %%% Purpose : Auxiliary tool for interface/messages translators %%% Created : 23 Apr 2005 by Sergei Golovan %%% Id : $Id$ %%%---------------------------------------------------------------------- -module(extract_translations). -author('sgolovan@nes.ru'). -export([start/0]). -define(STATUS_SUCCESS, 0). -define(STATUS_ERROR, 1). -define(STATUS_USAGE, 2). -include_lib("kernel/include/file.hrl"). start() -> ets:new(translations, [named_table, public]), ets:new(translations_obsolete, [named_table, public]), ets:new(files, [named_table, public]), ets:new(vars, [named_table, public]), case init:get_plain_arguments() of ["-srcmsg2po", Dir, File] -> print_po_header(File), Status = process(Dir, File, srcmsg2po), halt(Status); ["-unused", Dir, File] -> Status = process(Dir, File, unused), halt(Status); [Dir, File] -> Status = process(Dir, File, used), halt(Status); _ -> print_usage(), halt(?STATUS_USAGE) end. process(Dir, File, Used) -> case load_file(File) of {error, Reason} -> io:format("~s: ~s~n", [File, file:format_error(Reason)]), ?STATUS_ERROR; _ -> FileList = find_src_files(Dir), lists:foreach( fun(F) -> parse_file(Dir, F, Used) end, FileList), case Used of unused -> ets:foldl(fun({Key, _}, _) -> io:format("~p~n", [Key]) end, ok, translations); srcmsg2po -> ets:foldl(fun({Key, Trans}, _) -> print_translation_obsolete(Key, Trans) end, ok, translations_obsolete); _ -> ok end, ?STATUS_SUCCESS end. parse_file(Dir, File, Used) -> ets:delete_all_objects(vars), case epp:parse_file(File, [Dir, filename:dirname(File) | code:get_path()], []) of {ok, Forms} -> lists:foreach( fun(F) -> parse_form(Dir, File, F, Used) end, Forms); _ -> ok end. parse_form(Dir, File, Form, Used) -> case Form of %%{undefined, Something} -> %% io:format("Undefined: ~p~n", [Something]); {call, _, {remote, _, {atom, _, translate}, {atom, _, translate}}, [_, {string, Line, Str}] } -> process_string(Dir, File, Line, Str, Used); {call, _, {remote, _, {atom, _, translate}, {atom, _, translate}}, [_, {bin,_, [{bin_element,_, {string,Line,Str}, default,default}]}] } -> process_string(Dir, File, Line, Str, Used); {call, _, {remote, _, {atom, _, translate}, {atom, _, translate}}, [_, {var, _, Name}] } -> case ets:lookup(vars, Name) of [{_Name, Value, Line}] -> process_string(Dir, File, Line, Value, Used); _ -> ok end; {match, _, {var, _, Name}, {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) -> parse_form(Dir, File, F, Used) end, L); T when is_tuple(T) -> lists:foreach( fun(F) -> parse_form(Dir, File, F, Used) end, tuple_to_list(T)); _ -> ok end. process_string(_Dir, _File, _Line, "", _Used) -> ok; process_string(_Dir, File, Line, Str, Used) -> case {ets:lookup(translations, Str), Used} of {[{_Key, _Trans}], unused} -> ets:delete(translations, Str); {[{_Key, _Trans}], used} -> ok; {[{_Key, Trans}], srcmsg2po} -> ets:delete(translations_obsolete, Str), print_translation(File, Line, Str, Trans); {_, used} -> case ets:lookup(files, File) of [{_}] -> ok; _ -> io:format("~n% ~s~n", [File]), ets:insert(files, {File}) end, case Str of [] -> ok; _ -> io:format("{~p, \"\"}.~n", [Str]) end, ets:insert(translations, {Str, ""}); {_, srcmsg2po} -> case ets:lookup(files, File) of [{_}] -> ok; _ -> ets:insert(files, {File}) end, ets:insert(translations, {Str, ""}), print_translation(File, Line, Str, ""); _ -> ok end. load_file(File) -> case file:consult(File) of {ok, Terms} -> lists:foreach( fun({Orig, Trans}) -> case Trans of "" -> ok; _ -> ets:insert(translations, {Orig, Trans}), ets:insert(translations_obsolete, {Orig, Trans}) end end, Terms); Err -> Err end. find_src_files(Dir) -> case file:list_dir(Dir) of {ok, FileList} -> recurse_filelist( lists:map( fun(F) -> filename:join(Dir, F) end, FileList)); _ -> [] end. recurse_filelist(FileList) -> recurse_filelist(FileList, []). recurse_filelist([], Acc) -> lists:reverse(Acc); recurse_filelist([H | T], Acc) -> case file:read_file_info(H) of {ok, #file_info{type = directory}} -> recurse_filelist(T, lists:reverse(find_src_files(H)) ++ Acc); {ok, #file_info{type = regular}} -> case string:substr(H, string:len(H) - 3) of ".erl" -> recurse_filelist(T, [H | Acc]); ".hrl" -> recurse_filelist(T, [H | Acc]); _ -> recurse_filelist(T, Acc) end; _ -> recurse_filelist(T, Acc) end. print_usage() -> io:format( "Usage: extract_translations [-unused] dir file~n" "~n" "Example:~n" " extract_translations . ./msgs/ru.msg~n" ). %%% %%% Gettext %%% print_po_header(File) -> MsgProps = get_msg_header_props(File), {Language, [LastT | AddT]} = prepare_props(MsgProps), application:load(ejabberd), {ok, Version} = application:get_key(ejabberd, vsn), print_po_header(Version, Language, LastT, AddT). get_msg_header_props(File) -> {ok, F} = file:open(File, [read]), Lines = get_msg_header_props(F, []), file:close(F), Lines. get_msg_header_props(F, Lines) -> String = io:get_line(F, ""), case io_lib:fread("% ", String) of {ok, [], RemString} -> case io_lib:fread("~s", RemString) of {ok, [Key], Value} when Value /= "\n" -> %% The first character in Value is a blankspace: %% And the last characters are 'slash n' ValueClean = string:substr(Value, 2, string:len(Value)-2), get_msg_header_props(F, Lines ++ [{Key, ValueClean}]); _ -> get_msg_header_props(F, Lines) end; _ -> Lines end. prepare_props(MsgProps) -> Language = proplists:get_value("Language:", MsgProps), Authors = proplists:get_all_values("Author:", MsgProps), {Language, Authors}. print_po_header(Version, Language, LastTranslator, AdditionalTranslatorsList) -> AdditionalTranslatorsString = build_additional_translators(AdditionalTranslatorsList), HeaderString = "msgid \"\"\n" "msgstr \"\"\n" "\"Project-Id-Version: " ++ Version ++ "\\n\"\n" ++ "\"X-Language: " ++ Language ++ "\\n\"\n" "\"Last-Translator: " ++ LastTranslator ++ "\\n\"\n" ++ AdditionalTranslatorsString ++ "\"MIME-Version: 1.0\\n\"\n" "\"Content-Type: text/plain; charset=UTF-8\\n\"\n" "\"Content-Transfer-Encoding: 8bit\\n\"\n", io:format("~s~n", [HeaderString]). build_additional_translators(List) -> lists:foldl( fun(T, Str) -> Str ++ "\"X-Additional-Translator: " ++ T ++ "\\n\"\n" end, "", List). print_translation(File, Line, Str, StrT) -> StrQ = ejabberd_regexp:greplace(list_to_binary(Str), <<"\\\"">>, <<"\\\\\"">>), StrTQ = ejabberd_regexp:greplace(list_to_binary(StrT), <<"\\\"">>, <<"\\\\\"">>), io:format("#: ~s:~p~nmsgid \"~s\"~nmsgstr \"~s\"~n~n", [File, Line, StrQ, StrTQ]). print_translation_obsolete(Str, StrT) -> File = "unknown.erl", Line = 1, StrQ = ejabberd_regexp:greplace(Str, "\\\"", "\\\\\""), StrTQ = ejabberd_regexp:greplace(StrT, "\\\"", "\\\\\""), io:format("#: ~s:~p~n#~~ msgid \"~s\"~n#~~ msgstr \"~s\"~n~n", [File, Line, StrQ, StrTQ]). ejabberd-16.01/contrib/extract_translations/README0000644000232200023220000000121612645157216022431 0ustar debalancedebalanceextract_translations - auxiliary tool that extracts lines to be translated from ejabberd source tree. Building: erlc extract_translations.erl Invoking 1: erl -noinput -s extract_translations -extra dirname message_file where dirname is the directory "src" in ejabberd's source tree root, message_file is a file with translated messages (src/msgs/*.msg). Result is a list of messages from source files which aren't contained in message file. Invoking 2: erl -noinput -s extract_translations -extra -unused dirname message_file Result is a list of messages from message file which aren't in source files anymore. ejabberd-16.01/config/0000755000232200023220000000000012645157216015103 5ustar debalancedebalanceejabberd-16.01/config/config.exs0000644000232200023220000000033612645157216017073 0ustar debalancedebalanceuse Mix.Config # This is standard path in the context of ejabberd release config :ejabberd, file: "config/ejabberd.yml", log_path: 'log/ejabberd.log' # Customize Mnesia directory: config :mnesia, dir: 'mnesiadb/' ejabberd-16.01/configure0000755000232200023220000045525712645403255015564 0ustar debalancedebalance#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for ejabberd 16.01. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: ejabberd@process-one.net about your system, including $0: any error possibly output before this message. Then $0: install a modern shell, or manually run the script $0: under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ejabberd' PACKAGE_TARNAME='ejabberd' PACKAGE_VERSION='16.01' PACKAGE_STRING='ejabberd 16.01' PACKAGE_BUGREPORT='ejabberd@process-one.net' PACKAGE_URL='' ac_default_prefix=/ ac_subst_vars='LTLIBOBJS LIBOBJS latest_deps tools lager debug iconv elixir redis riak zlib pam sqlite pgsql mysql odbc db_type full_xml roster_gateway_workaround hipe SQLITE3_VERSION SQLITE3_LDFLAGS SQLITE3_CFLAGS OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC erlang_deprecated_types INSTALLUSER MAKE ESCRIPT ERLANG_ROOT_DIR ERLCFLAGS ERLC ERL SED INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM SET_MAKE target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_erlang enable_erlang_version_check enable_hipe enable_roster_gateway_workaround enable_full_xml enable_mssql enable_all enable_tools 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_latest_deps enable_user with_sqlite3 ' ac_precious_vars='build_alias host_alias target_alias ERL ERLC ERLCFLAGS CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures ejabberd 16.01 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/ejabberd] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of ejabberd 16.01:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-erlang-version-check Check Erlang/OTP version [default=yes] --enable-hipe compile natively with HiPE, not recommended (default: no) --enable-roster-gateway-workaround turn on workaround for processing gateway subscriptions (default: no) --enable-full-xml use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients) --enable-mssql use Microsoft SQL Server database (default: no, requires --enable-odbc) --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) --enable-tools build development tools (default: no) --enable-odbc enable pure ODBC support (default: no) --enable-mysql enable MySQL support (default: no) --enable-pgsql enable PostgreSQL support (default: no) --enable-sqlite enable SQLite support (default: no) --enable-pam enable PAM support (default: no) --enable-zlib enable Stream Compression (XEP-0138) using zlib (default: yes) --enable-riak enable Riak support (default: no) --enable-redis enable Redis support (default: no) --enable-elixir enable Elixir support (default: no) --enable-iconv enable iconv support (default: yes) --enable-debug enable debug information (default: yes) --enable-lager enable lager support (default: yes) --enable-latest-deps makes rebar use latest commits for dependences instead of tagged versions (default: no) --enable-user[[[=USER]]] allow this system user to start ejabberd (default: no) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-erlang=dir search for erlang in dir --with-sqlite3=[ARG] use SQLite 3 library [default=yes], optionally specify the prefix for sqlite3 library Some influential environment variables: ERL Erlang/OTP interpreter command [autodetected] ERLC Erlang/OTP compiler command [autodetected] ERLCFLAGS Erlang/OTP compiler flags [none] CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF ejabberd configure 16.01 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_erl_try_run LINENO # ------------------------ # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_erl_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_erl_try_run # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by ejabberd $as_me 16.01, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu REQUIRE_ERLANG_MIN="6.1 (Erlang/OTP 17.1)" REQUIRE_ERLANG_MAX="9.0.0 (No Max)" # Checks for programs. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed if test "x$GCC" = "xyes"; then CFLAGS="$CFLAGS -Wall" fi # Checks Erlang runtime and compiler # Check whether --with-erlang was given. if test "${with_erlang+set}" = set; then : withval=$with_erlang; if test "$withval" = "yes" -o "$withval" = "no" -o "X$with_erlang" = "X"; then extra_erl_path="" else extra_erl_path="$with_erlang:$with_erlang/bin:" fi fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}erl", so it can be a program name with args. set dummy ${ac_tool_prefix}erl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ERL+:} false; then : $as_echo_n "(cached) " >&6 else case $ERL in [\\/]* | ?:[\\/]*) ac_cv_path_ERL="$ERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in ${extra_erl_path}$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ERL="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ERL=$ac_cv_path_ERL if test -n "$ERL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERL" >&5 $as_echo "$ERL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_ERL"; then ac_pt_ERL=$ERL # Extract the first word of "erl", so it can be a program name with args. set dummy erl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_ERL+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_ERL in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_ERL="$ac_pt_ERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in ${extra_erl_path}$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_ERL="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_ERL=$ac_cv_path_ac_pt_ERL if test -n "$ac_pt_ERL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_ERL" >&5 $as_echo "$ac_pt_ERL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_ERL" = x; then ERL="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac ERL=$ac_pt_ERL fi else ERL="$ac_cv_path_ERL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}erlc", so it can be a program name with args. set dummy ${ac_tool_prefix}erlc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ERLC+:} false; then : $as_echo_n "(cached) " >&6 else case $ERLC in [\\/]* | ?:[\\/]*) ac_cv_path_ERLC="$ERLC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in ${extra_erl_path}$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ERLC="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ERLC=$ac_cv_path_ERLC if test -n "$ERLC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERLC" >&5 $as_echo "$ERLC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_ERLC"; then ac_pt_ERLC=$ERLC # Extract the first word of "erlc", so it can be a program name with args. set dummy erlc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_ERLC+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_ERLC in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_ERLC="$ac_pt_ERLC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in ${extra_erl_path}$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_ERLC="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_ERLC=$ac_cv_path_ac_pt_ERLC if test -n "$ac_pt_ERLC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_ERLC" >&5 $as_echo "$ac_pt_ERLC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_ERLC" = x; then ERLC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac ERLC=$ac_pt_ERLC fi else ERLC="$ac_cv_path_ERLC" fi if test -n "$ERL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for erl" >&5 $as_echo_n "checking for erl... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERL" >&5 $as_echo "$ERL" >&6; } else if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}erl", so it can be a program name with args. set dummy ${ac_tool_prefix}erl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ERL+:} false; then : $as_echo_n "(cached) " >&6 else case $ERL in [\\/]* | ?:[\\/]*) ac_cv_path_ERL="$ERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ERL="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ERL=$ac_cv_path_ERL if test -n "$ERL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERL" >&5 $as_echo "$ERL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_ERL"; then ac_pt_ERL=$ERL # Extract the first word of "erl", so it can be a program name with args. set dummy erl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_ERL+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_ERL in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_ERL="$ac_pt_ERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_ERL="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_ERL=$ac_cv_path_ac_pt_ERL if test -n "$ac_pt_ERL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_ERL" >&5 $as_echo "$ac_pt_ERL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_ERL" = x; then ERL="not found" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac ERL=$ac_pt_ERL fi else ERL="$ac_cv_path_ERL" fi fi if test "$ERL" = "not found"; then as_fn_error $? "Erlang/OTP interpreter (erl) not found but required" "$LINENO" 5 fi if test -n "$ERLC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for erlc" >&5 $as_echo_n "checking for erlc... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERLC" >&5 $as_echo "$ERLC" >&6; } else if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}erlc", so it can be a program name with args. set dummy ${ac_tool_prefix}erlc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ERLC+:} false; then : $as_echo_n "(cached) " >&6 else case $ERLC in [\\/]* | ?:[\\/]*) ac_cv_path_ERLC="$ERLC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ERLC="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ERLC=$ac_cv_path_ERLC if test -n "$ERLC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERLC" >&5 $as_echo "$ERLC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_ERLC"; then ac_pt_ERLC=$ERLC # Extract the first word of "erlc", so it can be a program name with args. set dummy erlc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_ERLC+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_ERLC in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_ERLC="$ac_pt_ERLC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_ERLC="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_ERLC=$ac_cv_path_ac_pt_ERLC if test -n "$ac_pt_ERLC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_ERLC" >&5 $as_echo "$ac_pt_ERLC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_ERLC" = x; then ERLC="not found" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac ERLC=$ac_pt_ERLC fi else ERLC="$ac_cv_path_ERLC" fi fi if test "$ERLC" = "not found"; then as_fn_error $? "Erlang/OTP compiler (erlc) not found but required" "$LINENO" 5 fi # Check whether --enable-erlang-version-check was given. if test "${enable_erlang_version_check+set}" = set; then : enableval=$enable_erlang_version_check; fi case "$enable_erlang_version_check" in yes|'') { $as_echo "$as_me:${as_lineno-$LINENO}: checking Erlang/OTP version" >&5 $as_echo_n "checking Erlang/OTP version... " >&6; } cat > conftest.erl < ERTS = erlang:system_info(version), RequiredMin = "$REQUIRE_ERLANG_MIN", RequiredMax = "$REQUIRE_ERLANG_MAX", Status = case {string:tokens(RequiredMin, " "), string:tokens(RequiredMax, " ")} of {[MinStr | _], [MaxStr | _]} -> case check(ERTS, {MinStr, MaxStr}) of less -> list_to_binary([ERTS, " found, ", RequiredMin, " required"]); greater -> list_to_binary([ERTS, " found, ", RequiredMax, " or earlier required"]); ok -> <<"ok">> end; _ -> list_to_binary([ERTS, " found, ", RequiredMin, " required"]) end, file:write_file("conftest.out", Status), halt(). check(CurStr, {MinStr, MaxStr}) -> Cur = parse(CurStr), Min = parse(MinStr), Max = parse(MaxStr), case {less_or_equal(Min, Cur), less_or_equal(Cur, Max)} of {false, true} -> less; {true, true} -> ok; {true, false} -> greater end. parse(Version) -> lists:map(fun(A) -> {Int,[]} = string:to_integer(A), Int end, string:tokens(Version, ".")). less_or_equal([], []) -> true; less_or_equal([], _Any) -> true; less_or_equal(_Any, []) -> false; less_or_equal([Left| Rl], [Right| Rr]) -> case {Left < Right, Left == Right} of {true, _} -> true; {false, false} -> false; {false, true} -> less_or_equal(Rl, Rr) end. EOF $ERLC conftest.erl || as_fn_error $? "\"Could not compile Erlang/OTP version check program using '$ERLC'\"" "$LINENO" 5 if ! $ERL -s conftest -noshell -o ! -f conftest.out ; then as_fn_error $? "\"Could not run Erlang/OTP version check program using '$ERL'\"" "$LINENO" 5 fi if test "x`cat conftest.out`" != "xok"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } X="`cat conftest.out`" if test "" == "warn"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $X" >&5 $as_echo "$as_me: WARNING: $X" >&2;} else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "$X See \`config.log' for more details" "$LINENO" 5; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: checking Erlang/OTP version" >&5 $as_echo_n "checking Erlang/OTP version... " >&6; } cat > conftest.erl < ERTS = erlang:system_info(version), RequiredMin = "$REQUIRE_ERLANG_MIN", RequiredMax = "$REQUIRE_ERLANG_MAX", Status = case {string:tokens(RequiredMin, " "), string:tokens(RequiredMax, " ")} of {[MinStr | _], [MaxStr | _]} -> case check(ERTS, {MinStr, MaxStr}) of less -> list_to_binary([ERTS, " found, ", RequiredMin, " required"]); greater -> list_to_binary([ERTS, " found, ", RequiredMax, " or earlier required"]); ok -> <<"ok">> end; _ -> list_to_binary([ERTS, " found, ", RequiredMin, " required"]) end, file:write_file("conftest.out", Status), halt(). check(CurStr, {MinStr, MaxStr}) -> Cur = parse(CurStr), Min = parse(MinStr), Max = parse(MaxStr), case {less_or_equal(Min, Cur), less_or_equal(Cur, Max)} of {false, true} -> less; {true, true} -> ok; {true, false} -> greater end. parse(Version) -> lists:map(fun(A) -> {Int,[]} = string:to_integer(A), Int end, string:tokens(Version, ".")). less_or_equal([], []) -> true; less_or_equal([], _Any) -> true; less_or_equal(_Any, []) -> false; less_or_equal([Left| Rl], [Right| Rr]) -> case {Left < Right, Left == Right} of {true, _} -> true; {false, false} -> false; {false, true} -> less_or_equal(Rl, Rr) end. EOF $ERLC conftest.erl || as_fn_error $? "\"Could not compile Erlang/OTP version check program using '$ERLC'\"" "$LINENO" 5 if ! $ERL -s conftest -noshell -o ! -f conftest.out ; then as_fn_error $? "\"Could not run Erlang/OTP version check program using '$ERL'\"" "$LINENO" 5 fi if test "x`cat conftest.out`" != "xok"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } X="`cat conftest.out`" if test "warn" == "warn"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $X" >&5 $as_echo "$as_me: WARNING: $X" >&2;} else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "$X See \`config.log' for more details" "$LINENO" 5; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi ;; esac # Checks and sets ERLANG_ROOT_DIR and ERLANG_LIB_DIR variable { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Erlang/OTP root directory" >&5 $as_echo_n "checking for Erlang/OTP root directory... " >&6; } if ${ac_cv_erlang_root_dir+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=erl ac_compile='$ERLC $ERLCFLAGS -b beam conftest.$ac_ext >&5' ac_link='$ERLC $ERLCFLAGS -b beam conftest.$ac_ext >&5 && echo "#!/bin/sh" > conftest$ac_exeext && $as_echo "\"$ERL\" -run conftest start -run init stop -noshell" >> conftest$ac_exeext && chmod +x conftest$ac_exeext' if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat > conftest.$ac_ext <<_ACEOF -module(conftest). -export([start/0]). start() -> RootDir = code:root_dir(), file:write_file("conftest.out", RootDir), ReturnValue = 0, halt(ReturnValue) . _ACEOF if ac_fn_erl_try_run "$LINENO"; then : ac_cv_erlang_root_dir=`cat conftest.out` rm -f conftest.out else rm -f conftest.out { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "test Erlang program execution failed See \`config.log' for more details" "$LINENO" 5; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_erlang_root_dir" >&5 $as_echo "$ac_cv_erlang_root_dir" >&6; } ERLANG_ROOT_DIR=$ac_cv_erlang_root_dir # AC_ERLANG_SUBST_LIB_DIR #locating escript # Extract the first word of "escript", so it can be a program name with args. set dummy escript; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ESCRIPT+:} false; then : $as_echo_n "(cached) " >&6 else case $ESCRIPT in [\\/]* | ?:[\\/]*) ac_cv_path_ESCRIPT="$ESCRIPT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $ERLANG_ROOT_DIR/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ESCRIPT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ESCRIPT=$ac_cv_path_ESCRIPT if test -n "$ESCRIPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ESCRIPT" >&5 $as_echo "$ESCRIPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi #locating make # Extract the first word of "make", so it can be a program name with args. set dummy make; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MAKE"; then ac_cv_prog_MAKE="$MAKE" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MAKE="make" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MAKE=$ac_cv_prog_MAKE if test -n "$MAKE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 $as_echo "$MAKE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ESCRIPT" = "x"; then as_fn_error $? "'escript' was not found" "$LINENO" 5 fi if test "x$MAKE" = "x"; then as_fn_error $? "'make' was not found" "$LINENO" 5 fi # Change default prefix # Check whether --enable-hipe was given. if test "${enable_hipe+set}" = set; then : enableval=$enable_hipe; case "${enableval}" in yes) hipe=true ;; no) hipe=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-hipe" "$LINENO" 5 ;; esac else hipe=false fi # Check whether --enable-roster_gateway_workaround was given. if test "${enable_roster_gateway_workaround+set}" = set; then : enableval=$enable_roster_gateway_workaround; case "${enableval}" in yes) roster_gateway_workaround=true ;; no) roster_gateway_workaround=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-roster-gateway-workaround" "$LINENO" 5 ;; esac else roster_gateway_workaround=false fi # Check whether --enable-full_xml was given. if test "${enable_full_xml+set}" = set; then : enableval=$enable_full_xml; case "${enableval}" in yes) full_xml=true ;; no) full_xml=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-full-xml" "$LINENO" 5 ;; esac else full_xml=false fi # Check whether --enable-mssql was given. if test "${enable_mssql+set}" = set; then : enableval=$enable_mssql; case "${enableval}" in yes) db_type=mssql ;; no) db_type=generic ;; *) as_fn_error $? "bad value ${enableval} for --enable-mssql" "$LINENO" 5 ;; esac else db_type=generic fi # Check whether --enable-all was given. if test "${enable_all+set}" = set; then : enableval=$enable_all; 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 ;; *) as_fn_error $? "bad value ${enableval} for --enable-all" "$LINENO" 5 ;; esac fi # Check whether --enable-tools was given. if test "${enable_tools+set}" = set; then : enableval=$enable_tools; case "${enableval}" in yes) tools=true ;; no) tools=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-tools" "$LINENO" 5 ;; esac else if test "x$tools" = "x"; then tools=false; fi fi # Check whether --enable-odbc was given. if test "${enable_odbc+set}" = set; then : enableval=$enable_odbc; case "${enableval}" in yes) odbc=true ;; no) odbc=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-odbc" "$LINENO" 5 ;; esac else if test "x$odbc" = "x"; then odbc=false; fi fi # Check whether --enable-mysql was given. if test "${enable_mysql+set}" = set; then : enableval=$enable_mysql; case "${enableval}" in yes) mysql=true ;; no) mysql=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-mysql" "$LINENO" 5 ;; esac else if test "x$mysql" = "x"; then mysql=false; fi fi # Check whether --enable-pgsql was given. if test "${enable_pgsql+set}" = set; then : enableval=$enable_pgsql; case "${enableval}" in yes) pgsql=true ;; no) pgsql=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-pgsql" "$LINENO" 5 ;; esac else if test "x$pgsql" = "x"; then pgsql=false; fi fi # Check whether --enable-sqlite was given. if test "${enable_sqlite+set}" = set; then : enableval=$enable_sqlite; case "${enableval}" in yes) sqlite=true ;; no) sqlite=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-sqlite" "$LINENO" 5 ;; esac else if test "x$sqlite" = "x"; then sqlite=false; fi fi # Check whether --enable-pam was given. if test "${enable_pam+set}" = set; then : enableval=$enable_pam; case "${enableval}" in yes) pam=true ;; no) pam=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-pam" "$LINENO" 5 ;; esac else if test "x$pam" = "x"; then pam=false; fi fi # Check whether --enable-zlib was given. if test "${enable_zlib+set}" = set; then : enableval=$enable_zlib; case "${enableval}" in yes) zlib=true ;; no) zlib=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-zlib" "$LINENO" 5 ;; esac else if test "x$zlib" = "x"; then zlib=true; fi fi # Check whether --enable-riak was given. if test "${enable_riak+set}" = set; then : enableval=$enable_riak; case "${enableval}" in yes) riak=true ;; no) riak=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-riak" "$LINENO" 5 ;; esac else if test "x$riak" = "x"; then riak=false; fi fi # Check whether --enable-redis was given. if test "${enable_redis+set}" = set; then : enableval=$enable_redis; case "${enableval}" in yes) redis=true ;; no) redis=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-redis" "$LINENO" 5 ;; esac else if test "x$redis" = "x"; then redis=false; fi fi # Check whether --enable-elixir was given. if test "${enable_elixir+set}" = set; then : enableval=$enable_elixir; case "${enableval}" in yes) elixir=true ;; no) elixir=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-elixir" "$LINENO" 5 ;; esac else if test "x$elixir" = "x"; then elixir=false; fi fi # Check whether --enable-iconv was given. if test "${enable_iconv+set}" = set; then : enableval=$enable_iconv; case "${enableval}" in yes) iconv=true ;; no) iconv=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-iconv" "$LINENO" 5 ;; esac else if test "x$iconv" = "x"; then iconv=true; fi fi # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; case "${enableval}" in yes) debug=true ;; no) debug=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-debug" "$LINENO" 5 ;; esac else if test "x$debug" = "x"; then debug=true; fi fi # Check whether --enable-lager was given. if test "${enable_lager+set}" = set; then : enableval=$enable_lager; case "${enableval}" in yes) lager=true ;; no) lager=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-lager" "$LINENO" 5 ;; esac else if test "x$lager" = "x"; then lager=true; fi fi # Check whether --enable-latest_deps was given. if test "${enable_latest_deps+set}" = set; then : enableval=$enable_latest_deps; case "${enableval}" in yes) latest_deps=true ;; no) latest_deps=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-latest-deps" "$LINENO" 5 ;; esac else if test "x$latest_deps" = "x"; then latest_deps=false; fi fi ac_config_files="$ac_config_files Makefile vars.config src/ejabberd.app.src" ENABLEUSER="" # Check whether --enable-user was given. if test "${enable_user+set}" = set; then : enableval=$enable_user; case "${enableval}" in yes) ENABLEUSER=`whoami` ;; no) ENABLEUSER="" ;; *) ENABLEUSER=$enableval esac fi if test "$ENABLEUSER" != ""; then echo "allow this system user to start ejabberd: $ENABLEUSER" INSTALLUSER=$ENABLEUSER fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Erlang is using deprecated types" >&5 $as_echo_n "checking whether Erlang is using deprecated types... " >&6; } cat > conftest.erl < /dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } erlang_deprecated_types=false else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } erlang_deprecated_types=true fi if test "$sqlite" = "true"; then ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Check whether --with-sqlite3 was given. if test "${with_sqlite3+set}" = set; then : withval=$with_sqlite3; if test "$withval" = "no"; then WANT_SQLITE3="no" elif test "$withval" = "yes"; then WANT_SQLITE3="yes" ac_sqlite3_path="" else WANT_SQLITE3="yes" ac_sqlite3_path="$withval" fi else WANT_SQLITE3="yes" fi SQLITE3_CFLAGS="" SQLITE3_LDFLAGS="" SQLITE3_VERSION="" if test "x$WANT_SQLITE3" = "xyes"; then ac_sqlite3_header="sqlite3.h" sqlite3_version_req=3.6.19 sqlite3_version_req_shorten=`expr $sqlite3_version_req : '\([0-9]*\.[0-9]*\)'` sqlite3_version_req_major=`expr $sqlite3_version_req : '\([0-9]*\)'` sqlite3_version_req_minor=`expr $sqlite3_version_req : '[0-9]*\.\([0-9]*\)'` sqlite3_version_req_micro=`expr $sqlite3_version_req : '[0-9]*\.[0-9]*\.\([0-9]*\)'` if test "x$sqlite3_version_req_micro" = "x" ; then sqlite3_version_req_micro="0" fi sqlite3_version_req_number=`expr $sqlite3_version_req_major \* 1000000 \ \+ $sqlite3_version_req_minor \* 1000 \ \+ $sqlite3_version_req_micro` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLite3 library >= $sqlite3_version_req" >&5 $as_echo_n "checking for SQLite3 library >= $sqlite3_version_req... " >&6; } if test "$ac_sqlite3_path" != ""; then ac_sqlite3_ldflags="-L$ac_sqlite3_path/lib" ac_sqlite3_cppflags="-I$ac_sqlite3_path/include" else for ac_sqlite3_path_tmp in /usr /usr/local /opt ; do if test -f "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header" \ && test -r "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header"; then ac_sqlite3_path=$ac_sqlite3_path_tmp ac_sqlite3_cppflags="-I$ac_sqlite3_path_tmp/include" ac_sqlite3_ldflags="-L$ac_sqlite3_path_tmp/lib" break; fi done fi ac_sqlite3_ldflags="$ac_sqlite3_ldflags -lsqlite3" saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $ac_sqlite3_cppflags" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if (SQLITE_VERSION_NUMBER >= $sqlite3_version_req_number) /* Everything is okay */ #else # error SQLite version is too old #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } success="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } success="no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CPPFLAGS="$saved_CPPFLAGS" if test "$success" = "yes"; then SQLITE3_CFLAGS="$ac_sqlite3_cppflags" SQLITE3_LDFLAGS="$ac_sqlite3_ldflags" ac_sqlite3_header_path="$ac_sqlite3_path/include/$ac_sqlite3_header" if test "x$ac_sqlite3_header_path" != "x"; then ac_sqlite3_version=`cat $ac_sqlite3_header_path \ | grep '#define.*SQLITE_VERSION.*\"' | sed -e 's/.* "//' \ | sed -e 's/"//'` if test $ac_sqlite3_version != ""; then SQLITE3_VERSION=$ac_sqlite3_version else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!" >&5 $as_echo "$as_me: WARNING: Cannot find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!" >&2;} fi fi $as_echo "#define HAVE_SQLITE3 /**/" >>confdefs.h fi fi if test "x$SQLITE3_VERSION" = "x"; then as_fn_error $? "SQLite3 library >= 3.6.19 was not found" "$LINENO" 5 fi fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by ejabberd $as_me 16.01, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ ejabberd config.status 16.01 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "vars.config") CONFIG_FILES="$CONFIG_FILES vars.config" ;; "src/ejabberd.app.src") CONFIG_FILES="$CONFIG_FILES src/ejabberd.app.src" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ejabberd-16.01/sql/0000755000232200023220000000000012645157216014435 5ustar debalancedebalanceejabberd-16.01/sql/mssql.sql0000644000232200023220000014131412645157216016321 0ustar debalancedebalanceÿþ-- -- 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. -- GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[archive] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[archive]( [username] [varchar](250) NOT NULL, [timestamp] [bigint] NOT NULL, [peer] [varchar](250) NOT NULL, [bare_peer] [varchar](250) NOT NULL, [xml] [text] NOT NULL, [txt] [text] NULL, [id] [bigint] IDENTITY(1,1) NOT NULL, [kind] [varchar](10) NULL, [nick] [varchar](250) NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [archive_PK] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO CREATE INDEX [archive_username] ON [archive] (username) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [archive_timestamp] ON [archive] (timestamp) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [archive_peer] ON [archive] (peer) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [archive_bare_peer] ON [archive] (bare_peer) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[archive_prefs] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[archive_prefs]( [username] [varchar](250) NOT NULL, [def] [text] NOT NULL, [always] [text] NOT NULL, [never] [text] NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [archive_prefs_PRIMARY] PRIMARY KEY CLUSTERED ( [username] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[caps_features] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[caps_features]( [node] [varchar](250) NOT NULL, [subnode] [varchar](250) NOT NULL, [feature] [text] NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE() ) TEXTIMAGE_ON [PRIMARY] GO CREATE CLUSTERED INDEX [caps_features_node_subnode] ON [caps_features] (node, subnode) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[irc_custom] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[irc_custom]( [jid] [varchar](255) NOT NULL, [host] [varchar](255) NOT NULL, [data] [text] NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE() ) TEXTIMAGE_ON [PRIMARY] GO CREATE UNIQUE CLUSTERED INDEX [irc_custom_jid_host] ON [irc_custom] (jid, host) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO /****** Object: Table [dbo].[last] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[last]( [username] [varchar](250) NOT NULL, [seconds] [text] NOT NULL, [state] [text] NOT NULL, CONSTRAINT [last_PRIMARY] PRIMARY KEY CLUSTERED ( [username] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[motd] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[motd]( [username] [varchar](250) NOT NULL, [xml] [text] NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [motd_PRIMARY] PRIMARY KEY CLUSTERED ( [username] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[muc_registered] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[muc_registered]( [jid] [varchar](255) NOT NULL, [host] [varchar](255) NOT NULL, [nick] [varchar](255) NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE() ) GO CREATE INDEX [muc_registered_nick] ON [muc_registered] (nick) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE UNIQUE CLUSTERED INDEX [muc_registered_jid_host] ON [muc_registered] (jid, host) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO /****** Object: Table [dbo].[muc_room] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[muc_room]( [name] [varchar](250) NOT NULL, [host] [varchar](250) NOT NULL, [opts] [text] NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE() ) TEXTIMAGE_ON [PRIMARY] GO CREATE UNIQUE CLUSTERED INDEX [muc_room_name_host] ON [muc_room] (name, host) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO /****** Object: Table [dbo].[privacy_default_list] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[privacy_default_list]( [username] [varchar](250) NOT NULL, [name] [varchar](250) NOT NULL, CONSTRAINT [privacy_default_list_PRIMARY] PRIMARY KEY CLUSTERED ( [username] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[privacy_list] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[privacy_list]( [username] [varchar](250) NOT NULL, [name] [varchar](250) NOT NULL, [id] [bigint] IDENTITY(1,1) NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [privacy_list_PK] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) GO CREATE INDEX [privacy_list_username] ON [privacy_list] (username) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE UNIQUE INDEX [privacy_list_username_name] ON [privacy_list] (username, name) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[privacy_list_data] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[privacy_list_data]( [id] [bigint] NULL, [t] [char](1) NOT NULL, [value] [text] NOT NULL, [action] [char](1) NOT NULL, [ord] [smallint] NOT NULL, [match_all] [smallint] NOT NULL, [match_iq] [smallint] NOT NULL, [match_message] [smallint] NOT NULL, [match_presence_in] [smallint] NOT NULL, [match_presence_out] [smallint] NOT NULL ) TEXTIMAGE_ON [PRIMARY] GO CREATE CLUSTERED INDEX [privacy_list_data_id] ON [privacy_list_data] (id) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[private_storage] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[private_storage]( [username] [varchar](250) NOT NULL, [namespace] [varchar](250) NOT NULL, [data] [text] NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE() ) TEXTIMAGE_ON [PRIMARY] GO CREATE INDEX [private_storage_username] ON [private_storage] (username) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE UNIQUE CLUSTERED INDEX [private_storage_username_namespace] ON [private_storage] (username, namespace) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[pubsub_item] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[pubsub_item]( [nodeid] [bigint] NULL, [itemid] [varchar](255) NULL, [publisher] [text] NULL, [creation] [text] NULL, [modification] [text] NULL, [payload] [text] NULL ) TEXTIMAGE_ON [PRIMARY] GO CREATE INDEX [pubsub_item_itemid] ON [pubsub_item] (itemid) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE UNIQUE CLUSTERED INDEX [pubsub_item_nodeid_itemid] ON [pubsub_item] (nodeid, itemid) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO /****** Object: Table [dbo].[pubsub_node] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[pubsub_node]( [host] [varchar](255) NULL, [node] [varchar](255) NULL, [parent] [varchar](255) NULL, [type] [text] NULL, [nodeid] [bigint] IDENTITY(1,1) NOT NULL, CONSTRAINT [pubsub_node_PRIMARY] PRIMARY KEY CLUSTERED ( [nodeid] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO CREATE INDEX [pubsub_node_parent] ON [pubsub_node] (parent) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE UNIQUE INDEX [pubsub_node_host_node] ON [pubsub_node] (host, node) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO /****** Object: Table [dbo].[pubsub_node_option] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[pubsub_node_option]( [nodeid] [bigint] NULL, [name] [text] NULL, [val] [text] NULL ) TEXTIMAGE_ON [PRIMARY] GO CREATE CLUSTERED INDEX [pubsub_node_option_nodeid] ON [pubsub_node_option] (nodeid) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO /****** Object: Table [dbo].[pubsub_node_owner] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[pubsub_node_owner]( [nodeid] [bigint] NULL, [owner] [text] NULL ) TEXTIMAGE_ON [PRIMARY] GO CREATE CLUSTERED INDEX [pubsub_node_owner_nodeid] ON [pubsub_node_owner] (nodeid) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO /****** Object: Table [dbo].[pubsub_state] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[pubsub_state]( [nodeid] [bigint] NULL, [jid] [varchar](255) NULL, [affiliation] [char](1) NULL, [subscriptions] [text] NULL, [stateid] [bigint] IDENTITY(1,1) NOT NULL, CONSTRAINT [pubsub_state_PRIMARY] PRIMARY KEY CLUSTERED ( [stateid] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO CREATE INDEX [pubsub_state_jid] ON [pubsub_state] (jid) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE UNIQUE INDEX [pubsub_state_nodeid_jid] ON [pubsub_state] (nodeid, jid) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[pubsub_subscription_opt] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[pubsub_subscription_opt]( [subid] [varchar](255) NULL, [opt_name] [varchar](32) NULL, [opt_value] [text] NULL ) TEXTIMAGE_ON [PRIMARY] GO CREATE UNIQUE CLUSTERED INDEX [pubsub_subscription_opt_subid_opt_name] ON [pubsub_subscription_opt] (subid, opt_name) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[roster_version] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[roster_version]( [username] [varchar](250) NOT NULL, [version] [text] NOT NULL, CONSTRAINT [roster_version_PRIMARY] PRIMARY KEY CLUSTERED ( [username] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[rostergroups] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[rostergroups]( [username] [varchar](250) NOT NULL, [jid] [varchar](250) NOT NULL, [grp] [text] NOT NULL ) TEXTIMAGE_ON [PRIMARY] GO CREATE CLUSTERED INDEX [rostergroups_username_jid] ON [rostergroups] ([username], [jid]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[rosterusers] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[rosterusers]( [username] [varchar](250) NOT NULL, [jid] [varchar](250) NOT NULL, [nick] [text] NOT NULL, [subscription] [char](1) NOT NULL, [ask] [char](1) NOT NULL, [askmessage] [text] NOT NULL, [server] [char](1) NOT NULL, [subscribe] [text] NOT NULL, [type] [text] NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE() ) TEXTIMAGE_ON [PRIMARY] GO CREATE UNIQUE CLUSTERED INDEX [rosterusers_username_jid] ON [rosterusers] ([username], [jid]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [rosterusers_username] ON [rosterusers] ([username]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [rosterusers_jid] ON [rosterusers] ([jid]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[sm] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[sm]( [usec] [bigint] NOT NULL, [pid] [varchar](100) NOT NULL, [node] [varchar](255) NOT NULL, [username] [varchar](255) NOT NULL, [resource] [varchar](255) NOT NULL, [priority] [text] NOT NULL, [info] [text] NOT NULL ) TEXTIMAGE_ON [PRIMARY] GO CREATE UNIQUE CLUSTERED INDEX [sm_sid] ON [sm] (usec, pid) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [sm_node] ON [sm] (node) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [sm_username] ON [sm] (username) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[spool] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[spool]( [username] [varchar](250) NOT NULL, [xml] [image] NOT NULL, [seq] [bigint] IDENTITY(1,1) NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [spool_PK] PRIMARY KEY CLUSTERED ( [seq] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO CREATE INDEX [spool_username] ON [spool] (username) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [spool_created_at] ON [spool] (created_at) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[sr_group] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[sr_group]( [name] [varchar](250) NOT NULL, [opts] [text] NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [sr_group_PRIMARY] PRIMARY KEY CLUSTERED ( [name] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[sr_user] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[sr_user]( [jid] [varchar](250) NOT NULL, [grp] [varchar](250) NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE() ) GO CREATE UNIQUE CLUSTERED INDEX [sr_user_jid_group] ON [sr_user] ([jid], [grp]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [sr_user_jid] ON [sr_user] ([jid]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [sr_user_grp] ON [sr_user] ([grp]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[users] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[users]( [username] [varchar](250) NOT NULL, [password] [text] NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [users_PRIMARY] PRIMARY KEY CLUSTERED ( [username] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[vcard] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[vcard]( [username] [varchar](250) NOT NULL, [vcard] [text] NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [vcard_PRIMARY] PRIMARY KEY CLUSTERED ( [username] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[vcard_search] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON 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, CONSTRAINT [vcard_search_PRIMARY] PRIMARY KEY CLUSTERED ( [lusername] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO CREATE INDEX [vcard_search_lfn] ON [vcard_search] (lfn) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lfamily] ON [vcard_search] (lfamily) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lgiven] ON [vcard_search] (lgiven) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lmiddle] ON [vcard_search] (lmiddle) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lnickname] ON [vcard_search] (lnickname) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lbday] ON [vcard_search] (lbday) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lctry] ON [vcard_search] (lctry) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_llocality] ON [vcard_search] (llocality) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lemail] ON [vcard_search] (lemail) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lorgname] ON [vcard_search] (lorgname) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO CREATE INDEX [vcard_search_lorgunit] ON [vcard_search] (lorgunit) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) GO SET ANSI_PADDING OFF GO /****** Object: Table [dbo].[vcard_xupdate] Script Date: 11.09.2015 14:53:04 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[vcard_xupdate]( [username] [varchar](250) NOT NULL, [hash] [text] NOT NULL, [created_at] [datetime] NOT NULL DEFAULT GETDATE(), CONSTRAINT [vcard_xupdate_PRIMARY] PRIMARY KEY CLUSTERED ( [username] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO ALTER TABLE [dbo].[pubsub_item] WITH CHECK ADD CONSTRAINT [pubsub_item_ibfk_1] FOREIGN KEY([nodeid]) REFERENCES [dbo].[pubsub_node] ([nodeid]) ON DELETE CASCADE GO ALTER TABLE [dbo].[pubsub_item] CHECK CONSTRAINT [pubsub_item_ibfk_1] GO ALTER TABLE [dbo].[pubsub_node_option] WITH CHECK ADD CONSTRAINT [pubsub_node_option_ibfk_1] FOREIGN KEY([nodeid]) REFERENCES [dbo].[pubsub_node] ([nodeid]) ON DELETE CASCADE GO ALTER TABLE [dbo].[pubsub_node_option] CHECK CONSTRAINT [pubsub_node_option_ibfk_1] GO ALTER TABLE [dbo].[pubsub_node_owner] WITH CHECK ADD CONSTRAINT [pubsub_node_owner_ibfk_1] FOREIGN KEY([nodeid]) REFERENCES [dbo].[pubsub_node] ([nodeid]) ON DELETE CASCADE GO ALTER TABLE [dbo].[pubsub_node_owner] CHECK CONSTRAINT [pubsub_node_owner_ibfk_1] GO ALTER TABLE [dbo].[pubsub_state] WITH CHECK ADD CONSTRAINT [pubsub_state_ibfk_1] FOREIGN KEY([nodeid]) REFERENCES [dbo].[pubsub_node] ([nodeid]) ON DELETE CASCADE GO ALTER TABLE [dbo].[pubsub_state] CHECK CONSTRAINT [pubsub_state_ibfk_1] GO ejabberd-16.01/sql/mysql.sql0000644000232200023220000002767712645157216016346 0ustar debalancedebalance-- -- 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. -- CREATE TABLE users ( username varchar(191) PRIMARY KEY, password text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- To support SCRAM auth: -- ALTER TABLE users ADD COLUMN serverkey text NOT NULL DEFAULT ''; -- ALTER TABLE users ADD COLUMN salt text NOT NULL DEFAULT ''; -- ALTER TABLE users ADD COLUMN iterationcount integer NOT NULL DEFAULT 0; CREATE TABLE last ( username varchar(191) PRIMARY KEY, seconds text NOT NULL, state text NOT NULl ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE rosterusers ( username varchar(191) NOT NULL, jid varchar(191) NOT NULL, nick text NOT NULL, subscription character(1) NOT NULL, ask character(1) NOT NULL, askmessage text NOT NULL, server character(1) NOT NULL, subscribe text NOT NULL, type text, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) 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(191) NOT NULL, jid varchar(191) NOT NULL, grp text NOT NULL ) 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(191) NOT NULL, opts text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE sr_user ( jid varchar(191) NOT NULL, grp varchar(191) NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) 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(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 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(191) NOT NULL, timestamp BIGINT UNSIGNED 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(191), created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) 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); 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(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 utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE vcard ( username varchar(191) PRIMARY KEY, vcard mediumtext NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE vcard_xupdate ( username varchar(191) PRIMARY KEY, hash text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE vcard_search ( username varchar(191) NOT NULL, lusername varchar(191) PRIMARY KEY, fn text NOT NULL, lfn varchar(191) NOT NULL, family text NOT NULL, lfamily varchar(191) NOT NULL, given text NOT NULL, lgiven varchar(191) NOT NULL, middle text NOT NULL, lmiddle varchar(191) NOT NULL, nickname text NOT NULL, lnickname varchar(191) NOT NULL, bday text NOT NULL, lbday varchar(191) NOT NULL, ctry text NOT NULL, lctry varchar(191) NOT NULL, locality text NOT NULL, llocality varchar(191) NOT NULL, email text NOT NULL, lemail varchar(191) NOT NULL, orgname text NOT NULL, lorgname varchar(191) NOT NULL, orgunit text NOT NULL, 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); CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven); CREATE INDEX i_vcard_search_lmiddle ON vcard_search(lmiddle); CREATE INDEX i_vcard_search_lnickname ON vcard_search(lnickname); CREATE INDEX i_vcard_search_lbday ON vcard_search(lbday); CREATE INDEX i_vcard_search_lctry ON vcard_search(lctry); CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality); CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail); 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(191) PRIMARY KEY, name varchar(191) NOT NULL ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE privacy_list ( 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 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)); CREATE TABLE privacy_list_data ( id bigint, t character(1) NOT NULL, value text NOT NULL, action character(1) NOT NULL, ord NUMERIC NOT NULL, match_all boolean NOT NULL, match_iq boolean NOT NULL, match_message boolean NOT NULL, match_presence_in boolean NOT NULL, match_presence_out boolean NOT NULL ) 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(191) NOT NULL, namespace varchar(191) NOT NULL, data text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) 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(191) PRIMARY KEY, version text NOT NULL ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- To update from 1.x: -- ALTER TABLE rosterusers ADD COLUMN askmessage text AFTER ask; -- UPDATE rosterusers SET askmessage = ''; -- ALTER TABLE rosterusers ALTER COLUMN askmessage SET NOT NULL; CREATE TABLE pubsub_node ( host text, node text, parent text, type text, nodeid bigint auto_increment primary key ) 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)); CREATE TABLE pubsub_node_option ( nodeid bigint, name text, val text ) 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 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; CREATE TABLE pubsub_state ( nodeid bigint, jid text, affiliation character(1), subscriptions text, stateid bigint auto_increment primary key ) 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; CREATE TABLE pubsub_item ( nodeid bigint, itemid text, publisher text, creation text, modification text, payload text ) 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; 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 ( name text NOT NULL, host text NOT NULL, opts text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) 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)); CREATE TABLE muc_registered ( jid text NOT NULL, host text NOT NULL, nick text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) 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)); CREATE TABLE irc_custom ( jid text NOT NULL, host text NOT NULL, data text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) 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(191) PRIMARY KEY, xml text, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE caps_features ( node varchar(191) NOT NULL, subnode varchar(191) NOT NULL, feature text, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_caps_features_node_subnode ON caps_features(node(75), subnode(75)); CREATE TABLE sm ( usec bigint NOT NULL, pid text NOT NULL, node text NOT NULL, username varchar(191) NOT NULL, resource varchar(191) NOT NULL, priority text NOT NULL, info text NOT NULL ) 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)); CREATE INDEX i_username ON sm(username); ejabberd-16.01/sql/pg.sql0000644000232200023220000002311612645157216015567 0ustar debalancedebalance-- -- 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. -- CREATE TABLE users ( username text PRIMARY KEY, "password" text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); -- To support SCRAM auth: -- ALTER TABLE users ADD COLUMN serverkey text NOT NULL DEFAULT ''; -- ALTER TABLE users ADD COLUMN salt text NOT NULL DEFAULT ''; -- ALTER TABLE users ADD COLUMN iterationcount integer NOT NULL DEFAULT 0; CREATE TABLE last ( username text PRIMARY KEY, seconds text NOT NULL, state text NOT NULL ); CREATE TABLE rosterusers ( username text NOT NULL, jid text NOT NULL, nick text NOT NULL, subscription character(1) NOT NULL, ask character(1) NOT NULL, askmessage text NOT NULL, server character(1) NOT NULL, subscribe text, "type" text, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers USING btree (username, jid); CREATE INDEX i_rosteru_username ON rosterusers USING btree (username); CREATE INDEX i_rosteru_jid ON rosterusers USING btree (jid); CREATE TABLE rostergroups ( username text NOT NULL, jid text NOT NULL, grp text NOT NULL ); CREATE INDEX pk_rosterg_user_jid ON rostergroups USING btree (username, jid); CREATE TABLE sr_group ( name text NOT NULL, opts text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE TABLE sr_user ( jid text NOT NULL, grp text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX i_sr_user_jid_grp ON sr_user USING btree (jid, grp); CREATE INDEX i_sr_user_jid ON sr_user USING btree (jid); CREATE INDEX i_sr_user_grp ON sr_user USING btree (grp); CREATE TABLE spool ( username text NOT NULL, xml text NOT NULL, seq SERIAL, created_at TIMESTAMP NOT NULL DEFAULT now() ); 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, kind text, nick text, 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, vcard text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE TABLE vcard_xupdate ( username text PRIMARY KEY, hash text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE TABLE vcard_search ( username text NOT NULL, lusername text PRIMARY KEY, fn text NOT NULL, lfn text NOT NULL, family text NOT NULL, lfamily text NOT NULL, given text NOT NULL, lgiven text NOT NULL, middle text NOT NULL, lmiddle text NOT NULL, nickname text NOT NULL, lnickname text NOT NULL, bday text NOT NULL, lbday text NOT NULL, ctry text NOT NULL, lctry text NOT NULL, locality text NOT NULL, llocality text NOT NULL, email text NOT NULL, lemail text NOT NULL, orgname text NOT NULL, lorgname text NOT NULL, orgunit text NOT NULL, lorgunit text NOT NULL ); CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn); CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily); CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven); CREATE INDEX i_vcard_search_lmiddle ON vcard_search(lmiddle); CREATE INDEX i_vcard_search_lnickname ON vcard_search(lnickname); CREATE INDEX i_vcard_search_lbday ON vcard_search(lbday); CREATE INDEX i_vcard_search_lctry ON vcard_search(lctry); CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality); CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail); 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 text PRIMARY KEY, name text NOT NULL ); CREATE TABLE privacy_list ( username text NOT NULL, name text NOT NULL, id SERIAL UNIQUE, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE INDEX i_privacy_list_username ON privacy_list USING btree (username); CREATE UNIQUE INDEX i_privacy_list_username_name ON privacy_list USING btree (username, name); CREATE TABLE privacy_list_data ( id bigint REFERENCES privacy_list(id) ON DELETE CASCADE, t character(1) NOT NULL, value text NOT NULL, action character(1) NOT NULL, ord NUMERIC NOT NULL, match_all boolean NOT NULL, match_iq boolean NOT NULL, match_message boolean NOT NULL, match_presence_in boolean NOT NULL, match_presence_out boolean NOT NULL ); CREATE INDEX i_privacy_list_data_id ON privacy_list_data USING btree (id); CREATE TABLE private_storage ( username text NOT NULL, namespace text NOT NULL, data text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE INDEX i_private_storage_username ON private_storage USING btree (username); CREATE UNIQUE INDEX i_private_storage_username_namespace ON private_storage USING btree (username, namespace); CREATE TABLE roster_version ( username text PRIMARY KEY, version text NOT NULL ); -- To update from 0.9.8: -- 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; -- To update from 1.x: -- ALTER TABLE rosterusers ADD COLUMN askmessage text; -- UPDATE rosterusers SET askmessage = ''; -- ALTER TABLE rosterusers ALTER COLUMN askmessage SET NOT NULL; CREATE TABLE pubsub_node ( host text, node text, parent text, "type" text, nodeid SERIAL UNIQUE ); CREATE INDEX i_pubsub_node_parent ON pubsub_node USING btree (parent); CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node USING btree (host, node); CREATE TABLE pubsub_node_option ( nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE, name text, val text ); CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option USING btree (nodeid); CREATE TABLE pubsub_node_owner ( nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE, owner text ); CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner USING btree (nodeid); CREATE TABLE pubsub_state ( nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE, jid text, affiliation character(1), subscriptions text, stateid SERIAL UNIQUE ); CREATE INDEX i_pubsub_state_jid ON pubsub_state USING btree (jid); CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state USING btree (nodeid, jid); CREATE TABLE pubsub_item ( nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE, itemid text, publisher text, creation text, modification text, payload text ); CREATE INDEX i_pubsub_item_itemid ON pubsub_item USING btree (itemid); CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item USING btree (nodeid, itemid); CREATE TABLE pubsub_subscription_opt ( subid text, opt_name varchar(32), opt_value text ); CREATE UNIQUE INDEX i_pubsub_subscription_opt ON pubsub_subscription_opt USING btree (subid, opt_name); CREATE TABLE muc_room ( name text NOT NULL, host text NOT NULL, opts text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room USING btree (name, host); CREATE TABLE muc_registered ( jid text NOT NULL, host text NOT NULL, nick text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE INDEX i_muc_registered_nick ON muc_registered USING btree (nick); CREATE UNIQUE INDEX i_muc_registered_jid_host ON muc_registered USING btree (jid, host); CREATE TABLE irc_custom ( jid text NOT NULL, host text NOT NULL, data text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom USING btree (jid, host); CREATE TABLE motd ( username text PRIMARY KEY, xml text, created_at TIMESTAMP NOT NULL DEFAULT now() ); CREATE TABLE caps_features ( node text NOT NULL, subnode text NOT NULL, feature text, created_at TIMESTAMP NOT NULL DEFAULT now() ); 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_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); ejabberd-16.01/sql/lite.sql0000644000232200023220000002062312645157216016116 0ustar debalancedebalance-- -- 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. -- CREATE TABLE users ( username text PRIMARY KEY, password text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE last ( username text PRIMARY KEY, seconds text NOT NULL, state text NOT NULL ); CREATE TABLE rosterusers ( username text NOT NULL, jid text NOT NULL, nick text NOT NULL, subscription character(1) NOT NULL, ask character(1) NOT NULL, askmessage text NOT NULL, server character(1) NOT NULL, subscribe text, type text, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers (username, jid); CREATE INDEX i_rosteru_username ON rosterusers (username); CREATE INDEX i_rosteru_jid ON rosterusers (jid); CREATE TABLE rostergroups ( username text NOT NULL, jid text NOT NULL, grp text NOT NULL ); CREATE INDEX pk_rosterg_user_jid ON rostergroups (username, jid); CREATE TABLE sr_group ( name text NOT NULL, opts text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE sr_user ( jid text NOT NULL, grp text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE UNIQUE INDEX i_sr_user_jid_grp ON sr_user (jid, grp); CREATE INDEX i_sr_user_jid ON sr_user (jid); CREATE INDEX i_sr_user_grp ON sr_user (grp); CREATE TABLE spool ( username text NOT NULL, xml text NOT NULL, seq INTEGER PRIMARY KEY AUTOINCREMENT, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX i_despool ON spool (username); CREATE TABLE vcard ( username text PRIMARY KEY, vcard text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE vcard_xupdate ( username text PRIMARY KEY, hash text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE vcard_search ( username text NOT NULL, lusername text PRIMARY KEY, fn text NOT NULL, lfn text NOT NULL, family text NOT NULL, lfamily text NOT NULL, given text NOT NULL, lgiven text NOT NULL, middle text NOT NULL, lmiddle text NOT NULL, nickname text NOT NULL, lnickname text NOT NULL, bday text NOT NULL, lbday text NOT NULL, ctry text NOT NULL, lctry text NOT NULL, locality text NOT NULL, llocality text NOT NULL, email text NOT NULL, lemail text NOT NULL, orgname text NOT NULL, lorgname text NOT NULL, orgunit text NOT NULL, lorgunit text NOT NULL ); CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn); CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily); CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven); CREATE INDEX i_vcard_search_lmiddle ON vcard_search(lmiddle); CREATE INDEX i_vcard_search_lnickname ON vcard_search(lnickname); CREATE INDEX i_vcard_search_lbday ON vcard_search(lbday); CREATE INDEX i_vcard_search_lctry ON vcard_search(lctry); CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality); CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail); 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 text PRIMARY KEY, name text NOT NULL ); CREATE TABLE privacy_list ( username text NOT NULL, name text NOT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX i_privacy_list_username ON privacy_list (username); CREATE UNIQUE INDEX i_privacy_list_username_name ON privacy_list (username, name); CREATE TABLE privacy_list_data ( id bigint REFERENCES privacy_list(id) ON DELETE CASCADE, t character(1) NOT NULL, value text NOT NULL, action character(1) NOT NULL, ord NUMERIC NOT NULL, match_all boolean NOT NULL, match_iq boolean NOT NULL, match_message boolean NOT NULL, match_presence_in boolean NOT NULL, match_presence_out boolean NOT NULL ); CREATE TABLE private_storage ( username text NOT NULL, namespace text NOT NULL, data text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX i_private_storage_username ON private_storage (username); CREATE UNIQUE INDEX i_private_storage_username_namespace ON private_storage (username, namespace); CREATE TABLE roster_version ( username text PRIMARY KEY, version text NOT NULL ); CREATE TABLE pubsub_node ( host text, node text, parent text, type text, nodeid INTEGER PRIMARY KEY AUTOINCREMENT ); CREATE INDEX i_pubsub_node_parent ON pubsub_node (parent); CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node (host, node); CREATE TABLE pubsub_node_option ( nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE, name text, val text ); CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option (nodeid); CREATE TABLE pubsub_node_owner ( nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE, owner text ); CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner (nodeid); CREATE TABLE pubsub_state ( nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE, jid text, affiliation character(1), subscriptions text, stateid INTEGER PRIMARY KEY AUTOINCREMENT ); CREATE INDEX i_pubsub_state_jid ON pubsub_state (jid); CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state (nodeid, jid); CREATE TABLE pubsub_item ( nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE, itemid text, publisher text, creation text, modification text, payload text ); CREATE INDEX i_pubsub_item_itemid ON pubsub_item (itemid); CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item (nodeid, itemid); CREATE TABLE pubsub_subscription_opt ( subid text, opt_name varchar(32), opt_value text ); CREATE UNIQUE INDEX i_pubsub_subscription_opt ON pubsub_subscription_opt (subid, opt_name); CREATE TABLE muc_room ( name text NOT NULL, host text NOT NULL, opts text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room (name, host); CREATE TABLE muc_registered ( jid text NOT NULL, host text NOT NULL, nick text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX i_muc_registered_nick ON muc_registered (nick); CREATE UNIQUE INDEX i_muc_registered_jid_host ON muc_registered (jid, host); CREATE TABLE irc_custom ( jid text NOT NULL, host text NOT NULL, data text NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom (jid, host); CREATE TABLE motd ( username text PRIMARY KEY, xml text, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE caps_features ( node text NOT NULL, subnode text NOT NULL, feature text, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); 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, kind text, nick text, 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 ); ejabberd-16.01/src/0000755000232200023220000000000012645157216014425 5ustar debalancedebalanceejabberd-16.01/src/mod_pres_counter.erl0000644000232200023220000000753212645157216020507 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_pres_counter.erl %%% Author : Ahmed Omar %%% Purpose : Presence subscription flood prevention %%% Created : 23 Sep 2010 by Ahmed Omar %%% %%% %%% 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_pres_counter). -behavior(gen_mod). -export([start/2, stop/1, check_packet/6, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -record(pres_counter, {dir, start, count, logged = false}). start(Host, _Opts) -> ejabberd_hooks:add(privacy_check_packet, Host, ?MODULE, check_packet, 25), ok. stop(Host) -> ejabberd_hooks:delete(privacy_check_packet, Host, ?MODULE, check_packet, 25), ok. 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) of <<"subscribe">> -> true; <<"subscribed">> -> true; <<"unsubscribe">> -> true; <<"unsubscribed">> -> true; _ -> false end, if IsSubscription -> JID = case Dir of in -> To; out -> From end, update(Server, JID, Dir); true -> allow end; _ -> allow end. update(Server, JID, Dir) -> StormCount = gen_mod:get_module_opt(Server, ?MODULE, count, fun(I) when is_integer(I), I>0 -> I end, 5), TimeInterval = gen_mod:get_module_opt(Server, ?MODULE, interval, fun(I) when is_integer(I), I>0 -> I end, 60), TimeStamp = p1_time_compat:system_time(seconds), case read(Dir) of undefined -> write(Dir, #pres_counter{dir = Dir, start = TimeStamp, count = 1}), allow; #pres_counter{start = TimeStart, count = Count, logged = Logged} = R -> if TimeStamp - TimeStart > TimeInterval -> write(Dir, R#pres_counter{start = TimeStamp, count = 1}), allow; (Count =:= StormCount) and Logged -> {stop, deny}; Count =:= StormCount -> write(Dir, R#pres_counter{logged = true}), case Dir of in -> ?WARNING_MSG("User ~s is being flooded, ignoring received " "presence subscriptions", [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", [jid:to_string(JID), jlib:ip_to_list(IP)]) end, {stop, deny}; true -> write(Dir, R#pres_counter{start = TimeStamp, count = Count + 1}), allow end end. 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]. ejabberd-16.01/src/ejabberd_sm_mnesia.erl0000644000232200023220000001024512645157216020724 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov %%% @copyright (C) 2015, Evgeny Khramtsov %%% @doc %%% %%% @end %%% Created : 9 Mar 2015 by Evgeny Khramtsov %%%------------------------------------------------------------------- -module(ejabberd_sm_mnesia). -behaviour(gen_server). -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]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("ejabberd.hrl"). -include("ejabberd_sm.hrl"). -include("jlib.hrl"). -include_lib("stdlib/include/ms_transform.hrl"). -record(state, {}). %%%=================================================================== %%% API %%%=================================================================== -spec init() -> ok | {error, any()}. init() -> case gen_server:start_link({local, ?MODULE}, ?MODULE, [], []) of {ok, _Pid} -> ok; Err -> Err end. -spec set_session(#session{}) -> ok. set_session(Session) -> mnesia:dirty_write(Session). -spec delete_session(binary(), binary(), binary(), sid()) -> {ok, #session{}} | {error, notfound}. delete_session(_LUser, _LServer, _LResource, SID) -> case mnesia:dirty_read(session, SID) of [Session] -> mnesia:dirty_delete(session, SID), {ok, Session}; [] -> {error, notfound} end. -spec get_sessions() -> [#session{}]. get_sessions() -> ets:tab2list(session). -spec get_sessions(binary()) -> [#session{}]. get_sessions(LServer) -> mnesia:dirty_select(session, [{#session{usr = '$1', _ = '_'}, [{'==', {element, 2, '$1'}, LServer}], ['$_']}]). -spec get_sessions(binary(), binary()) -> [#session{}]. get_sessions(LUser, LServer) -> mnesia:dirty_index_read(session, {LUser, LServer}, #session.us). -spec get_sessions(binary(), binary(), binary()) -> [#session{}]. get_sessions(LUser, LServer, LResource) -> mnesia:dirty_index_read(session, {LUser, LServer, LResource}, #session.usr). %%%=================================================================== %%% gen_server callbacks %%%=================================================================== init([]) -> update_tables(), mnesia:create_table(session, [{ram_copies, [node()]}, {attributes, record_info(fields, session)}]), mnesia:create_table(session_counter, [{ram_copies, [node()]}, {attributes, record_info(fields, session_counter)}]), mnesia:add_table_index(session, usr), mnesia:add_table_index(session, us), mnesia:add_table_copy(session, node(), ram_copies), mnesia:add_table_copy(session_counter, node(), ram_copies), mnesia:subscribe(system), {ok, #state{}}. handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({mnesia_system_event, {mnesia_down, Node}}, State) -> ets:select_delete( session, ets:fun2ms( fun(#session{sid = {_, Pid}}) -> node(Pid) == Node end)), {noreply, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%%=================================================================== %%% Internal functions %%%=================================================================== update_tables() -> case catch mnesia:table_info(session, attributes) of [ur, user, node] -> mnesia:delete_table(session); [ur, user, pid] -> mnesia:delete_table(session); [usr, us, pid] -> mnesia:delete_table(session); [usr, us, sid, priority, info] -> mnesia:delete_table(session); [sid, usr, us, priority] -> mnesia:delete_table(session); [sid, usr, us, priority, info] -> ok; {'EXIT', _} -> ok end, case lists:member(presence, mnesia:system_info(tables)) of true -> mnesia:delete_table(presence); false -> ok end, case lists:member(local_session, mnesia:system_info(tables)) of true -> mnesia:delete_table(local_session); false -> ok end. ejabberd-16.01/src/mod_announce.erl0000644000232200023220000011421512645157216017602 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_announce.erl %%% Author : Alexey Shchepin %%% Purpose : Manage announce messages %%% Created : 11 Aug 2003 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. %%% %%%---------------------------------------------------------------------- %%% Implements a small subset of XEP-0133: Service Administration %%% Version 1.1 (2005-08-19) -module(mod_announce). -author('alexey@process-one.net'). -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, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("adhoc.hrl"). -record(motd, {server = <<"">> :: binary(), packet = #xmlel{} :: xmlel()}). -record(motd_users, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$1', dummy = [] :: [] | '_'}). -define(PROCNAME, ejabberd_announce). -define(NS_ADMINL(Sub), [<<"http:">>, <<"jabber.org">>, <<"protocol">>, <<"admin">>, <>]). tokenize(Node) -> str:tokens(Node, <<"/#">>). start(Host, Opts) -> case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(motd, [{disc_copies, [node()]}, {attributes, record_info(fields, motd)}]), mnesia:create_table(motd_users, [{disc_copies, [node()]}, {attributes, record_info(fields, motd_users)}]), update_tables(); _ -> ok end, ejabberd_hooks:add(local_send_to_resource_hook, Host, ?MODULE, announce, 50), ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, disco_identity, 50), ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50), ejabberd_hooks:add(disco_local_items, Host, ?MODULE, disco_items, 50), ejabberd_hooks:add(adhoc_local_items, Host, ?MODULE, announce_items, 50), ejabberd_hooks:add(adhoc_local_commands, Host, ?MODULE, announce_commands, 50), ejabberd_hooks:add(user_available_hook, Host, ?MODULE, send_motd, 50), register(gen_mod:get_module_proc(Host, ?PROCNAME), proc_lib:spawn(?MODULE, init, [])). init() -> loop(). loop() -> receive {announce_all, From, To, Packet} -> announce_all(From, To, Packet), loop(); {announce_all_hosts_all, From, To, Packet} -> announce_all_hosts_all(From, To, Packet), loop(); {announce_online, From, To, Packet} -> announce_online(From, To, Packet), loop(); {announce_all_hosts_online, From, To, Packet} -> announce_all_hosts_online(From, To, Packet), loop(); {announce_motd, From, To, Packet} -> announce_motd(From, To, Packet), loop(); {announce_all_hosts_motd, From, To, Packet} -> announce_all_hosts_motd(From, To, Packet), loop(); {announce_motd_update, From, To, Packet} -> announce_motd_update(From, To, Packet), loop(); {announce_all_hosts_motd_update, From, To, Packet} -> announce_all_hosts_motd_update(From, To, Packet), loop(); {announce_motd_delete, From, To, Packet} -> announce_motd_delete(From, To, Packet), loop(); {announce_all_hosts_motd_delete, From, To, Packet} -> announce_all_hosts_motd_delete(From, To, Packet), loop(); _ -> loop() end. stop(Host) -> ejabberd_hooks:delete(adhoc_local_commands, Host, ?MODULE, announce_commands, 50), ejabberd_hooks:delete(adhoc_local_items, Host, ?MODULE, announce_items, 50), ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, disco_identity, 50), ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 50), ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, disco_items, 50), ejabberd_hooks:delete(local_send_to_resource_hook, Host, ?MODULE, announce, 50), ejabberd_hooks:delete(user_available_hook, Host, ?MODULE, send_motd, 50), Proc = gen_mod:get_module_proc(Host, ?PROCNAME), exit(whereis(Proc), stop), {wait, Proc}. %% Announcing via messages to a custom resource announce(From, #jid{luser = <<>>} = To, #xmlel{name = <<"message">>} = Packet) -> Proc = gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME), case To#jid.lresource of <<"announce/all">> -> Proc ! {announce_all, From, To, Packet}, stop; <<"announce/all-hosts/all">> -> Proc ! {announce_all_hosts_all, From, To, Packet}, stop; <<"announce/online">> -> Proc ! {announce_online, From, To, Packet}, stop; <<"announce/all-hosts/online">> -> Proc ! {announce_all_hosts_online, From, To, Packet}, stop; <<"announce/motd">> -> Proc ! {announce_motd, From, To, Packet}, stop; <<"announce/all-hosts/motd">> -> Proc ! {announce_all_hosts_motd, From, To, Packet}, stop; <<"announce/motd/update">> -> Proc ! {announce_motd_update, From, To, Packet}, stop; <<"announce/all-hosts/motd/update">> -> Proc ! {announce_all_hosts_motd_update, From, To, Packet}, stop; <<"announce/motd/delete">> -> Proc ! {announce_motd_delete, From, To, Packet}, stop; <<"announce/all-hosts/motd/delete">> -> Proc ! {announce_all_hosts_motd_delete, From, To, Packet}, stop; _ -> ok end; announce(_From, _To, _Packet) -> ok. %%------------------------------------------------------------------------- %% Announcing via ad-hoc commands -define(INFO_COMMAND(Lang, Node), [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"automation">>}, {<<"type">>, <<"command-node">>}, {<<"name">>, get_title(Lang, Node)}]}]). disco_identity(Acc, _From, _To, Node, Lang) -> LNode = tokenize(Node), case LNode of ?NS_ADMINL("announce") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("announce-allhosts") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("announce-all") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("announce-all-allhosts") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("set-motd") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("set-motd-allhosts") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("edit-motd") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("edit-motd-allhosts") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("delete-motd") -> ?INFO_COMMAND(Lang, Node); ?NS_ADMINL("delete-motd-allhosts") -> ?INFO_COMMAND(Lang, Node); _ -> Acc end. %%------------------------------------------------------------------------- -define(INFO_RESULT(Allow, Feats), case Allow of deny -> {error, ?ERR_FORBIDDEN}; allow -> {result, Feats} end). disco_features(Acc, From, #jid{lserver = LServer} = _To, <<"announce">>, _Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> Access1 = get_access(LServer), Access2 = get_access(global), case {acl:match_rule(LServer, Access1, From), acl:match_rule(global, Access2, From)} of {deny, deny} -> {error, ?ERR_FORBIDDEN}; _ -> {result, []} end end; disco_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> Access = get_access(LServer), Allow = acl:match_rule(LServer, Access, From), AccessGlobal = get_access(global), AllowGlobal = acl:match_rule(global, AccessGlobal, From), case Node of ?NS_ADMIN_ANNOUNCE -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMIN_ANNOUNCE_ALL -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMIN_SET_MOTD -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMIN_EDIT_MOTD -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMIN_DELETE_MOTD -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMIN_ANNOUNCE_ALLHOSTS -> ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); ?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS -> ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); ?NS_ADMIN_SET_MOTD_ALLHOSTS -> ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); ?NS_ADMIN_EDIT_MOTD_ALLHOSTS -> ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); ?NS_ADMIN_DELETE_MOTD_ALLHOSTS -> ?INFO_RESULT(AllowGlobal, [?NS_COMMANDS]); _ -> Acc end end. %%------------------------------------------------------------------------- -define(NODE_TO_ITEM(Lang, Server, Node), ( #xmlel{ name = <<"item">>, attrs = [ {<<"jid">>, Server}, {<<"node">>, Node}, {<<"name">>, get_title(Lang, Node)} ] } )). -define(ITEMS_RESULT(Allow, Items), case Allow of deny -> {error, ?ERR_FORBIDDEN}; allow -> {result, Items} end). disco_items(Acc, From, #jid{lserver = LServer, server = Server} = _To, <<>>, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> Access1 = get_access(LServer), Access2 = get_access(global), case {acl:match_rule(LServer, Access1, From), acl:match_rule(global, Access2, From)} of {deny, deny} -> Acc; _ -> Items = case Acc of {result, I} -> I; _ -> [] end, Nodes = [?NODE_TO_ITEM(Lang, Server, <<"announce">>)], {result, Items ++ Nodes} end end; disco_items(Acc, From, #jid{lserver = LServer} = To, <<"announce">>, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> announce_items(Acc, From, To, Lang) end; disco_items(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> Access = get_access(LServer), Allow = acl:match_rule(LServer, Access, From), AccessGlobal = get_access(global), AllowGlobal = acl:match_rule(global, AccessGlobal, From), case Node of ?NS_ADMIN_ANNOUNCE -> ?ITEMS_RESULT(Allow, []); ?NS_ADMIN_ANNOUNCE_ALL -> ?ITEMS_RESULT(Allow, []); ?NS_ADMIN_SET_MOTD -> ?ITEMS_RESULT(Allow, []); ?NS_ADMIN_EDIT_MOTD -> ?ITEMS_RESULT(Allow, []); ?NS_ADMIN_DELETE_MOTD -> ?ITEMS_RESULT(Allow, []); ?NS_ADMIN_ANNOUNCE_ALLHOSTS -> ?ITEMS_RESULT(AllowGlobal, []); ?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS -> ?ITEMS_RESULT(AllowGlobal, []); ?NS_ADMIN_SET_MOTD_ALLHOSTS -> ?ITEMS_RESULT(AllowGlobal, []); ?NS_ADMIN_EDIT_MOTD_ALLHOSTS -> ?ITEMS_RESULT(AllowGlobal, []); ?NS_ADMIN_DELETE_MOTD_ALLHOSTS -> ?ITEMS_RESULT(AllowGlobal, []); _ -> Acc end end. %%------------------------------------------------------------------------- announce_items(Acc, From, #jid{lserver = LServer, server = Server} = _To, Lang) -> Access1 = get_access(LServer), Nodes1 = case acl:match_rule(LServer, Access1, From) of allow -> [?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_ANNOUNCE), ?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_ANNOUNCE_ALL), ?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_SET_MOTD), ?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_EDIT_MOTD), ?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_DELETE_MOTD)]; deny -> [] end, Access2 = get_access(global), Nodes2 = case acl:match_rule(global, Access2, From) of allow -> [?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_ANNOUNCE_ALLHOSTS), ?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS), ?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_SET_MOTD_ALLHOSTS), ?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_EDIT_MOTD_ALLHOSTS), ?NODE_TO_ITEM(Lang, Server, ?NS_ADMIN_DELETE_MOTD_ALLHOSTS)]; deny -> [] end, case {Nodes1, Nodes2} of {[], []} -> Acc; _ -> Items = case Acc of {result, I} -> I; _ -> [] end, {result, Items ++ Nodes1 ++ Nodes2} end. %%------------------------------------------------------------------------- commands_result(Allow, From, To, Request) -> case Allow of deny -> {error, ?ERR_FORBIDDEN}; allow -> announce_commands(From, To, Request) end. announce_commands(Acc, From, #jid{lserver = LServer} = To, #adhoc_request{ node = Node} = Request) -> LNode = tokenize(Node), F = fun() -> Access = get_access(global), Allow = acl:match_rule(global, Access, From), commands_result(Allow, From, To, Request) end, R = case LNode of ?NS_ADMINL("announce-allhosts") -> F(); ?NS_ADMINL("announce-all-allhosts") -> F(); ?NS_ADMINL("set-motd-allhosts") -> F(); ?NS_ADMINL("edit-motd-allhosts") -> F(); ?NS_ADMINL("delete-motd-allhosts") -> F(); _ -> Access = get_access(LServer), Allow = acl:match_rule(LServer, Access, From), case LNode of ?NS_ADMINL("announce") -> commands_result(Allow, From, To, Request); ?NS_ADMINL("announce-all") -> commands_result(Allow, From, To, Request); ?NS_ADMINL("set-motd") -> commands_result(Allow, From, To, Request); ?NS_ADMINL("edit-motd") -> commands_result(Allow, From, To, Request); ?NS_ADMINL("delete-motd") -> commands_result(Allow, From, To, Request); _ -> unknown end end, case R of unknown -> Acc; _ -> {stop, R} end. %%------------------------------------------------------------------------- announce_commands(From, To, #adhoc_request{lang = Lang, node = Node, action = Action, xdata = XData} = Request) -> %% If the "action" attribute is not present, it is %% understood as "execute". If there was no %% element in the first response (which there isn't in our %% case), "execute" and "complete" are equivalent. ActionIsExecute = lists:member(Action, [<<>>, <<"execute">>, <<"complete">>]), if Action == <<"cancel">> -> %% User cancels request adhoc:produce_response(Request, #adhoc_response{status = canceled}); XData == false, ActionIsExecute -> %% User requests form Elements = generate_adhoc_form(Lang, Node, To#jid.lserver), adhoc:produce_response(Request, #adhoc_response{status = executing,elements = [Elements]}); XData /= false, ActionIsExecute -> %% User returns form. case jlib:parse_xdata_submit(XData) of invalid -> {error, ?ERR_BAD_REQUEST}; Fields -> handle_adhoc_form(From, To, Request, Fields) end; true -> {error, ?ERR_BAD_REQUEST} end. -define(VVALUE(Val), ( #xmlel{ name = <<"value">>, children = [{xmlcdata, Val}] } )). -define(TVFIELD(Type, Var, Val), ( #xmlel{ name = <<"field">>, attrs = [{<<"type">>, Type}, {<<"var">>, Var}], children = vvaluel(Val) } )). -define(HFIELD(), ?TVFIELD(<<"hidden">>, <<"FORM_TYPE">>, ?NS_ADMIN)). vvaluel(Val) -> case Val of <<>> -> []; _ -> [?VVALUE(Val)] end. generate_adhoc_form(Lang, Node, ServerHost) -> LNode = tokenize(Node), {OldSubject, OldBody} = if (LNode == ?NS_ADMINL("edit-motd")) or (LNode == ?NS_ADMINL("edit-motd-allhosts")) -> get_stored_motd(ServerHost); true -> {<<>>, <<>>} end, #xmlel{ name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = [ ?HFIELD(), #xmlel{name = <<"title">>, children = [{xmlcdata, get_title(Lang, Node)}]} ] ++ if (LNode == ?NS_ADMINL("delete-motd")) or (LNode == ?NS_ADMINL("delete-motd-allhosts")) -> [#xmlel{ name = <<"field">>, attrs = [ {<<"var">>, <<"confirm">>}, {<<"type">>, <<"boolean">>}, {<<"label">>, translate:translate(Lang, <<"Really delete message of the day?">>)} ], children = [ #xmlel{name = <<"value">>, children = [{xmlcdata, <<"true">>}]} ] } ]; true -> [#xmlel{ name = <<"field">>, attrs = [ {<<"var">>, <<"subject">>}, {<<"type">>, <<"text-single">>}, {<<"label">>, translate:translate(Lang, <<"Subject">>)}], children = vvaluel(OldSubject) }, #xmlel{ name = <<"field">>, attrs = [ {<<"var">>, <<"body">>}, {<<"type">>, <<"text-multi">>}, {<<"label">>, translate:translate(Lang, <<"Message body">>)}], children = vvaluel(OldBody) } ] end}. join_lines([]) -> <<>>; join_lines(Lines) -> join_lines(Lines, []). join_lines([Line|Lines], Acc) -> join_lines(Lines, [<<"\n">>,Line|Acc]); join_lines([], Acc) -> %% Remove last newline iolist_to_binary(lists:reverse(tl(Acc))). handle_adhoc_form(From, #jid{lserver = LServer} = To, #adhoc_request{lang = Lang, node = Node, sessionid = SessionID}, Fields) -> Confirm = case lists:keysearch(<<"confirm">>, 1, Fields) of {value, {<<"confirm">>, [<<"true">>]}} -> true; {value, {<<"confirm">>, [<<"1">>]}} -> true; _ -> false end, Subject = case lists:keysearch(<<"subject">>, 1, Fields) of {value, {<<"subject">>, SubjectLines}} -> %% There really shouldn't be more than one %% subject line, but can we stop them? join_lines(SubjectLines); _ -> <<>> end, Body = case lists:keysearch(<<"body">>, 1, Fields) of {value, {<<"body">>, BodyLines}} -> join_lines(BodyLines); _ -> <<>> end, Response = #adhoc_response{lang = Lang, node = Node, sessionid = SessionID, status = completed}, Packet = #xmlel{ name = <<"message">>, attrs = [{<<"type">>, <<"headline">>}], children = if Subject /= <<>> -> [#xmlel{name = <<"subject">>, children = [{xmlcdata, Subject}]}]; true -> [] end ++ if Body /= <<>> -> [#xmlel{name = <<"body">>, children = [{xmlcdata, Body}]}]; true -> [] end }, Proc = gen_mod:get_module_proc(LServer, ?PROCNAME), case {Node, Body} of {?NS_ADMIN_DELETE_MOTD, _} -> if Confirm -> Proc ! {announce_motd_delete, From, To, Packet}, adhoc:produce_response(Response); true -> adhoc:produce_response(Response) end; {?NS_ADMIN_DELETE_MOTD_ALLHOSTS, _} -> if Confirm -> Proc ! {announce_all_hosts_motd_delete, From, To, Packet}, adhoc:produce_response(Response); true -> adhoc:produce_response(Response) end; {_, <<>>} -> %% An announce message with no body is definitely an operator error. %% Throw an error and give him/her a chance to send message again. {error, ?ERRT_NOT_ACCEPTABLE(Lang, <<"No body provided for announce message">>)}; %% Now send the packet to ?PROCNAME. %% We don't use direct announce_* functions because it %% leads to large delay in response and queries processing {?NS_ADMIN_ANNOUNCE, _} -> Proc ! {announce_online, From, To, Packet}, adhoc:produce_response(Response); {?NS_ADMIN_ANNOUNCE_ALLHOSTS, _} -> Proc ! {announce_all_hosts_online, From, To, Packet}, adhoc:produce_response(Response); {?NS_ADMIN_ANNOUNCE_ALL, _} -> Proc ! {announce_all, From, To, Packet}, adhoc:produce_response(Response); {?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS, _} -> Proc ! {announce_all_hosts_all, From, To, Packet}, adhoc:produce_response(Response); {?NS_ADMIN_SET_MOTD, _} -> Proc ! {announce_motd, From, To, Packet}, adhoc:produce_response(Response); {?NS_ADMIN_SET_MOTD_ALLHOSTS, _} -> Proc ! {announce_all_hosts_motd, From, To, Packet}, adhoc:produce_response(Response); {?NS_ADMIN_EDIT_MOTD, _} -> Proc ! {announce_motd_update, From, To, Packet}, adhoc:produce_response(Response); {?NS_ADMIN_EDIT_MOTD_ALLHOSTS, _} -> Proc ! {announce_all_hosts_motd_update, From, To, Packet}, adhoc:produce_response(Response); _ -> %% This can't happen, as we haven't registered any other %% command nodes. {error, ?ERR_INTERNAL_SERVER_ERROR} end. get_title(Lang, <<"announce">>) -> translate:translate(Lang, <<"Announcements">>); get_title(Lang, ?NS_ADMIN_ANNOUNCE_ALL) -> translate:translate(Lang, <<"Send announcement to all users">>); get_title(Lang, ?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS) -> translate:translate(Lang, <<"Send announcement to all users on all hosts">>); get_title(Lang, ?NS_ADMIN_ANNOUNCE) -> translate:translate(Lang, <<"Send announcement to all online users">>); get_title(Lang, ?NS_ADMIN_ANNOUNCE_ALLHOSTS) -> translate:translate(Lang, <<"Send announcement to all online users on all hosts">>); get_title(Lang, ?NS_ADMIN_SET_MOTD) -> translate:translate(Lang, <<"Set message of the day and send to online users">>); get_title(Lang, ?NS_ADMIN_SET_MOTD_ALLHOSTS) -> translate:translate(Lang, <<"Set message of the day on all hosts and send to online users">>); get_title(Lang, ?NS_ADMIN_EDIT_MOTD) -> translate:translate(Lang, <<"Update message of the day (don't send)">>); get_title(Lang, ?NS_ADMIN_EDIT_MOTD_ALLHOSTS) -> translate:translate(Lang, <<"Update message of the day on all hosts (don't send)">>); get_title(Lang, ?NS_ADMIN_DELETE_MOTD) -> translate:translate(Lang, <<"Delete message of the day">>); get_title(Lang, ?NS_ADMIN_DELETE_MOTD_ALLHOSTS) -> translate:translate(Lang, <<"Delete message of the day on all hosts">>). %%------------------------------------------------------------------------- announce_all(From, To, Packet) -> Host = To#jid.lserver, Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> Local = jid:make(<<>>, To#jid.server, <<>>), lists:foreach( fun({User, Server}) -> Dest = jid:make(User, Server, <<>>), ejabberd_router:route(Local, Dest, Packet) end, ejabberd_auth:get_vh_registered_users(Host)) end. announce_all_hosts_all(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> Local = jid:make(<<>>, To#jid.server, <<>>), lists:foreach( fun({User, Server}) -> Dest = jid:make(User, Server, <<>>), ejabberd_router:route(Local, Dest, Packet) end, ejabberd_auth:dirty_get_registered_users()) end. announce_online(From, To, Packet) -> Host = To#jid.lserver, Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> announce_online1(ejabberd_sm:get_vh_session_list(Host), To#jid.server, Packet) end. announce_all_hosts_online(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> announce_online1(ejabberd_sm:dirty_get_sessions_list(), To#jid.server, Packet) end. announce_online1(Sessions, Server, Packet) -> Local = jid:make(<<>>, Server, <<>>), lists:foreach( fun({U, S, R}) -> Dest = jid:make(U, S, R), ejabberd_router:route(Local, Dest, Packet) end, Sessions). announce_motd(From, To, Packet) -> Host = To#jid.lserver, Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> announce_motd(Host, Packet) end. announce_all_hosts_motd(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> Hosts = ?MYHOSTS, [announce_motd(Host, Packet) || Host <- Hosts] end. announce_motd(Host, Packet) -> LServer = jid:nameprep(Host), announce_motd_update(LServer, Packet), Sessions = ejabberd_sm:get_vh_session_list(LServer), announce_online1(Sessions, LServer, Packet), case gen_mod:db_type(LServer, ?MODULE) of mnesia -> F = fun() -> lists:foreach( fun({U, S, _R}) -> mnesia:write(#motd_users{us = {U, S}}) end, Sessions) end, mnesia:transaction(F); riak -> try lists:foreach( fun({U, S, _R}) -> ok = ejabberd_riak:put(#motd_users{us = {U, S}}, motd_users_schema(), [{'2i', [{<<"server">>, S}]}]) end, Sessions), {atomic, ok} catch _:{badmatch, Err} -> {atomic, Err} end; odbc -> F = fun() -> lists:foreach( fun({U, _S, _R}) -> Username = ejabberd_odbc:escape(U), odbc_queries:update_t( <<"motd">>, [<<"username">>, <<"xml">>], [Username, <<"">>], [<<"username='">>, Username, <<"'">>]) end, Sessions) end, ejabberd_odbc:sql_transaction(LServer, F) end. announce_motd_update(From, To, Packet) -> Host = To#jid.lserver, Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> announce_motd_update(Host, Packet) end. announce_all_hosts_motd_update(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> Hosts = ?MYHOSTS, [announce_motd_update(Host, Packet) || Host <- Hosts] end. announce_motd_update(LServer, Packet) -> announce_motd_delete(LServer), case gen_mod:db_type(LServer, ?MODULE) of mnesia -> F = fun() -> mnesia:write(#motd{server = LServer, packet = Packet}) end, mnesia:transaction(F); riak -> {atomic, ejabberd_riak:put(#motd{server = LServer, packet = Packet}, motd_schema())}; odbc -> XML = ejabberd_odbc:escape(xml:element_to_binary(Packet)), F = fun() -> odbc_queries:update_t( <<"motd">>, [<<"username">>, <<"xml">>], [<<"">>, XML], [<<"username=''">>]) end, ejabberd_odbc:sql_transaction(LServer, F) end. announce_motd_delete(From, To, Packet) -> Host = To#jid.lserver, Access = get_access(Host), case acl:match_rule(Host, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> announce_motd_delete(Host) end. announce_all_hosts_motd_delete(From, To, Packet) -> Access = get_access(global), case acl:match_rule(global, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> Hosts = ?MYHOSTS, [announce_motd_delete(Host) || Host <- Hosts] end. announce_motd_delete(LServer) -> case gen_mod:db_type(LServer, ?MODULE) of mnesia -> F = fun() -> mnesia:delete({motd, LServer}), mnesia:write_lock_table(motd_users), Users = mnesia:select( motd_users, [{#motd_users{us = '$1', _ = '_'}, [{'==', {element, 2, '$1'}, LServer}], ['$1']}]), lists:foreach(fun(US) -> mnesia:delete({motd_users, US}) end, Users) end, mnesia:transaction(F); riak -> try ok = ejabberd_riak:delete(motd, LServer), ok = ejabberd_riak:delete_by_index(motd_users, <<"server">>, LServer), {atomic, ok} catch _:{badmatch, Err} -> {atomic, Err} end; odbc -> F = fun() -> ejabberd_odbc:sql_query_t([<<"delete from motd;">>]) end, ejabberd_odbc:sql_transaction(LServer, F) end. send_motd(JID) -> send_motd(JID, gen_mod:db_type(JID#jid.lserver, ?MODULE)). send_motd(#jid{luser = LUser, lserver = LServer} = JID, mnesia) -> case catch mnesia:dirty_read({motd, LServer}) of [#motd{packet = Packet}] -> US = {LUser, LServer}, case catch mnesia:dirty_read({motd_users, US}) of [#motd_users{}] -> ok; _ -> Local = jid:make(<<>>, LServer, <<>>), ejabberd_router:route(Local, JID, Packet), F = fun() -> mnesia:write(#motd_users{us = US}) end, mnesia:transaction(F) end; _ -> ok end; send_motd(#jid{luser = LUser, lserver = LServer} = JID, riak) -> case catch ejabberd_riak:get(motd, motd_schema(), LServer) of {ok, #motd{packet = Packet}} -> US = {LUser, LServer}, case ejabberd_riak:get(motd_users, motd_users_schema(), US) of {ok, #motd_users{}} -> ok; _ -> Local = jid:make(<<>>, LServer, <<>>), ejabberd_router:route(Local, JID, Packet), {atomic, ejabberd_riak:put( #motd_users{us = US}, motd_users_schema(), [{'2i', [{<<"server">>, LServer}]}])} end; _ -> ok end; 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 {error, _} -> ok; Packet -> Username = ejabberd_odbc:escape(LUser), case catch ejabberd_odbc:sql_query( LServer, [<<"select username from motd " "where username='">>, Username, <<"';">>]) of {selected, [<<"username">>], []} -> Local = jid:make(<<"">>, LServer, <<"">>), ejabberd_router:route(Local, JID, Packet), F = fun() -> odbc_queries:update_t( <<"motd">>, [<<"username">>, <<"xml">>], [Username, <<"">>], [<<"username='">>, Username, <<"'">>]) end, ejabberd_odbc:sql_transaction(LServer, F); _ -> ok end end; _ -> ok end; send_motd(_, odbc) -> ok. 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">>)}; error -> {<<>>, <<>>} end. get_stored_motd_packet(LServer, mnesia) -> case catch mnesia:dirty_read({motd, LServer}) of [#motd{packet = Packet}] -> {ok, Packet}; _ -> error end; get_stored_motd_packet(LServer, riak) -> case ejabberd_riak:get(motd, motd_schema(), LServer) of {ok, #motd{packet = Packet}} -> {ok, Packet}; _ -> error end; 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 {error, _} -> error; Packet -> {ok, Packet} end; _ -> error end. %% This function is similar to others, but doesn't perform any ACL verification send_announcement_to_all(Host, SubjectS, BodyS) -> SubjectEls = if SubjectS /= <<>> -> [#xmlel{name = <<"subject">>, children = [{xmlcdata, SubjectS}]}]; true -> [] end, BodyEls = if BodyS /= <<>> -> [#xmlel{name = <<"body">>, children = [{xmlcdata, BodyS}]}]; true -> [] end, Packet = #xmlel{ name = <<"message">>, attrs = [{<<"type">>, <<"headline">>}], children = SubjectEls ++ BodyEls }, Sessions = ejabberd_sm:dirty_get_sessions_list(), Local = jid:make(<<>>, Host, <<>>), lists:foreach( fun({U, S, R}) -> Dest = jid:make(U, S, R), ejabberd_router:route(Local, Dest, Packet) end, Sessions). -spec get_access(global | binary()) -> atom(). get_access(Host) -> gen_mod:get_module_opt(Host, ?MODULE, access, fun(A) when is_atom(A) -> A end, none). %%------------------------------------------------------------------------- update_tables() -> update_motd_table(), update_motd_users_table(). update_motd_table() -> Fields = record_info(fields, motd), case mnesia:table_info(motd, attributes) of Fields -> ejabberd_config:convert_table_to_binary( motd, Fields, set, fun(#motd{server = S}) -> S end, fun(#motd{server = S, packet = P} = R) -> NewS = iolist_to_binary(S), NewP = xml:to_xmlel(P), R#motd{server = NewS, packet = NewP} end); _ -> ?INFO_MSG("Recreating motd table", []), mnesia:transform_table(motd, ignore, Fields) end. update_motd_users_table() -> Fields = record_info(fields, motd_users), case mnesia:table_info(motd_users, attributes) of Fields -> ejabberd_config:convert_table_to_binary( motd_users, Fields, set, fun(#motd_users{us = {U, _}}) -> U end, fun(#motd_users{us = {U, S}} = R) -> NewUS = {iolist_to_binary(U), iolist_to_binary(S)}, R#motd_users{us = NewUS} end); _ -> ?INFO_MSG("Recreating motd_users table", []), mnesia:transform_table(motd_users, ignore, Fields) end. motd_schema() -> {record_info(fields, motd), #motd{}}. motd_users_schema() -> {record_info(fields, motd_users), #motd_users{}}. export(_Server) -> [{motd, fun(Host, #motd{server = LServer, packet = El}) when LServer == Host -> [[<<"delete from motd where username='';">>], [<<"insert into motd(username, xml) values ('', '">>, ejabberd_odbc:escape(xml:element_to_binary(El)), <<"');">>]]; (_Host, _R) -> [] end}, {motd_users, fun(Host, #motd_users{us = {LUser, LServer}}) when LServer == Host, LUser /= <<"">> -> Username = ejabberd_odbc:escape(LUser), [[<<"delete from motd where username='">>, Username, <<"';">>], [<<"insert into motd(username, xml) values ('">>, Username, <<"', '');">>]]; (_Host, _R) -> [] end}]. import(LServer) -> [{<<"select xml from motd where username='';">>, fun([XML]) -> El = xml_stream:parse_element(XML), #motd{server = LServer, packet = El} end}, {<<"select username from motd where xml='';">>, fun([LUser]) -> #motd_users{us = {LUser, LServer}} end}]. import(_LServer, mnesia, #motd{} = Motd) -> mnesia:dirty_write(Motd); import(_LServer, mnesia, #motd_users{} = Users) -> mnesia:dirty_write(Users); import(_LServer, riak, #motd{} = Motd) -> ejabberd_riak:put(Motd, motd_schema()); import(_LServer, riak, #motd_users{us = {_, S}} = Users) -> ejabberd_riak:put(Users, motd_users_schema(), [{'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]. ejabberd-16.01/src/ejabberd_s2s_out.erl0000644000232200023220000013334212645157216020353 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_s2s_out.erl %%% Author : Alexey Shchepin %%% Purpose : Manage outgoing server-to-server connections %%% Created : 6 Dec 2002 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_s2s_out). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(p1_fsm). %% External exports -export([start/3, start_link/3, start_connection/1, terminate_if_waiting_delay/2, stop_connection/1, transform_options/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"). -include("jlib.hrl"). -record(state, {socket :: ejabberd_socket:socket_state(), streamid = <<"">> :: binary(), remote_streamid = <<"">> :: binary(), use_v10 = true :: boolean(), tls = false :: boolean(), tls_required = false :: boolean(), tls_certverify = false :: boolean(), tls_enabled = false :: boolean(), tls_options = [connect] :: list(), authenticated = false :: boolean(), db_enabled = true :: boolean(), try_auth = true :: boolean(), myname = <<"">> :: binary(), server = <<"">> :: binary(), queue = queue:new() :: ?TQUEUE, delay_to_retry = undefined_delay :: undefined_delay | non_neg_integer(), new = false :: boolean(), verify = false :: false | {pid(), binary(), binary()}, bridge :: {atom(), atom()}, timer = make_ref() :: reference()}). %%-define(DBGFSM, true). -ifdef(DBGFSM). -define(FSMOPTS, [{debug, [trace]}]). -else. -define(FSMOPTS, []). -endif. -define(FSMTIMEOUT, 30000). %% We do not block on send anymore. -define(TCP_SEND_TIMEOUT, 15000). %% Maximum delay to wait before retrying to connect after a failed attempt. %% Specified in miliseconds. Default value is 5 minutes. -define(MAX_RETRY_DELAY, 300000). -define(STREAM_HEADER, <<"">>). -define(STREAM_TRAILER, <<"">>). -define(INVALID_NAMESPACE_ERR, xml:element_to_binary(?SERR_INVALID_NAMESPACE)). -define(HOST_UNKNOWN_ERR, xml:element_to_binary(?SERR_HOST_UNKNOWN)). -define(INVALID_XML_ERR, xml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). -define(SOCKET_DEFAULT_RESULT, {error, badarg}). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start(From, Host, Type) -> supervisor:start_child(ejabberd_s2s_out_sup, [From, Host, Type]). start_link(From, Host, Type) -> p1_fsm:start_link(ejabberd_s2s_out, [From, Host, Type], fsm_limit_opts() ++ (?FSMOPTS)). start_connection(Pid) -> p1_fsm:send_event(Pid, init). stop_connection(Pid) -> p1_fsm:send_event(Pid, closed). %%%---------------------------------------------------------------------- %%% Callback functions from p1_fsm %%%---------------------------------------------------------------------- init([From, Server, Type]) -> process_flag(trap_exit, true), ?DEBUG("started: ~p", [{From, Server, Type}]), {TLS, TLSRequired, TLSCertverify} = case ejabberd_config:get_option( s2s_use_starttls, fun(true) -> true; (false) -> false; (optional) -> optional; (required) -> required; (required_trusted) -> required_trusted end) of UseTls when (UseTls == undefined) or (UseTls == false) -> {false, false, false}; UseTls when (UseTls == true) or (UseTls == optional) -> {true, false, false}; required -> {true, true, false}; required_trusted -> {true, true, true} end, UseV10 = TLS, TLSOpts1 = case ejabberd_config:get_option( s2s_certfile, fun iolist_to_binary/1) of undefined -> [connect]; CertFile -> [{certfile, CertFile}, connect] end, TLSOpts2 = case ejabberd_config:get_option( s2s_ciphers, fun iolist_to_binary/1) of undefined -> TLSOpts1; Ciphers -> [{ciphers, Ciphers} | TLSOpts1] end, TLSOpts3 = case ejabberd_config:get_option( 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) of 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 | TLSOpts4]; true -> TLSOpts4 end, {New, Verify} = case Type of new -> {true, false}; {verify, Pid, Key, SID} -> start_connection(self()), {false, {Pid, Key, SID}} end, Timer = erlang:start_timer(?S2STIMEOUT, self(), []), {ok, open_socket, #state{use_v10 = UseV10, tls = TLS, tls_required = TLSRequired, tls_certverify = TLSCertverify, tls_options = TLSOpts, queue = queue:new(), myname = From, server = Server, new = New, verify = Verify, timer = Timer}}. open_socket(init, StateData) -> log_s2s_out(StateData#state.new, StateData#state.myname, StateData#state.server, StateData#state.tls), ?DEBUG("open_socket: ~p", [{StateData#state.myname, StateData#state.server, StateData#state.new, StateData#state.verify}]), AddrList = case ejabberd_idna:domain_utf8_to_ascii(StateData#state.server) of false -> []; ASCIIAddr -> get_addr_port(ASCIIAddr) end, case lists:foldl(fun ({Addr, Port}, Acc) -> case Acc of {ok, Socket} -> {ok, Socket}; _ -> open_socket1(Addr, Port) end end, ?SOCKET_DEFAULT_RESULT, AddrList) of {ok, Socket} -> Version = if StateData#state.use_v10 -> <<" version='1.0'">>; true -> <<"">> end, NewStateData = StateData#state{socket = Socket, tls_enabled = false, streamid = new_id()}, send_text(NewStateData, io_lib:format(?STREAM_HEADER, [StateData#state.myname, StateData#state.server, Version])), {next_state, wait_for_stream, NewStateData, ?FSMTIMEOUT}; {error, _Reason} -> ?INFO_MSG("s2s connection: ~s -> ~s (remote server " "not found)", [StateData#state.myname, StateData#state.server]), case ejabberd_hooks:run_fold(find_s2s_bridge, undefined, [StateData#state.myname, StateData#state.server]) of {Mod, Fun, Type} -> ?INFO_MSG("found a bridge to ~s for: ~s -> ~s", [Type, StateData#state.myname, StateData#state.server]), NewStateData = StateData#state{bridge = {Mod, Fun}}, {next_state, relay_to_bridge, NewStateData}; _ -> wait_before_reconnect(StateData) end end; open_socket(closed, StateData) -> ?INFO_MSG("s2s connection: ~s -> ~s (stopped in " "open socket)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; open_socket(timeout, StateData) -> ?INFO_MSG("s2s connection: ~s -> ~s (timeout in " "open socket)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; open_socket(_, StateData) -> {next_state, open_socket, StateData}. open_socket1({_, _, _, _} = Addr, Port) -> open_socket2(inet, Addr, Port); %% IPv6 open_socket1({_, _, _, _, _, _, _, _} = Addr, Port) -> open_socket2(inet6, Addr, Port); %% Hostname open_socket1(Host, Port) -> lists:foldl(fun (_Family, {ok, _Socket} = R) -> R; (Family, _) -> Addrs = get_addrs(Host, Family), lists:foldl(fun (_Addr, {ok, _Socket} = R) -> R; (Addr, _) -> open_socket1(Addr, Port) end, ?SOCKET_DEFAULT_RESULT, Addrs) end, ?SOCKET_DEFAULT_RESULT, outgoing_s2s_families()). open_socket2(Type, Addr, Port) -> ?DEBUG("s2s_out: connecting to ~p:~p~n", [Addr, Port]), Timeout = outgoing_s2s_timeout(), case catch ejabberd_socket:connect(Addr, Port, [binary, {packet, 0}, {send_timeout, ?TCP_SEND_TIMEOUT}, {send_timeout_close, true}, {active, false}, Type], Timeout) of {ok, _Socket} = R -> R; {error, Reason} = R -> ?DEBUG("s2s_out: connect return ~p~n", [Reason]), R; {'EXIT', Reason} -> ?DEBUG("s2s_out: connect crashed ~p~n", [Reason]), {error, Reason} end. %%---------------------------------------------------------------------- wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> {CertCheckRes, CertCheckMsg, StateData0} = if StateData#state.tls_certverify, StateData#state.tls_enabled -> {Res, Msg} = ejabberd_s2s:check_peer_certificate(ejabberd_socket, StateData#state.socket, StateData#state.server), ?DEBUG("Certificate verification result for ~s: ~s", [StateData#state.server, Msg]), {Res, Msg, StateData#state{tls_certverify = false}}; 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">>} of _ when CertCheckRes == error -> send_text(NewStateData, <<(xml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>, CertCheckMsg)))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (~s)", [NewStateData#state.myname, NewStateData#state.server, CertCheckMsg]), {stop, normal, NewStateData}; {<<"jabber:server">>, <<"jabber:server:dialback">>, false} -> send_db_request(NewStateData); {<<"jabber:server">>, <<"jabber:server:dialback">>, true} when NewStateData#state.use_v10 -> {next_state, wait_for_features, NewStateData, ?FSMTIMEOUT}; %% Clause added to handle Tigase's workaround for an old ejabberd bug: {<<"jabber:server">>, <<"jabber:server:dialback">>, true} when not NewStateData#state.use_v10 -> send_db_request(NewStateData); {<<"jabber:server">>, <<"">>, true} when NewStateData#state.use_v10 -> {next_state, wait_for_features, NewStateData#state{db_enabled = false}, ?FSMTIMEOUT}; {NSProvided, DB, _} -> send_text(NewStateData, ?INVALID_NAMESPACE_ERR), ?INFO_MSG("Closing s2s connection: ~s -> ~s (invalid " "namespace).~nNamespace provided: ~p~nNamespac" "e expected: \"jabber:server\"~nxmlns:db " "provided: ~p~nAll attributes: ~p", [NewStateData#state.myname, NewStateData#state.server, NSProvided, DB, Attrs]), {stop, normal, NewStateData} end; wait_for_stream({xmlstreamerror, _}, StateData) -> send_text(StateData, <<(?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (invalid " "xml)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; wait_for_stream({xmlstreamend, _Name}, StateData) -> ?INFO_MSG("Closing s2s connection: ~s -> ~s (xmlstreamend)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; wait_for_stream(timeout, StateData) -> ?INFO_MSG("Closing s2s connection: ~s -> ~s (timeout " "in wait_for_stream)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; wait_for_stream(closed, StateData) -> ?INFO_MSG("Closing s2s connection: ~s -> ~s (close " "in wait_for_stream)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}. wait_for_validation({xmlstreamelement, El}, StateData) -> case is_verify_res(El) of {result, To, From, Id, Type} -> ?DEBUG("recv result: ~p", [{From, To, Id, Type}]), case {Type, StateData#state.tls_enabled, StateData#state.tls_required} of {<<"valid">>, Enabled, Required} when (Enabled == true) or (Required == false) -> send_queue(StateData, StateData#state.queue), ?INFO_MSG("Connection established: ~s -> ~s with " "TLS=~p", [StateData#state.myname, StateData#state.server, StateData#state.tls_enabled]), ejabberd_hooks:run(s2s_connect_hook, [StateData#state.myname, StateData#state.server]), {next_state, stream_established, StateData#state{queue = queue:new()}}; {<<"valid">>, Enabled, Required} when (Enabled == false) and (Required == true) -> ?INFO_MSG("Closing s2s connection: ~s -> ~s (TLS " "is required but unavailable)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; _ -> ?INFO_MSG("Closing s2s connection: ~s -> ~s (invalid " "dialback key)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData} end; {verify, To, From, Id, Type} -> ?DEBUG("recv verify: ~p", [{From, To, Id, Type}]), case StateData#state.verify of false -> NextState = wait_for_validation, {next_state, NextState, StateData, get_timeout_interval(NextState)}; {Pid, _Key, _SID} -> case Type of <<"valid">> -> p1_fsm:send_event(Pid, {valid, StateData#state.server, StateData#state.myname}); _ -> p1_fsm:send_event(Pid, {invalid, StateData#state.server, StateData#state.myname}) end, if StateData#state.verify == false -> {stop, normal, StateData}; true -> NextState = wait_for_validation, {next_state, NextState, StateData, get_timeout_interval(NextState)} end end; _ -> {next_state, wait_for_validation, StateData, (?FSMTIMEOUT) * 3} end; wait_for_validation({xmlstreamend, _Name}, StateData) -> ?INFO_MSG("wait for validation: ~s -> ~s (xmlstreamend)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; wait_for_validation({xmlstreamerror, _}, StateData) -> ?INFO_MSG("wait for validation: ~s -> ~s (xmlstreamerror)", [StateData#state.myname, StateData#state.server]), send_text(StateData, <<(?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), {stop, normal, StateData}; wait_for_validation(timeout, #state{verify = {VPid, VKey, SID}} = StateData) when is_pid(VPid) and is_binary(VKey) and is_binary(SID) -> ?DEBUG("wait_for_validation: ~s -> ~s (timeout " "in verify connection)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; wait_for_validation(timeout, StateData) -> ?INFO_MSG("wait_for_validation: ~s -> ~s (connect " "timeout)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; wait_for_validation(closed, StateData) -> ?INFO_MSG("wait for validation: ~s -> ~s (closed)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}. wait_for_features({xmlstreamelement, El}, StateData) -> case El of #xmlel{name = <<"stream:features">>, children = Els} -> {SASLEXT, StartTLS, StartTLSRequired} = lists:foldl(fun (#xmlel{name = <<"mechanisms">>, attrs = Attrs1, children = Els1} = _El1, {_SEXT, STLS, STLSReq} = Acc) -> case xml:get_attr_s(<<"xmlns">>, Attrs1) of ?NS_SASL -> NewSEXT = lists:any(fun (#xmlel{name = <<"mechanism">>, children = Els2}) -> case xml:get_cdata(Els2) of <<"EXTERNAL">> -> true; _ -> false end; (_) -> false end, Els1), {NewSEXT, STLS, STLSReq}; _ -> Acc end; (#xmlel{name = <<"starttls">>, attrs = Attrs1} = El1, {SEXT, _STLS, _STLSReq} = Acc) -> case xml:get_attr_s(<<"xmlns">>, Attrs1) of ?NS_TLS -> Req = case xml:get_subtag(El1, <<"required">>) of #xmlel{} -> true; false -> false end, {SEXT, true, Req}; _ -> Acc end; (_, Acc) -> Acc end, {false, false, false}, Els), if not SASLEXT and not StartTLS and StateData#state.authenticated -> send_queue(StateData, StateData#state.queue), ?INFO_MSG("Connection established: ~s -> ~s with " "SASL EXTERNAL and TLS=~p", [StateData#state.myname, StateData#state.server, StateData#state.tls_enabled]), ejabberd_hooks:run(s2s_connect_hook, [StateData#state.myname, StateData#state.server]), {next_state, stream_established, StateData#state{queue = queue:new()}}; SASLEXT and StateData#state.try_auth and (StateData#state.new /= false) and (StateData#state.tls_enabled or not StateData#state.tls_required) -> send_element(StateData, #xmlel{name = <<"auth">>, attrs = [{<<"xmlns">>, ?NS_SASL}, {<<"mechanism">>, <<"EXTERNAL">>}], children = [{xmlcdata, jlib:encode_base64(StateData#state.myname)}]}), {next_state, wait_for_auth_result, StateData#state{try_auth = false}, ?FSMTIMEOUT}; StartTLS and StateData#state.tls and not StateData#state.tls_enabled -> send_element(StateData, #xmlel{name = <<"starttls">>, attrs = [{<<"xmlns">>, ?NS_TLS}], children = []}), {next_state, wait_for_starttls_proceed, StateData, ?FSMTIMEOUT}; StartTLSRequired and not StateData#state.tls -> ?DEBUG("restarted: ~p", [{StateData#state.myname, StateData#state.server}]), ejabberd_socket:close(StateData#state.socket), {next_state, reopen_socket, StateData#state{socket = undefined, use_v10 = false}, ?FSMTIMEOUT}; StateData#state.db_enabled -> send_db_request(StateData); true -> ?DEBUG("restarted: ~p", [{StateData#state.myname, StateData#state.server}]), ejabberd_socket:close(StateData#state.socket), {next_state, reopen_socket, StateData#state{socket = undefined, use_v10 = false}, ?FSMTIMEOUT} end; _ -> send_text(StateData, <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData} end; wait_for_features({xmlstreamend, _Name}, StateData) -> ?INFO_MSG("wait_for_features: xmlstreamend", []), {stop, normal, StateData}; wait_for_features({xmlstreamerror, _}, StateData) -> send_text(StateData, <<(?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("wait for features: xmlstreamerror", []), {stop, normal, StateData}; wait_for_features(timeout, StateData) -> ?INFO_MSG("wait for features: timeout", []), {stop, normal, StateData}; wait_for_features(closed, StateData) -> ?INFO_MSG("wait for features: closed", []), {stop, normal, StateData}. wait_for_auth_result({xmlstreamelement, El}, StateData) -> case El of #xmlel{name = <<"success">>, attrs = Attrs} -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_SASL -> ?DEBUG("auth: ~p", [{StateData#state.myname, StateData#state.server}]), ejabberd_socket:reset_stream(StateData#state.socket), send_text(StateData, io_lib:format(?STREAM_HEADER, [StateData#state.myname, StateData#state.server, <<" version='1.0'">>])), {next_state, wait_for_stream, StateData#state{streamid = new_id(), authenticated = true}, ?FSMTIMEOUT}; _ -> send_text(StateData, <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData} end; #xmlel{name = <<"failure">>, attrs = Attrs} -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_SASL -> ?DEBUG("restarted: ~p", [{StateData#state.myname, StateData#state.server}]), ejabberd_socket:close(StateData#state.socket), {next_state, reopen_socket, StateData#state{socket = undefined}, ?FSMTIMEOUT}; _ -> send_text(StateData, <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData} end; _ -> send_text(StateData, <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData} end; wait_for_auth_result({xmlstreamend, _Name}, StateData) -> ?INFO_MSG("wait for auth result: xmlstreamend", []), {stop, normal, StateData}; wait_for_auth_result({xmlstreamerror, _}, StateData) -> send_text(StateData, <<(?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("wait for auth result: xmlstreamerror", []), {stop, normal, StateData}; wait_for_auth_result(timeout, StateData) -> ?INFO_MSG("wait for auth result: timeout", []), {stop, normal, StateData}; wait_for_auth_result(closed, StateData) -> ?INFO_MSG("wait for auth result: closed", []), {stop, normal, StateData}. wait_for_starttls_proceed({xmlstreamelement, El}, StateData) -> case El of #xmlel{name = <<"proceed">>, attrs = Attrs} -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_TLS -> ?DEBUG("starttls: ~p", [{StateData#state.myname, StateData#state.server}]), Socket = StateData#state.socket, TLSOpts = case ejabberd_config:get_option( {domain_certfile, StateData#state.myname}, fun iolist_to_binary/1) of undefined -> StateData#state.tls_options; CertFile -> [{certfile, CertFile} | lists:keydelete(certfile, 1, StateData#state.tls_options)] end, TLSSocket = ejabberd_socket:starttls(Socket, TLSOpts), NewStateData = StateData#state{socket = TLSSocket, streamid = new_id(), tls_enabled = true, tls_options = TLSOpts}, send_text(NewStateData, io_lib:format(?STREAM_HEADER, [NewStateData#state.myname, NewStateData#state.server, <<" version='1.0'">>])), {next_state, wait_for_stream, NewStateData, ?FSMTIMEOUT}; _ -> send_text(StateData, <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData} end; _ -> ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData} end; wait_for_starttls_proceed({xmlstreamend, _Name}, StateData) -> ?INFO_MSG("wait for starttls proceed: xmlstreamend", []), {stop, normal, StateData}; wait_for_starttls_proceed({xmlstreamerror, _}, StateData) -> send_text(StateData, <<(?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("wait for starttls proceed: xmlstreamerror", []), {stop, normal, StateData}; wait_for_starttls_proceed(timeout, StateData) -> ?INFO_MSG("wait for starttls proceed: timeout", []), {stop, normal, StateData}; wait_for_starttls_proceed(closed, StateData) -> ?INFO_MSG("wait for starttls proceed: closed", []), {stop, normal, StateData}. reopen_socket({xmlstreamelement, _El}, StateData) -> {next_state, reopen_socket, StateData, ?FSMTIMEOUT}; reopen_socket({xmlstreamend, _Name}, StateData) -> {next_state, reopen_socket, StateData, ?FSMTIMEOUT}; reopen_socket({xmlstreamerror, _}, StateData) -> {next_state, reopen_socket, StateData, ?FSMTIMEOUT}; reopen_socket(timeout, StateData) -> ?INFO_MSG("reopen socket: timeout", []), {stop, normal, StateData}; reopen_socket(closed, StateData) -> p1_fsm:send_event(self(), init), {next_state, open_socket, StateData, ?FSMTIMEOUT}. %% This state is use to avoid reconnecting to often to bad sockets wait_before_retry(_Event, StateData) -> {next_state, wait_before_retry, StateData, ?FSMTIMEOUT}. relay_to_bridge(stop, StateData) -> wait_before_reconnect(StateData); relay_to_bridge(closed, StateData) -> ?INFO_MSG("relay to bridge: ~s -> ~s (closed)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; relay_to_bridge(_Event, StateData) -> {next_state, relay_to_bridge, StateData}. stream_established({xmlstreamelement, El}, StateData) -> ?DEBUG("s2S stream established", []), case is_verify_res(El) of {verify, VTo, VFrom, VId, VType} -> ?DEBUG("recv verify: ~p", [{VFrom, VTo, VId, VType}]), case StateData#state.verify of {VPid, _VKey, _SID} -> case VType of <<"valid">> -> p1_fsm:send_event(VPid, {valid, StateData#state.server, StateData#state.myname}); _ -> p1_fsm:send_event(VPid, {invalid, StateData#state.server, StateData#state.myname}) end; _ -> ok end; _ -> ok end, {next_state, stream_established, StateData}; stream_established({xmlstreamend, _Name}, StateData) -> ?INFO_MSG("Connection closed in stream established: " "~s -> ~s (xmlstreamend)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; stream_established({xmlstreamerror, _}, StateData) -> send_text(StateData, <<(?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("stream established: ~s -> ~s (xmlstreamerror)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; stream_established(timeout, StateData) -> ?INFO_MSG("stream established: ~s -> ~s (timeout)", [StateData#state.myname, StateData#state.server]), {stop, normal, StateData}; stream_established(closed, StateData) -> ?INFO_MSG("stream established: ~s -> ~s (closed)", [StateData#state.myname, StateData#state.server]), {stop, normal, 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}. handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData, get_timeout_interval(StateName)}. handle_sync_event(get_state_infos, _From, StateName, StateData) -> {Addr, Port} = try ejabberd_socket:peername(StateData#state.socket) of {ok, {A, P}} -> {A, P}; {error, _} -> {unknown, unknown} catch _:_ -> {unknown, unknown} end, Infos = [{direction, out}, {statename, StateName}, {addr, Addr}, {port, Port}, {streamid, StateData#state.streamid}, {use_v10, StateData#state.use_v10}, {tls, StateData#state.tls}, {tls_required, StateData#state.tls_required}, {tls_enabled, StateData#state.tls_enabled}, {tls_options, StateData#state.tls_options}, {authenticated, StateData#state.authenticated}, {db_enabled, StateData#state.db_enabled}, {try_auth, StateData#state.try_auth}, {myname, StateData#state.myname}, {server, StateData#state.server}, {delay_to_retry, StateData#state.delay_to_retry}, {verify, StateData#state.verify}], Reply = {state_infos, Infos}, {reply, Reply, 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(_Event, _From, StateName, StateData) -> Reply = ok, {reply, Reply, StateName, StateData, get_timeout_interval(StateName)}. code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. handle_info({send_text, Text}, StateName, StateData) -> send_text(StateData, Text), cancel_timer(StateData#state.timer), Timer = erlang:start_timer(?S2STIMEOUT, self(), []), {next_state, StateName, StateData#state{timer = Timer}, get_timeout_interval(StateName)}; handle_info({send_element, El}, StateName, StateData) -> case StateName of stream_established -> cancel_timer(StateData#state.timer), Timer = erlang:start_timer(?S2STIMEOUT, self(), []), send_element(StateData, El), {next_state, StateName, StateData#state{timer = Timer}}; %% In this state we bounce all message: We are waiting before %% trying to reconnect wait_before_retry -> bounce_element(El, ?ERR_REMOTE_SERVER_NOT_FOUND), {next_state, StateName, StateData}; relay_to_bridge -> {Mod, Fun} = StateData#state.bridge, ?DEBUG("relaying stanza via ~p:~p/1", [Mod, Fun]), case catch Mod:Fun(El) of {'EXIT', Reason} -> ?ERROR_MSG("Error while relaying to bridge: ~p", [Reason]), bounce_element(El, ?ERR_INTERNAL_SERVER_ERROR), wait_before_reconnect(StateData); _ -> {next_state, StateName, StateData} end; _ -> Q = queue:in(El, StateData#state.queue), {next_state, StateName, StateData#state{queue = Q}, get_timeout_interval(StateName)} end; handle_info({timeout, Timer, _}, wait_before_retry, #state{timer = Timer} = StateData) -> ?INFO_MSG("Reconnect delay expired: Will now retry " "to connect to ~s when needed.", [StateData#state.server]), {stop, normal, StateData}; handle_info({timeout, Timer, _}, _StateName, #state{timer = Timer} = StateData) -> ?INFO_MSG("Closing connection with ~s: timeout", [StateData#state.server]), {stop, normal, StateData}; handle_info(terminate_if_waiting_before_retry, wait_before_retry, StateData) -> {stop, normal, StateData}; handle_info(terminate_if_waiting_before_retry, StateName, StateData) -> {next_state, StateName, StateData, get_timeout_interval(StateName)}; handle_info(_, StateName, StateData) -> {next_state, StateName, StateData, get_timeout_interval(StateName)}. terminate(Reason, StateName, StateData) -> ?DEBUG("terminated: ~p", [{Reason, StateName}]), case StateData#state.new of false -> ok; true -> ejabberd_s2s:remove_connection({StateData#state.myname, StateData#state.server}, self()) end, bounce_queue(StateData#state.queue, ?ERR_REMOTE_SERVER_NOT_FOUND), bounce_messages(?ERR_REMOTE_SERVER_NOT_FOUND), case StateData#state.socket of undefined -> ok; _Socket -> ejabberd_socket:close(StateData#state.socket) end, ok. print_state(State) -> State. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- send_text(StateData, Text) -> ejabberd_socket:send(StateData#state.socket, Text). send_element(StateData, El) -> send_text(StateData, xml:element_to_binary(El)). send_queue(StateData, Q) -> case queue:out(Q) of {{value, El}, Q1} -> send_element(StateData, El), send_queue(StateData, Q1); {empty, _Q1} -> ok end. %% Bounce a single message (xmlelement) bounce_element(El, Error) -> #xmlel{attrs = Attrs} = El, case xml: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">>, El)), To = jid:from_string(xml:get_tag_attr_s(<<"to">>, El)), ejabberd_router:route(To, From, Err) end. bounce_queue(Q, Error) -> case queue:out(Q) of {{value, El}, Q1} -> bounce_element(El, Error), bounce_queue(Q1, Error); {empty, _} -> ok end. new_id() -> randoms:get_string(). cancel_timer(Timer) -> erlang:cancel_timer(Timer), receive {timeout, Timer, _} -> ok after 0 -> ok end. bounce_messages(Error) -> receive {send_element, El} -> bounce_element(El, Error), bounce_messages(Error) after 0 -> ok end. send_db_request(StateData) -> Server = StateData#state.server, New = case StateData#state.new of false -> ejabberd_s2s:try_register({StateData#state.myname, Server}); true -> true end, NewStateData = StateData#state{new = New}, try case New of 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">>, StateData#state.myname}, {<<"to">>, Server}], children = [{xmlcdata, Key1}]}) end, case StateData#state.verify of false -> ok; {_Pid, Key2, SID} -> send_element(StateData, #xmlel{name = <<"db:verify">>, attrs = [{<<"from">>, StateData#state.myname}, {<<"to">>, StateData#state.server}, {<<"id">>, SID}], children = [{xmlcdata, Key2}]}) end, {next_state, wait_for_validation, NewStateData, (?FSMTIMEOUT) * 6} catch _:_ -> {stop, normal, NewStateData} end. 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)}; 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)}; is_verify_res(_) -> false. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% SRV support -include_lib("kernel/include/inet.hrl"). -spec get_addr_port(binary()) -> [{binary(), inet:port_number()}]. get_addr_port(Server) -> Res = srv_lookup(Server), case Res of {error, Reason} -> ?DEBUG("srv lookup of '~s' failed: ~p~n", [Server, Reason]), [{Server, outgoing_s2s_port()}]; {ok, HEnt} -> ?DEBUG("srv lookup of '~s': ~p~n", [Server, HEnt#hostent.h_addr_list]), AddrList = HEnt#hostent.h_addr_list, random:seed(p1_time_compat:timestamp()), case catch lists:map(fun ({Priority, Weight, Port, Host}) -> N = case Weight of 0 -> 0; _ -> (Weight + 1) * random:uniform() end, {Priority * 65536 - N, Host, Port} end, AddrList) of SortedList = [_ | _] -> List = lists:map(fun ({_, Host, Port}) -> {list_to_binary(Host), Port} end, lists:keysort(1, SortedList)), ?DEBUG("srv lookup of '~s': ~p~n", [Server, List]), List; _ -> [{Server, outgoing_s2s_port()}] end end. srv_lookup(Server) -> TimeoutMs = timer:seconds( ejabberd_config:get_option( s2s_dns_timeout, fun(I) when is_integer(I), I>=0 -> I end, 10)), Retries = ejabberd_config:get_option( s2s_dns_retries, fun(I) when is_integer(I), I>=0 -> I end, 2), srv_lookup(binary_to_list(Server), TimeoutMs, Retries). %% XXX - this behaviour is suboptimal in the case that the domain %% has a "_xmpp-server._tcp." but not a "_jabber._tcp." record and %% we don't get a DNS reply for the "_xmpp-server._tcp." lookup. In this %% case we'll give up when we get the "_jabber._tcp." nxdomain reply. srv_lookup(_Server, _Timeout, Retries) when Retries < 1 -> {error, timeout}; srv_lookup(Server, Timeout, Retries) -> case inet_res:getbyname("_xmpp-server._tcp." ++ Server, srv, Timeout) of {error, _Reason} -> case inet_res:getbyname("_jabber._tcp." ++ Server, srv, Timeout) of {error, timeout} -> ?ERROR_MSG("The DNS servers~n ~p~ntimed out on " "request for ~p IN SRV. You should check " "your DNS configuration.", [inet_db:res_option(nameserver), Server]), srv_lookup(Server, Timeout, Retries - 1); R -> R end; {ok, _HEnt} = R -> R end. test_get_addr_port(Server) -> lists:foldl(fun (_, Acc) -> [HostPort | _] = get_addr_port(Server), case lists:keysearch(HostPort, 1, Acc) of false -> [{HostPort, 1} | Acc]; {value, {_, Num}} -> lists:keyreplace(HostPort, 1, Acc, {HostPort, Num + 1}) end end, [], lists:seq(1, 100000)). get_addrs(Host, Family) -> Type = case Family of inet4 -> inet; ipv4 -> inet; inet6 -> inet6; ipv6 -> inet6 end, case inet:gethostbyname(binary_to_list(Host), Type) of {ok, #hostent{h_addr_list = Addrs}} -> ?DEBUG("~s of ~s resolved to: ~p~n", [Type, Host, Addrs]), Addrs; {error, Reason} -> ?DEBUG("~s lookup of '~s' failed: ~p~n", [Type, Host, Reason]), [] end. outgoing_s2s_port() -> ejabberd_config:get_option( outgoing_s2s_port, fun(I) when is_integer(I), I > 0, I =< 65536 -> I end, 5269). outgoing_s2s_families() -> ejabberd_config:get_option( outgoing_s2s_families, fun(Families) -> true = lists:all( fun(ipv4) -> true; (ipv6) -> true end, Families), Families end, [ipv4, ipv6]). outgoing_s2s_timeout() -> ejabberd_config:get_option( outgoing_s2s_timeout, fun(TimeOut) when is_integer(TimeOut), TimeOut > 0 -> TimeOut; (infinity) -> infinity end, 10000). transform_options(Opts) -> lists:foldl(fun transform_options/2, [], Opts). transform_options({outgoing_s2s_options, Families, Timeout}, Opts) -> ?WARNING_MSG("Option 'outgoing_s2s_options' is deprecated. " "The option is still supported " "but it is better to fix your config: " "use 'outgoing_s2s_timeout' and " "'outgoing_s2s_families' instead.", []), [{outgoing_s2s_families, Families}, {outgoing_s2s_timeout, Timeout} | Opts]; transform_options({s2s_dns_options, S2SDNSOpts}, AllOpts) -> ?WARNING_MSG("Option 's2s_dns_options' is deprecated. " "The option is still supported " "but it is better to fix your config: " "use 's2s_dns_timeout' and " "'s2s_dns_retries' instead", []), lists:foldr( fun({timeout, T}, AccOpts) -> [{s2s_dns_timeout, T}|AccOpts]; ({retries, R}, AccOpts) -> [{s2s_dns_retries, R}|AccOpts]; (_, AccOpts) -> AccOpts end, AllOpts, S2SDNSOpts); transform_options(Opt, Opts) -> [Opt|Opts]. %% Human readable S2S logging: Log only new outgoing connections as INFO %% Do not log dialback log_s2s_out(false, _, _, _) -> ok; %% Log new outgoing connections: log_s2s_out(_, Myname, Server, Tls) -> ?INFO_MSG("Trying to open s2s connection: ~s -> " "~s with TLS=~p", [Myname, Server, Tls]). %% Calculate timeout depending on which state we are in: %% Can return integer > 0 | infinity get_timeout_interval(StateName) -> case StateName of %% Validation implies dialback: Networking can take longer: wait_for_validation -> (?FSMTIMEOUT) * 6; %% When stream is established, we only rely on S2S Timeout timer: stream_established -> infinity; _ -> ?FSMTIMEOUT end. %% This function is intended to be called at the end of a state %% function that want to wait for a reconnect delay before stopping. wait_before_reconnect(StateData) -> bounce_queue(StateData#state.queue, ?ERR_REMOTE_SERVER_NOT_FOUND), bounce_messages(?ERR_REMOTE_SERVER_NOT_FOUND), cancel_timer(StateData#state.timer), Delay = case StateData#state.delay_to_retry of undefined_delay -> {_, _, 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(), []), {next_state, wait_before_retry, StateData#state{timer = Timer, delay_to_retry = Delay, queue = queue:new()}}. get_max_retry_delay() -> case ejabberd_config:get_option( s2s_max_retry_delay, fun(I) when is_integer(I), I > 0 -> I end) of undefined -> ?MAX_RETRY_DELAY; Seconds -> Seconds * 1000 end. %% Terminate s2s_out connections that are in state wait_before_retry terminate_if_waiting_delay(From, To) -> FromTo = {From, To}, Pids = ejabberd_s2s:get_connections_pids(FromTo), lists:foreach(fun (Pid) -> Pid ! terminate_if_waiting_before_retry end, Pids). fsm_limit_opts() -> case ejabberd_config:get_option( max_fsm_queue, fun(I) when is_integer(I), I > 0 -> I end) of 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_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) -> 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_dhfile, s2s_dns_retries, s2s_dns_timeout, s2s_max_retry_delay, s2s_protocol_options, s2s_tls_compression, s2s_use_starttls]. ejabberd-16.01/src/ejabberd_auth_anonymous.erl0000644000232200023220000002131212645157216022017 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_auth_anonymous.erl %%% Author : Mickael Remond %%% Purpose : Anonymous feature support in ejabberd %%% Created : 17 Feb 2006 by Mickael Remond %%% %%% %%% 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_anonymous). -behaviour(ejabberd_config). -author('mickael.remond@process-one.net'). -export([start/1, allow_anonymous/1, is_sasl_anonymous_enabled/1, is_login_anonymous_enabled/1, anonymous_user_exist/2, allow_multiple_connections/1, register_connection/3, unregister_connection/3 ]). -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_password/2, get_password/3, is_user_exists/2, remove_user/2, remove_user/3, store_type/0, plain_password_required/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). %% 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 = {p1_time_compat:timestamp(), self()} :: ejabberd_sm:sid()}). start(Host) -> %% TODO: Check cluster mode mnesia:create_table(anonymous, [{ram_copies, [node()]}, {type, bag}, {attributes, record_info(fields, anonymous)}]), %% The hooks are needed to add / remove users from the anonymous tables ejabberd_hooks:add(sm_register_connection_hook, Host, ?MODULE, register_connection, 100), ejabberd_hooks:add(sm_remove_connection_hook, Host, ?MODULE, unregister_connection, 100), ok. %% Return true if anonymous is allowed for host or false otherwise allow_anonymous(Host) -> lists:member(?MODULE, ejabberd_auth:auth_modules(Host)). %% Return true if anonymous mode is enabled and if anonymous protocol is SASL %% anonymous protocol can be: sasl_anon|login_anon|both is_sasl_anonymous_enabled(Host) -> case allow_anonymous(Host) of false -> false; true -> case anonymous_protocol(Host) of sasl_anon -> true; both -> true; _Other -> false end end. %% Return true if anonymous login is enabled on the server %% anonymous login can be use using standard authentication method (i.e. with %% clients that do not support anonymous login) is_login_anonymous_enabled(Host) -> case allow_anonymous(Host) of false -> false; true -> case anonymous_protocol(Host) of login_anon -> true; both -> true; _Other -> false end end. %% Return the anonymous protocol to use: sasl_anon|login_anon|both %% defaults to login_anon anonymous_protocol(Host) -> ejabberd_config:get_option( {anonymous_protocol, Host}, fun(sasl_anon) -> sasl_anon; (login_anon) -> login_anon; (both) -> both end, sasl_anon). %% Return true if multiple connections have been allowed in the config file %% defaults to false allow_multiple_connections(Host) -> ejabberd_config:get_option( {allow_multiple_connections, Host}, fun(V) when is_boolean(V) -> V end, false). %% Check if user exist in the anonymus database anonymous_user_exist(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), US = {LUser, LServer}, case catch mnesia:dirty_read({anonymous, US}) of [] -> false; [_H|_T] -> true end. %% Remove connection from Mnesia tables remove_connection(SID, LUser, LServer) -> US = {LUser, LServer}, F = fun () -> mnesia:delete_object({anonymous, US, SID}) end, mnesia:transaction(F). %% Register connection register_connection(SID, #jid{luser = LUser, lserver = LServer}, Info) -> AuthModule = proplists:get_value(auth_module, Info, undefined), case AuthModule == (?MODULE) of true -> ejabberd_hooks:run(register_user, LServer, [LUser, LServer]), US = {LUser, LServer}, mnesia:sync_dirty(fun () -> mnesia:write(#anonymous{us = US, sid = SID}) end); false -> ok end. %% Remove an anonymous user from the anonymous users table unregister_connection(SID, #jid{luser = LUser, lserver = LServer}, _) -> purge_hook(anonymous_user_exist(LUser, LServer), LUser, LServer), remove_connection(SID, LUser, LServer). %% Launch the hook to purge user data only for anonymous users purge_hook(false, _LUser, _LServer) -> ok; purge_hook(true, LUser, LServer) -> ejabberd_hooks:run(anonymous_purge_hook, LServer, [LUser, LServer]). %% --------------------------------- %% Specific anonymous auth functions %% --------------------------------- %% 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, undefined). check_password(User, Server, _Password, _Digest, _DigestGen) -> case ejabberd_auth:is_user_exists_in_other_modules(?MODULE, User, Server) of %% If user exists in other module, reject anonnymous authentication true -> false; %% If we are not sure whether the user exists in other module, reject anon auth maybe -> false; false -> login(User, Server) end. login(User, Server) -> case is_login_anonymous_enabled(Server) of false -> false; true -> case anonymous_user_exist(User, Server) of %% Reject the login if an anonymous user with the same login %% is already logged and if multiple login has not been enable %% in the config file. true -> allow_multiple_connections(Server); %% Accept login and add user to the anonymous table false -> true end end. %% When anonymous login is enabled, check that the user is permanent before %% changing its password set_password(User, Server, _Password) -> case anonymous_user_exist(User, Server) of true -> ok; false -> {error, not_allowed} end. %% When anonymous login is enabled, check if permanent users are allowed on %% the server: try_register(_User, _Server, _Password) -> {error, not_allowed}. dirty_get_registered_users() -> []. get_vh_registered_users(Server) -> [{U, S} || {U, S, _R} <- ejabberd_sm:get_vh_session_list(Server)]. get_vh_registered_users(Server, _) -> get_vh_registered_users(Server). get_vh_registered_users_number(Server) -> length(get_vh_registered_users(Server)). get_vh_registered_users_number(Server, _) -> get_vh_registered_users_number(Server). %% Return password of permanent user or false for anonymous users get_password(User, Server) -> get_password(User, Server, <<"">>). get_password(User, Server, DefaultValue) -> case anonymous_user_exist(User, Server) or login(User, Server) of %% We return the default value if the user is anonymous true -> DefaultValue; %% We return the permanent user password otherwise false -> false end. get_password_s(User, Server) -> case get_password(User, Server) of false -> <<"">>; Password -> Password end. %% Returns true if the user exists in the DB or if an anonymous user is logged %% under the given name is_user_exists(User, Server) -> anonymous_user_exist(User, Server). remove_user(_User, _Server) -> {error, not_allowed}. remove_user(_User, _Server, _Password) -> not_allowed. 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]. ejabberd-16.01/src/gen_pubsub_nodetree.erl0000644000232200023220000000566112645157216021157 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : gen_pubsub_nodetree.erl %%% Author : Christophe Romain %%% Purpose : Define the pubsub node tree plugin behaviour %%% Created : 1 Dec 2007 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(gen_pubsub_nodetree). -include("jlib.hrl"). -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(). -callback terminate(Host :: host(), ServerHost :: binary()) -> atom(). -callback options() -> nodeOptions(). -callback set_node(PubsubNode :: pubsubNode()) -> ok | {result, NodeIdx::nodeIdx()} | {error, xmlel()}. -callback get_node(Host :: host(), NodeId :: nodeId(), From :: jid()) -> pubsubNode() | {error, xmlel()}. -callback get_node(Host :: host(), NodeId :: nodeId()) -> pubsubNode() | {error, xmlel()}. -callback get_node(NodeIdx :: nodeIdx()) -> pubsubNode() | {error, xmlel()}. -callback get_nodes(Host :: host(), From :: jid())-> [pubsubNode()]. -callback get_nodes(Host :: host())-> [pubsubNode()]. -callback get_parentnodes(Host :: host(), NodeId :: nodeId(), From :: jid()) -> [pubsubNode()] | {error, xmlel()}. -callback get_parentnodes_tree(Host :: host(), NodeId :: nodeId(), From :: jid()) -> [{0, [pubsubNode(),...]}]. -callback get_subnodes(Host :: host(), NodeId :: nodeId(), From :: jid()) -> [pubsubNode()]. -callback get_subnodes_tree(Host :: host(), NodeId :: nodeId(), From :: jid()) -> [pubsubNode()]. -callback create_node(Host :: host(), NodeId :: nodeId(), Type :: binary(), Owner :: jid(), Options :: nodeOptions(), Parents :: [nodeId()]) -> {ok, NodeIdx::nodeIdx()} | {error, xmlel()} | {error, {virtual, {host(), nodeId()}}}. -callback delete_node(Host :: host(), NodeId :: nodeId()) -> [pubsubNode()]. ejabberd-16.01/src/mod_vcard.erl0000644000232200023220000012600212645157216017070 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_vcard.erl %%% Author : Alexey Shchepin %%% Purpose : Vcard management %%% Created : 2 Jan 2003 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(mod_vcard). -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, process_local_iq/3, process_sm_iq/3, reindex_vcards/0, remove_user/2, export/1, import/1, import/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -define(JUD_MATCHES, 30). -record(vcard_search, {us, user, luser, fn, lfn, family, lfamily, given, lgiven, middle, lmiddle, nickname, lnickname, bday, lbday, ctry, lctry, locality, llocality, email, lemail, orgname, lorgname, orgunit, lorgunit}). -record(vcard, {us = {<<"">>, <<"">>} :: {binary(), binary()} | binary(), vcard = #xmlel{} :: xmlel()}). -define(PROCNAME, ejabberd_mod_vcard). start(Host, Opts) -> case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(vcard, [{disc_only_copies, [node()]}, {attributes, record_info(fields, vcard)}]), mnesia:create_table(vcard_search, [{disc_copies, [node()]}, {attributes, record_info(fields, vcard_search)}]), update_tables(), mnesia:add_table_index(vcard_search, luser), mnesia:add_table_index(vcard_search, lfn), mnesia:add_table_index(vcard_search, lfamily), mnesia:add_table_index(vcard_search, lgiven), mnesia:add_table_index(vcard_search, lmiddle), mnesia:add_table_index(vcard_search, lnickname), mnesia:add_table_index(vcard_search, lbday), mnesia:add_table_index(vcard_search, lctry), mnesia:add_table_index(vcard_search, llocality), mnesia:add_table_index(vcard_search, lemail), mnesia:add_table_index(vcard_search, lorgname), mnesia:add_table_index(vcard_search, lorgunit); _ -> ok end, ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), 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_VCARD, ?MODULE, process_local_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD, ?MODULE, process_sm_iq, IQDisc), ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), MyHost = gen_mod:get_opt_host(Host, Opts, <<"vjud.@HOST@">>), Search = gen_mod:get_opt(search, Opts, fun(B) when is_boolean(B) -> B end, false), register(gen_mod:get_module_proc(Host, ?PROCNAME), spawn(?MODULE, init, [MyHost, Host, Search])). init(Host, ServerHost, Search) -> case Search of false -> loop(Host, ServerHost); _ -> ejabberd_router:register_route(Host), loop(Host, ServerHost) end. loop(Host, ServerHost) -> receive {route, From, To, Packet} -> case catch do_route(ServerHost, From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); _ -> ok end, loop(Host, ServerHost); stop -> ejabberd_router:unregister_route(Host), ok; _ -> loop(Host, ServerHost) end. stop(Host) -> ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD), ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), Proc = gen_mod:get_module_proc(Host, ?PROCNAME), Proc ! stop, {wait, Proc}. get_sm_features({error, _Error} = Acc, _From, _To, _Node, _Lang) -> Acc; get_sm_features(Acc, _From, _To, Node, _Lang) -> case Node of <<"">> -> case Acc of {result, Features} -> {result, [?NS_DISCO_INFO, ?NS_VCARD | Features]}; empty -> {result, [?NS_DISCO_INFO, ?NS_VCARD]} end; _ -> Acc end. 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]}; get -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"vCard">>, attrs = [{<<"xmlns">>, ?NS_VCARD}], children = [#xmlel{name = <<"FN">>, attrs = [], children = [{xmlcdata, <<"ejabberd">>}]}, #xmlel{name = <<"URL">>, attrs = [], children = [{xmlcdata, ?EJABBERD_URI}]}, #xmlel{name = <<"DESC">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"Erlang Jabber Server">>))/binary, "\nCopyright (c) 2002-2015 ProcessOne">>}]}, #xmlel{name = <<"BDAY">>, attrs = [], children = [{xmlcdata, <<"2002-11-16">>}]}]}]} end. process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> case Type of set -> #jid{user = User, lserver = LServer} = From, case lists:member(LServer, ?MYHOSTS) of true -> set_vcard(User, LServer, SubEl), IQ#iq{type = result, sub_el = []}; false -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} end; get -> #jid{luser = LUser, lserver = LServer} = To, case get_vcard(LUser, LServer) of error -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}; [] -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"vCard">>, attrs = [{<<"xmlns">>, ?NS_VCARD}], children = []}]}; Els -> IQ#iq{type = result, sub_el = Els} end end. get_vcard(LUser, LServer) -> get_vcard(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). get_vcard(LUser, LServer, mnesia) -> US = {LUser, LServer}, F = fun () -> mnesia:read({vcard, US}) end, case mnesia:transaction(F) of {atomic, Rs} -> lists:map(fun (R) -> R#vcard.vcard end, Rs); {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 xml_stream:parse_element(SVCARD) of {error, _Reason} -> error; VCARD -> [VCARD] end; {selected, [<<"vcard">>], []} -> []; _ -> error end; get_vcard(LUser, LServer, riak) -> case ejabberd_riak:get(vcard, vcard_schema(), {LUser, LServer}) of {ok, R} -> [R#vcard.vcard]; {error, notfound} -> []; _ -> error end. set_vcard(User, LServer, VCARD) -> FN = xml:get_path_s(VCARD, [{elem, <<"FN">>}, cdata]), Family = xml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"FAMILY">>}, cdata]), Given = xml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"GIVEN">>}, cdata]), Middle = xml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"MIDDLE">>}, cdata]), Nickname = xml:get_path_s(VCARD, [{elem, <<"NICKNAME">>}, cdata]), BDay = xml:get_path_s(VCARD, [{elem, <<"BDAY">>}, cdata]), CTRY = xml:get_path_s(VCARD, [{elem, <<"ADR">>}, {elem, <<"CTRY">>}, cdata]), Locality = xml:get_path_s(VCARD, [{elem, <<"ADR">>}, {elem, <<"LOCALITY">>}, cdata]), EMail1 = xml:get_path_s(VCARD, [{elem, <<"EMAIL">>}, {elem, <<"USERID">>}, cdata]), EMail2 = xml:get_path_s(VCARD, [{elem, <<"EMAIL">>}, cdata]), OrgName = xml:get_path_s(VCARD, [{elem, <<"ORG">>}, {elem, <<"ORGNAME">>}, cdata]), OrgUnit = xml:get_path_s(VCARD, [{elem, <<"ORG">>}, {elem, <<"ORGUNIT">>}, cdata]), EMail = case EMail1 of <<"">> -> EMail2; _ -> EMail1 end, LUser = jid:nodeprep(User), LFN = string2lower(FN), LFamily = string2lower(Family), LGiven = string2lower(Given), LMiddle = string2lower(Middle), LNickname = string2lower(Nickname), LBDay = string2lower(BDay), LCTRY = string2lower(CTRY), LLocality = string2lower(Locality), LEMail = string2lower(EMail), LOrgName = string2lower(OrgName), LOrgUnit = string2lower(OrgUnit), if (LUser == error) -> {error, badarg}; true -> case gen_mod:db_type(LServer, ?MODULE) of mnesia -> US = {LUser, LServer}, F = fun () -> mnesia:write(#vcard{us = US, vcard = VCARD}), mnesia:write(#vcard_search{us = US, user = {User, LServer}, luser = LUser, fn = FN, lfn = LFN, family = Family, lfamily = LFamily, given = Given, lgiven = LGiven, middle = Middle, lmiddle = LMiddle, nickname = Nickname, lnickname = LNickname, bday = BDay, lbday = LBDay, ctry = CTRY, lctry = LCTRY, locality = Locality, llocality = LLocality, email = EMail, lemail = LEMail, orgname = OrgName, lorgname = LOrgName, orgunit = OrgUnit, lorgunit = LOrgUnit}) end, mnesia:transaction(F); riak -> US = {LUser, LServer}, ejabberd_riak:put(#vcard{us = US, vcard = VCARD}, vcard_schema(), [{'2i', [{<<"user">>, User}, {<<"luser">>, LUser}, {<<"fn">>, FN}, {<<"lfn">>, LFN}, {<<"family">>, Family}, {<<"lfamily">>, LFamily}, {<<"given">>, Given}, {<<"lgiven">>, LGiven}, {<<"middle">>, Middle}, {<<"lmiddle">>, LMiddle}, {<<"nickname">>, Nickname}, {<<"lnickname">>, LNickname}, {<<"bday">>, BDay}, {<<"lbday">>, LBDay}, {<<"ctry">>, CTRY}, {<<"lctry">>, LCTRY}, {<<"locality">>, Locality}, {<<"llocality">>, LLocality}, {<<"email">>, EMail}, {<<"lemail">>, LEMail}, {<<"orgname">>, OrgName}, {<<"lorgname">>, LOrgName}, {<<"orgunit">>, OrgUnit}, {<<"lorgunit">>, LOrgUnit}]}]); odbc -> Username = ejabberd_odbc:escape(User), LUsername = ejabberd_odbc:escape(LUser), SVCARD = ejabberd_odbc:escape(xml: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) end, ejabberd_hooks:run(vcard_set, LServer, [LUser, LServer, VCARD]) end. string2lower(String) -> case stringprep:tolower(String) of Lower when is_binary(Lower) -> Lower; error -> str:to_lower(String) end. -define(TLFIELD(Type, Label, Var), #xmlel{name = <<"field">>, attrs = [{<<"type">>, Type}, {<<"label">>, translate:translate(Lang, Label)}, {<<"var">>, Var}], children = []}). -define(FORM(JID), [#xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"You need an x:data capable client to " "search">>)}]}, #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = [#xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"Search users in ">>))/binary, (jid:to_string(JID))/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Fill in the form to search for any matching " "Jabber User (Add * to the end of field " "to match substring)">>)}]}, ?TLFIELD(<<"text-single">>, <<"User">>, <<"user">>), ?TLFIELD(<<"text-single">>, <<"Full Name">>, <<"fn">>), ?TLFIELD(<<"text-single">>, <<"Name">>, <<"first">>), ?TLFIELD(<<"text-single">>, <<"Middle Name">>, <<"middle">>), ?TLFIELD(<<"text-single">>, <<"Family Name">>, <<"last">>), ?TLFIELD(<<"text-single">>, <<"Nickname">>, <<"nick">>), ?TLFIELD(<<"text-single">>, <<"Birthday">>, <<"bday">>), ?TLFIELD(<<"text-single">>, <<"Country">>, <<"ctry">>), ?TLFIELD(<<"text-single">>, <<"City">>, <<"locality">>), ?TLFIELD(<<"text-single">>, <<"Email">>, <<"email">>), ?TLFIELD(<<"text-single">>, <<"Organization Name">>, <<"orgname">>), ?TLFIELD(<<"text-single">>, <<"Organization Unit">>, <<"orgunit">>)]}]). do_route(ServerHost, From, To, Packet) -> #jid{user = User, resource = Resource} = To, if (User /= <<"">>) or (Resource /= <<"">>) -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err); true -> IQ = jlib:iq_query_info(Packet), case IQ of #iq{type = Type, xmlns = ?NS_SEARCH, lang = Lang, sub_el = SubEl} -> case Type of set -> XDataEl = find_xdata_el(SubEl), case XDataEl of false -> Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), ejabberd_router:route(To, From, Err); _ -> XData = jlib:parse_xdata_submit(XDataEl), case XData of invalid -> Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), ejabberd_router:route(To, From, Err); _ -> ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_SEARCH}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}], children = search_result(Lang, To, ServerHost, XData)}]}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end end; get -> ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_SEARCH}], children = ?FORM(To)}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end; #iq{type = Type, xmlns = ?NS_DISCO_INFO, lang = Lang} -> case Type of set -> Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), ejabberd_router:route(To, From, Err); get -> Info = ejabberd_hooks:run_fold(disco_info, ServerHost, [], [ServerHost, ?MODULE, <<"">>, <<"">>]), ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_INFO}], children = [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"directory">>}, {<<"type">>, <<"user">>}, {<<"name">>, translate:translate(Lang, <<"vCard User Search">>)}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_DISCO_INFO}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_SEARCH}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_VCARD}], children = []}] ++ Info}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end; #iq{type = Type, xmlns = ?NS_DISCO_ITEMS} -> case Type of set -> Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), ejabberd_router:route(To, From, Err); get -> ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_ITEMS}], children = []}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)) end; #iq{type = get, xmlns = ?NS_VCARD, lang = Lang} -> ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"vCard">>, attrs = [{<<"xmlns">>, ?NS_VCARD}], children = iq_get_vcard(Lang)}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)); _ -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err) end end. iq_get_vcard(Lang) -> [#xmlel{name = <<"FN">>, attrs = [], children = [{xmlcdata, <<"ejabberd/mod_vcard">>}]}, #xmlel{name = <<"URL">>, attrs = [], children = [{xmlcdata, ?EJABBERD_URI}]}, #xmlel{name = <<"DESC">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd vCard module">>))/binary, "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. find_xdata_el(#xmlel{children = SubEls}) -> find_xdata_el1(SubEls). find_xdata_el1([]) -> false; find_xdata_el1([#xmlel{name = Name, attrs = Attrs, children = SubEls} | Els]) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> #xmlel{name = Name, attrs = Attrs, children = SubEls}; _ -> find_xdata_el1(Els) end; find_xdata_el1([_ | Els]) -> find_xdata_el1(Els). -define(LFIELD(Label, Var), #xmlel{name = <<"field">>, attrs = [{<<"label">>, translate:translate(Lang, Label)}, {<<"var">>, Var}], children = []}). search_result(Lang, JID, ServerHost, Data) -> [#xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"Search Results for ">>))/binary, (jid:to_string(JID))/binary>>}]}, #xmlel{name = <<"reported">>, attrs = [], children = [?TLFIELD(<<"text-single">>, <<"Jabber ID">>, <<"jid">>), ?TLFIELD(<<"text-single">>, <<"Full Name">>, <<"fn">>), ?TLFIELD(<<"text-single">>, <<"Name">>, <<"first">>), ?TLFIELD(<<"text-single">>, <<"Middle Name">>, <<"middle">>), ?TLFIELD(<<"text-single">>, <<"Family Name">>, <<"last">>), ?TLFIELD(<<"text-single">>, <<"Nickname">>, <<"nick">>), ?TLFIELD(<<"text-single">>, <<"Birthday">>, <<"bday">>), ?TLFIELD(<<"text-single">>, <<"Country">>, <<"ctry">>), ?TLFIELD(<<"text-single">>, <<"City">>, <<"locality">>), ?TLFIELD(<<"text-single">>, <<"Email">>, <<"email">>), ?TLFIELD(<<"text-single">>, <<"Organization Name">>, <<"orgname">>), ?TLFIELD(<<"text-single">>, <<"Organization Unit">>, <<"orgunit">>)]}] ++ lists:map(fun (R) -> record_to_item(ServerHost, R) end, search(ServerHost, Data)). -define(FIELD(Var, Val), #xmlel{name = <<"field">>, attrs = [{<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Val}]}]}). record_to_item(LServer, [Username, FN, Family, Given, Middle, Nickname, BDay, CTRY, Locality, EMail, OrgName, OrgUnit]) -> #xmlel{name = <<"item">>, attrs = [], children = [?FIELD(<<"jid">>, <>), ?FIELD(<<"fn">>, FN), ?FIELD(<<"last">>, Family), ?FIELD(<<"first">>, Given), ?FIELD(<<"middle">>, Middle), ?FIELD(<<"nick">>, Nickname), ?FIELD(<<"bday">>, BDay), ?FIELD(<<"ctry">>, CTRY), ?FIELD(<<"locality">>, Locality), ?FIELD(<<"email">>, EMail), ?FIELD(<<"orgname">>, OrgName), ?FIELD(<<"orgunit">>, OrgUnit)]}; record_to_item(_LServer, #vcard_search{} = R) -> {User, Server} = R#vcard_search.user, #xmlel{name = <<"item">>, attrs = [], children = [?FIELD(<<"jid">>, <>), ?FIELD(<<"fn">>, (R#vcard_search.fn)), ?FIELD(<<"last">>, (R#vcard_search.family)), ?FIELD(<<"first">>, (R#vcard_search.given)), ?FIELD(<<"middle">>, (R#vcard_search.middle)), ?FIELD(<<"nick">>, (R#vcard_search.nickname)), ?FIELD(<<"bday">>, (R#vcard_search.bday)), ?FIELD(<<"ctry">>, (R#vcard_search.ctry)), ?FIELD(<<"locality">>, (R#vcard_search.locality)), ?FIELD(<<"email">>, (R#vcard_search.email)), ?FIELD(<<"orgname">>, (R#vcard_search.orgname)), ?FIELD(<<"orgunit">>, (R#vcard_search.orgunit))]}. search(LServer, Data) -> DBType = gen_mod:db_type(LServer, ?MODULE), MatchSpec = make_matchspec(LServer, Data, DBType), AllowReturnAll = gen_mod:get_module_opt(LServer, ?MODULE, allow_return_all, fun(B) when is_boolean(B) -> B end, false), search(LServer, MatchSpec, AllowReturnAll, DBType). search(LServer, MatchSpec, AllowReturnAll, mnesia) -> if (MatchSpec == #vcard_search{_ = '_'}) and not AllowReturnAll -> []; true -> case catch mnesia:dirty_select(vcard_search, [{MatchSpec, [], ['$_']}]) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), []; Rs -> case gen_mod:get_module_opt(LServer, ?MODULE, matches, fun(infinity) -> infinity; (I) when is_integer(I), I>0 -> I end, ?JUD_MATCHES) of infinity -> Rs; Val -> lists:sublist(Rs, Val) end end end; search(LServer, MatchSpec, AllowReturnAll, odbc) -> if (MatchSpec == <<"">>) and not AllowReturnAll -> []; true -> Limit = case gen_mod:get_module_opt(LServer, ?MODULE, matches, fun(infinity) -> infinity; (I) when is_integer(I), I>0 -> I end, ?JUD_MATCHES) of infinity -> <<"">>; Val -> [<<" LIMIT ">>, jlib:integer_to_binary(Val)] end, case catch ejabberd_odbc:sql_query(LServer, [<<"select username, fn, family, given, " "middle, nickname, bday, ctry, " "locality, email, orgname, orgunit " "from vcard_search ">>, MatchSpec, Limit, <<";">>]) of {selected, [<<"username">>, <<"fn">>, <<"family">>, <<"given">>, <<"middle">>, <<"nickname">>, <<"bday">>, <<"ctry">>, <<"locality">>, <<"email">>, <<"orgname">>, <<"orgunit">>], Rs} when is_list(Rs) -> Rs; Error -> ?ERROR_MSG("~p", [Error]), [] end end; search(_LServer, _MatchSpec, _AllowReturnAll, riak) -> []. make_matchspec(LServer, Data, mnesia) -> GlobMatch = #vcard_search{_ = '_'}, Match = filter_fields(Data, GlobMatch, LServer, mnesia), Match; make_matchspec(LServer, Data, odbc) -> filter_fields(Data, <<"">>, LServer, odbc); make_matchspec(_LServer, _Data, riak) -> []. filter_fields([], Match, _LServer, mnesia) -> Match; filter_fields([], Match, _LServer, odbc) -> case Match of <<"">> -> <<"">>; _ -> [<<" where ">>, Match] end; filter_fields([{SVar, [Val]} | Ds], Match, LServer, mnesia) when is_binary(Val) and (Val /= <<"">>) -> LVal = string2lower(Val), NewMatch = case SVar of <<"user">> -> case gen_mod:get_module_opt(LServer, ?MODULE, search_all_hosts, fun(B) when is_boolean(B) -> B end, true) of true -> Match#vcard_search{luser = make_val(LVal)}; false -> Host = find_my_host(LServer), Match#vcard_search{us = {make_val(LVal), Host}} end; <<"fn">> -> Match#vcard_search{lfn = make_val(LVal)}; <<"last">> -> Match#vcard_search{lfamily = make_val(LVal)}; <<"first">> -> Match#vcard_search{lgiven = make_val(LVal)}; <<"middle">> -> Match#vcard_search{lmiddle = make_val(LVal)}; <<"nick">> -> Match#vcard_search{lnickname = make_val(LVal)}; <<"bday">> -> Match#vcard_search{lbday = make_val(LVal)}; <<"ctry">> -> Match#vcard_search{lctry = make_val(LVal)}; <<"locality">> -> Match#vcard_search{llocality = make_val(LVal)}; <<"email">> -> Match#vcard_search{lemail = make_val(LVal)}; <<"orgname">> -> Match#vcard_search{lorgname = make_val(LVal)}; <<"orgunit">> -> Match#vcard_search{lorgunit = make_val(LVal)}; _ -> Match end, filter_fields(Ds, NewMatch, LServer, mnesia); filter_fields([{SVar, [Val]} | Ds], Match, LServer, odbc) when is_binary(Val) and (Val /= <<"">>) -> LVal = string2lower(Val), NewMatch = case SVar of <<"user">> -> make_val(Match, <<"lusername">>, LVal); <<"fn">> -> make_val(Match, <<"lfn">>, LVal); <<"last">> -> make_val(Match, <<"lfamily">>, LVal); <<"first">> -> make_val(Match, <<"lgiven">>, LVal); <<"middle">> -> make_val(Match, <<"lmiddle">>, LVal); <<"nick">> -> make_val(Match, <<"lnickname">>, LVal); <<"bday">> -> make_val(Match, <<"lbday">>, LVal); <<"ctry">> -> make_val(Match, <<"lctry">>, LVal); <<"locality">> -> make_val(Match, <<"llocality">>, LVal); <<"email">> -> make_val(Match, <<"lemail">>, LVal); <<"orgname">> -> make_val(Match, <<"lorgname">>, LVal); <<"orgunit">> -> make_val(Match, <<"lorgunit">>, LVal); _ -> Match end, filter_fields(Ds, NewMatch, LServer, odbc); filter_fields([_ | Ds], Match, LServer, DBType) -> filter_fields(Ds, Match, LServer, DBType). make_val(Match, Field, Val) -> Condition = case str:suffix(<<"*">>, Val) of true -> Val1 = str:substr(Val, 1, byte_size(Val) - 1), SVal = <<(ejabberd_odbc:escape_like(Val1))/binary, "%">>, [Field, <<" LIKE '">>, SVal, <<"'">>]; _ -> SVal = ejabberd_odbc:escape(Val), [Field, <<" = '">>, SVal, <<"'">>] end, case Match of <<"">> -> Condition; _ -> [Match, <<" and ">>, Condition] end. make_val(Val) -> case str:suffix(<<"*">>, Val) of true -> [str:substr(Val, 1, byte_size(Val) - 1)] ++ '_'; _ -> Val end. find_my_host(LServer) -> Parts = str:tokens(LServer, <<".">>), find_my_host(Parts, ?MYHOSTS). find_my_host([], _Hosts) -> ?MYNAME; find_my_host([_ | Tail] = Parts, Hosts) -> Domain = parts_to_string(Parts), case lists:member(Domain, Hosts) of true -> Domain; false -> find_my_host(Tail, Hosts) end. parts_to_string(Parts) -> str:strip(list_to_binary( lists:map(fun (S) -> <> end, Parts)), right, $.). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 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, [{elem, <<"N">>}, {elem, <<"FAMILY">>}, cdata]), Given = xml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"GIVEN">>}, cdata]), Middle = xml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"MIDDLE">>}, cdata]), Nickname = xml:get_path_s(VCARD, [{elem, <<"NICKNAME">>}, cdata]), BDay = xml:get_path_s(VCARD, [{elem, <<"BDAY">>}, cdata]), CTRY = xml:get_path_s(VCARD, [{elem, <<"ADR">>}, {elem, <<"CTRY">>}, cdata]), Locality = xml:get_path_s(VCARD, [{elem, <<"ADR">>}, {elem, <<"LOCALITY">>}, cdata]), EMail = xml:get_path_s(VCARD, [{elem, <<"EMAIL">>}, cdata]), OrgName = xml:get_path_s(VCARD, [{elem, <<"ORG">>}, {elem, <<"ORGNAME">>}, cdata]), OrgUnit = xml:get_path_s(VCARD, [{elem, <<"ORG">>}, {elem, <<"ORGUNIT">>}, cdata]), {LUser, _LServer} = US, LFN = string2lower(FN), LFamily = string2lower(Family), LGiven = string2lower(Given), LMiddle = string2lower(Middle), LNickname = string2lower(Nickname), LBDay = string2lower(BDay), LCTRY = string2lower(CTRY), LLocality = string2lower(Locality), LEMail = string2lower(EMail), LOrgName = string2lower(OrgName), LOrgUnit = string2lower(OrgUnit), mnesia:write(#vcard_search{us = US, user = User, luser = LUser, fn = FN, lfn = LFN, family = Family, lfamily = LFamily, given = Given, lgiven = LGiven, middle = Middle, lmiddle = LMiddle, nickname = Nickname, lnickname = LNickname, bday = BDay, lbday = LBDay, ctry = CTRY, lctry = LCTRY, locality = Locality, llocality = LLocality, email = EMail, lemail = LEMail, orgname = OrgName, lorgname = LOrgName, orgunit = OrgUnit, lorgunit = LOrgUnit}). reindex_vcards() -> F = fun () -> mnesia:foldl(fun set_vcard_t/2, [], vcard) end, mnesia:transaction(F). remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). remove_user(LUser, LServer, mnesia) -> US = {LUser, LServer}, F = fun () -> mnesia:delete({vcard, US}), mnesia:delete({vcard_search, US}) 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, <<"';">>]]); remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete(vcard, {LUser, LServer})}. update_tables() -> update_vcard_table(), update_vcard_search_table(). update_vcard_table() -> Fields = record_info(fields, vcard), case mnesia:table_info(vcard, attributes) of Fields -> ejabberd_config:convert_table_to_binary( vcard, Fields, set, fun(#vcard{us = {U, _}}) -> U end, fun(#vcard{us = {U, S}, vcard = El} = R) -> R#vcard{us = {iolist_to_binary(U), iolist_to_binary(S)}, vcard = xml:to_xmlel(El)} end); _ -> ?INFO_MSG("Recreating vcard table", []), mnesia:transform_table(vcard, ignore, Fields) end. update_vcard_search_table() -> Fields = record_info(fields, vcard_search), case mnesia:table_info(vcard_search, attributes) of Fields -> ejabberd_config:convert_table_to_binary( vcard_search, Fields, set, fun(#vcard_search{us = {U, _}}) -> U end, fun(#vcard_search{} = VS) -> [vcard_search | L] = tuple_to_list(VS), NewL = lists:map( fun({U, S}) -> {iolist_to_binary(U), iolist_to_binary(S)}; (Str) -> iolist_to_binary(Str) end, L), list_to_tuple([vcard_search | NewL]) end); _ -> ?INFO_MSG("Recreating vcard_search table", []), mnesia:transform_table(vcard_search, ignore, Fields) end. vcard_schema() -> {record_info(fields, vcard), #vcard{}}. export(_Server) -> [{vcard, fun(Host, #vcard{us = {LUser, LServer}, vcard = VCARD}) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), SVCARD = ejabberd_odbc:escape(xml:element_to_binary(VCARD)), [[<<"delete from vcard where username='">>, Username, <<"';">>], [<<"insert into vcard(username, vcard) values ('">>, Username, <<"', '">>, SVCARD, <<"');">>]]; (_Host, _R) -> [] end}, {vcard_search, fun(Host, #vcard_search{user = {User, LServer}, luser = LUser, fn = FN, lfn = LFN, family = Family, lfamily = LFamily, given = Given, lgiven = LGiven, middle = Middle, lmiddle = LMiddle, nickname = Nickname, lnickname = LNickname, bday = BDay, lbday = LBDay, ctry = CTRY, lctry = LCTRY, locality = Locality, llocality = LLocality, email = EMail, lemail = LEMail, orgname = OrgName, lorgname = LOrgName, orgunit = OrgUnit, lorgunit = LOrgUnit}) when LServer == Host -> Username = ejabberd_odbc:escape(User), LUsername = ejabberd_odbc:escape(LUser), 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), [[<<"delete from vcard_search where lusername='">>, LUsername, <<"';">>], [<<"insert into 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)values (">>, <<" '">>, Username, <<"', '">>, LUsername, <<"', '">>, SFN, <<"', '">>, SLFN, <<"', '">>, SFamily, <<"', '">>, SLFamily, <<"', '">>, SGiven, <<"', '">>, SLGiven, <<"', '">>, SMiddle, <<"', '">>, SLMiddle, <<"', '">>, SNickname, <<"', '">>, SLNickname, <<"', '">>, SBDay, <<"', '">>, SLBDay, <<"', '">>, SCTRY, <<"', '">>, SLCTRY, <<"', '">>, SLocality, <<"', '">>, SLLocality, <<"', '">>, SEMail, <<"', '">>, SLEMail, <<"', '">>, SOrgName, <<"', '">>, SLOrgName, <<"', '">>, SOrgUnit, <<"', '">>, SLOrgUnit, <<"');">>]]; (_Host, _R) -> [] end}]. import(LServer) -> [{<<"select username, vcard from vcard;">>, fun([LUser, SVCard]) -> #xmlel{} = VCARD = xml_stream:parse_element(SVCard), #vcard{us = {LUser, LServer}, vcard = VCARD} end}, {<<"select username, lusername, fn, lfn, family, lfamily, " "given, lgiven, middle, lmiddle, nickname, lnickname, " "bday, lbday, ctry, lctry, locality, llocality, email, " "lemail, orgname, lorgname, orgunit, lorgunit from vcard_search;">>, fun([User, LUser, FN, LFN, Family, LFamily, Given, LGiven, Middle, LMiddle, Nickname, LNickname, BDay, LBDay, CTRY, LCTRY, Locality, LLocality, EMail, LEMail, OrgName, LOrgName, OrgUnit, LOrgUnit]) -> #vcard_search{us = {LUser, LServer}, user = {User, LServer}, luser = LUser, fn = FN, lfn = LFN, family = Family, lfamily = LFamily, given = Given, lgiven = LGiven, middle = Middle, lmiddle = LMiddle, nickname = Nickname, lnickname = LNickname, bday = BDay, lbday = LBDay, ctry = CTRY, lctry = LCTRY, locality = Locality, llocality = LLocality, email = EMail, lemail = LEMail, orgname = OrgName, lorgname = LOrgName, orgunit = OrgUnit, lorgunit = LOrgUnit} end}]. import(_LServer, mnesia, #vcard{} = VCard) -> mnesia:dirty_write(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, [{elem, <<"N">>}, {elem, <<"FAMILY">>}, cdata]), Given = xml:get_path_s(El, [{elem, <<"N">>}, {elem, <<"GIVEN">>}, cdata]), Middle = xml:get_path_s(El, [{elem, <<"N">>}, {elem, <<"MIDDLE">>}, cdata]), Nickname = xml:get_path_s(El, [{elem, <<"NICKNAME">>}, cdata]), BDay = xml:get_path_s(El, [{elem, <<"BDAY">>}, cdata]), CTRY = xml:get_path_s(El, [{elem, <<"ADR">>}, {elem, <<"CTRY">>}, cdata]), Locality = xml:get_path_s(El, [{elem, <<"ADR">>}, {elem, <<"LOCALITY">>}, cdata]), EMail1 = xml:get_path_s(El, [{elem, <<"EMAIL">>}, {elem, <<"USERID">>}, cdata]), EMail2 = xml:get_path_s(El, [{elem, <<"EMAIL">>}, cdata]), OrgName = xml:get_path_s(El, [{elem, <<"ORG">>}, {elem, <<"ORGNAME">>}, cdata]), OrgUnit = xml:get_path_s(El, [{elem, <<"ORG">>}, {elem, <<"ORGUNIT">>}, cdata]), EMail = case EMail1 of <<"">> -> EMail2; _ -> EMail1 end, LFN = string2lower(FN), LFamily = string2lower(Family), LGiven = string2lower(Given), LMiddle = string2lower(Middle), LNickname = string2lower(Nickname), LBDay = string2lower(BDay), LCTRY = string2lower(CTRY), LLocality = string2lower(Locality), LEMail = string2lower(EMail), LOrgName = string2lower(OrgName), LOrgUnit = string2lower(OrgUnit), ejabberd_riak:put(VCard, vcard_schema(), [{'2i', [{<<"user">>, LUser}, {<<"luser">>, LUser}, {<<"fn">>, FN}, {<<"lfn">>, LFN}, {<<"family">>, Family}, {<<"lfamily">>, LFamily}, {<<"given">>, Given}, {<<"lgiven">>, LGiven}, {<<"middle">>, Middle}, {<<"lmiddle">>, LMiddle}, {<<"nickname">>, Nickname}, {<<"lnickname">>, LNickname}, {<<"bday">>, BDay}, {<<"lbday">>, LBDay}, {<<"ctry">>, CTRY}, {<<"lctry">>, LCTRY}, {<<"locality">>, Locality}, {<<"llocality">>, LLocality}, {<<"email">>, EMail}, {<<"lemail">>, LEMail}, {<<"orgname">>, OrgName}, {<<"lorgname">>, LOrgName}, {<<"orgunit">>, OrgUnit}, {<<"lorgunit">>, LOrgUnit}]}]); 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]. ejabberd-16.01/src/ejabberd_auth_ldap.erl0000644000232200023220000003437512645157216020724 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_auth_ldap.erl %%% Author : Alexey Shchepin %%% Purpose : Authentification via LDAP %%% Created : 12 Dec 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_auth_ldap). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_server). -behaviour(ejabberd_auth). %% gen_server callbacks -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -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_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]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("eldap.hrl"). -record(state, {host = <<"">> :: binary(), eldap_id = <<"">> :: binary(), bind_eldap_id = <<"">> :: binary(), servers = [] :: [binary()], backups = [] :: [binary()], port = ?LDAP_PORT :: inet:port_number(), tls_options = [] :: list(), dn = <<"">> :: binary(), password = <<"">> :: binary(), base = <<"">> :: binary(), uids = [] :: [{binary()} | {binary(), binary()}], ufilter = <<"">> :: binary(), sfilter = <<"">> :: binary(), lfilter :: {any(), any()}, deref_aliases = never :: never | searching | finding | always, dn_filter :: binary(), dn_filter_attrs = [] :: [binary()]}). handle_cast(_Request, State) -> {noreply, State}. code_change(_OldVsn, State, _Extra) -> {ok, State}. handle_info(_Info, State) -> {noreply, State}. -define(LDAP_SEARCH_TIMEOUT, 5). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start(Host) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), ChildSpec = {Proc, {?MODULE, start_link, [Host]}, transient, 1000, worker, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop(Host) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:call(Proc, stop), supervisor:terminate_child(ejabberd_sup, Proc), supervisor:delete_child(ejabberd_sup, Proc). start_link(Host) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:start_link({local, Proc}, ?MODULE, Host, []). terminate(_Reason, _State) -> ok. init(Host) -> State = parse_options(Host), 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), eldap_pool:start_link(State#state.bind_eldap_id, State#state.servers, State#state.backups, State#state.port, State#state.dn, State#state.password, State#state.tls_options), {ok, State}. 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 end. check_password(User, Server, Password, _Digest, _DigestGen) -> check_password(User, Server, Password). set_password(User, Server, Password) -> {ok, State} = eldap_utils:get_state(Server, ?MODULE), case find_user_dn(User, State) of false -> {error, user_not_found}; DN -> eldap_pool:modify_passwd(State#state.eldap_id, DN, Password) end. %% @spec (User, Server, Password) -> {error, not_allowed} try_register(_User, _Server, _Password) -> {error, not_allowed}. dirty_get_registered_users() -> Servers = ejabberd_config:get_vh_by_auth_method(ldap), lists:flatmap(fun (Server) -> get_vh_registered_users(Server) end, Servers). get_vh_registered_users(Server) -> case catch get_vh_registered_users_ldap(Server) of {'EXIT', _} -> []; Result -> Result end. get_vh_registered_users(Server, _) -> get_vh_registered_users(Server). get_vh_registered_users_number(Server) -> length(get_vh_registered_users(Server)). get_vh_registered_users_number(Server, _) -> get_vh_registered_users_number(Server). get_password(_User, _Server) -> false. get_password_s(_User, _Server) -> <<"">>. %% @spec (User, Server) -> true | false | {error, Error} is_user_exists(User, Server) -> case catch is_user_exists_ldap(User, Server) of {'EXIT', Error} -> {error, Error}; Result -> Result end. remove_user(_User, _Server) -> {error, not_allowed}. remove_user(_User, _Server, _Password) -> not_allowed. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- check_password_ldap(User, Server, Password) -> {ok, State} = eldap_utils:get_state(Server, ?MODULE), case find_user_dn(User, State) of false -> false; DN -> case eldap_pool:bind(State#state.bind_eldap_id, DN, Password) of ok -> true; _ -> false end end. get_vh_registered_users_ldap(Server) -> {ok, State} = eldap_utils:get_state(Server, ?MODULE), UIDs = State#state.uids, Eldap_ID = State#state.eldap_id, Server = State#state.host, ResAttrs = result_attrs(State), case eldap_filter:parse(State#state.sfilter) of {ok, EldapFilter} -> case eldap_pool:search(Eldap_ID, [{base, State#state.base}, {filter, EldapFilter}, {timeout, ?LDAP_SEARCH_TIMEOUT}, {deref_aliases, State#state.deref_aliases}, {attributes, ResAttrs}]) of #eldap_search_result{entries = Entries} -> lists:flatmap(fun (#eldap_entry{attributes = Attrs, object_name = DN}) -> case is_valid_dn(DN, Attrs, State) of false -> []; _ -> case eldap_utils:find_ldap_attrs(UIDs, Attrs) of <<"">> -> []; {User, UIDFormat} -> case eldap_utils:get_user_part(User, UIDFormat) of {ok, U} -> case jid:nodeprep(U) of error -> []; LU -> [{LU, jid:nameprep(Server)}] end; _ -> [] end end end end, Entries); _ -> [] end; _ -> [] end. is_user_exists_ldap(User, Server) -> {ok, State} = eldap_utils:get_state(Server, ?MODULE), case find_user_dn(User, State) of false -> false; _DN -> true end. handle_call(get_state, _From, State) -> {reply, {ok, State}, State}; handle_call(stop, _From, State) -> {stop, normal, ok, State}; handle_call(_Request, _From, State) -> {reply, bad_request, State}. find_user_dn(User, State) -> ResAttrs = result_attrs(State), case eldap_filter:parse(State#state.ufilter, [{<<"%u">>, User}]) of {ok, Filter} -> case eldap_pool:search(State#state.eldap_id, [{base, State#state.base}, {filter, Filter}, {deref_aliases, State#state.deref_aliases}, {attributes, ResAttrs}]) of #eldap_search_result{entries = [#eldap_entry{attributes = Attrs, object_name = DN} | _]} -> dn_filter(DN, Attrs, State); _ -> false end; _ -> false end. %% apply the dn filter and the local filter: dn_filter(DN, Attrs, State) -> case check_local_filter(Attrs, State) of false -> false; true -> is_valid_dn(DN, Attrs, State) end. %% Check that the DN is valid, based on the dn filter is_valid_dn(DN, _, #state{dn_filter = undefined}) -> DN; is_valid_dn(DN, Attrs, State) -> DNAttrs = State#state.dn_filter_attrs, UIDs = State#state.uids, Values = [{<<"%s">>, eldap_utils:get_ldap_attr(Attr, Attrs), 1} || Attr <- DNAttrs], SubstValues = case eldap_utils:find_ldap_attrs(UIDs, Attrs) of <<"">> -> Values; {S, UAF} -> case eldap_utils:get_user_part(S, UAF) of {ok, U} -> [{<<"%u">>, U} | Values]; _ -> Values end end ++ [{<<"%d">>, State#state.host}, {<<"%D">>, DN}], case eldap_filter:parse(State#state.dn_filter, SubstValues) of {ok, EldapFilter} -> case eldap_pool:search(State#state.eldap_id, [{base, State#state.base}, {filter, EldapFilter}, {deref_aliases, State#state.deref_aliases}, {attributes, [<<"dn">>]}]) of #eldap_search_result{entries = [_ | _]} -> DN; _ -> false end; _ -> false end. %% The local filter is used to check an attribute in ejabberd %% and not in LDAP to limit the load on the LDAP directory. %% A local rule can be either: %% {equal, {"accountStatus",["active"]}} %% {notequal, {"accountStatus",["disabled"]}} %% {ldap_local_filter, {notequal, {"accountStatus",["disabled"]}}} check_local_filter(_Attrs, #state{lfilter = undefined}) -> true; check_local_filter(Attrs, #state{lfilter = LocalFilter}) -> {Operation, FilterMatch} = LocalFilter, local_filter(Operation, Attrs, FilterMatch). local_filter(equal, Attrs, FilterMatch) -> {Attr, Value} = FilterMatch, case lists:keysearch(Attr, 1, Attrs) of false -> false; {value, {Attr, Value}} -> true; _ -> false end; local_filter(notequal, Attrs, FilterMatch) -> not local_filter(equal, Attrs, FilterMatch). result_attrs(#state{uids = UIDs, dn_filter_attrs = DNFilterAttrs}) -> lists:foldl(fun ({UID}, Acc) -> [UID | Acc]; ({UID, _}, Acc) -> [UID | Acc] end, DNFilterAttrs, UIDs). %%%---------------------------------------------------------------------- %%% Auxiliary functions %%%---------------------------------------------------------------------- parse_options(Host) -> Cfg = eldap_utils:get_config(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 = gen_mod:get_opt( {ldap_uids, Host}, [], 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, [{<<"uid">>, <<"%u">>}]), UIDs = eldap_utils:uids_domain_subst(Host, UIDsTemp), SubFilter = eldap_utils:generate_subfilter(UIDs), UserFilter = case gen_mod:get_opt( {ldap_filter, Host}, [], fun check_filter/1, <<"">>) of <<"">> -> SubFilter; F -> <<"(&", SubFilter/binary, F/binary, ")">> end, SearchFilter = eldap_filter:do_sub(UserFilter, [{<<"%u">>, <<"*">>}]), {DNFilter, DNFilterAttrs} = gen_mod:get_opt({ldap_dn_filter, Host}, [], fun([{DNF, DNFA}]) -> NewDNFA = case DNFA of undefined -> []; _ -> [iolist_to_binary(A) || A <- DNFA] end, NewDNF = check_filter(DNF), {NewDNF, NewDNFA} end, {undefined, []}), 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, 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, password = Cfg#eldap_config.password, base = Cfg#eldap_config.base, deref_aliases = Cfg#eldap_config.deref_aliases, uids = UIDs, ufilter = UserFilter, sfilter = SearchFilter, lfilter = LocalFilter, dn_filter = DNFilter, dn_filter_attrs = DNFilterAttrs}. check_filter(F) -> NewF = iolist_to_binary(F), {ok, _} = eldap_filter:parse(NewF), NewF. 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]. ejabberd-16.01/src/mod_muc_room.erl0000644000232200023220000044706212645157216017625 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_muc_room.erl %%% Author : Alexey Shchepin %%% Purpose : MUC room stuff %%% Created : 19 Mar 2003 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(mod_muc_room). -author('alexey@process-one.net'). -behaviour(gen_fsm). %% External exports -export([start_link/9, start_link/7, start/9, start/7, get_role/2, get_affiliation/2, is_occupant_or_admin/2, route/4]). %% gen_fsm callbacks -export([init/1, normal_state/2, handle_event/3, handle_sync_event/4, handle_info/3, terminate/3, code_change/4]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("mod_muc_room.hrl"). -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). -define(FSMOPTS, [{debug, [trace]}]). -else. -define(FSMOPTS, []). -endif. %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Creator, Nick, DefRoomOpts) -> gen_fsm:start(?MODULE, [Host, ServerHost, Access, Room, HistorySize, RoomShaper, Creator, Nick, DefRoomOpts], ?FSMOPTS). start(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts) -> gen_fsm:start(?MODULE, [Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts], ?FSMOPTS). start_link(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Creator, Nick, DefRoomOpts) -> gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize, RoomShaper, Creator, Nick, DefRoomOpts], ?FSMOPTS). start_link(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts) -> gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts], ?FSMOPTS). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- 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 = jid:make(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, State1#state.host, State1#state.room, make_opts(State1)); true -> ok end, ?INFO_MSG("Created MUC room ~s@~s by ~s", [Room, Host, jid:to_string(Creator)]), add_to_log(room_existence, created, State1), add_to_log(room_existence, started, State1), {ok, normal_state, State1}; init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts]) -> process_flag(trap_exit, true), Shaper = shaper:new(RoomShaper), State = set_opts(Opts, #state{host = Host, server_host = ServerHost, access = Access, room = Room, history = lqueue_new(HistorySize), jid = jid:make(Room, Host, <<"">>), room_shaper = Shaper}), add_to_log(room_existence, started, State), {ok, normal_state, State}. normal_state({route, From, <<"">>, #xmlel{name = <<"message">>, attrs = Attrs, children = Els} = Packet}, StateData) -> Lang = xml: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 <<"groupchat">> -> Activity = get_user_activity(From, StateData), 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) * 1000000), Size = element_size(Packet), {MessageShaper, MessageShaperInterval} = shaper:update(Activity#activity.message_shaper, Size), if Activity#activity.message /= undefined -> ErrText = <<"Traffic rate limit is exceeded">>, Err = jlib:make_error_reply(Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), {next_state, normal_state, StateData}; Now >= Activity#activity.message_time + MinMessageInterval, MessageShaperInterval == 0 -> {RoomShaper, RoomShaperInterval} = shaper:update(StateData#state.room_shaper, Size), RoomQueueEmpty = queue:is_empty(StateData#state.room_queue), if RoomShaperInterval == 0, RoomQueueEmpty -> NewActivity = Activity#activity{message_time = Now, message_shaper = MessageShaper}, StateData1 = store_user_activity(From, NewActivity, StateData), StateData2 = StateData1#state{room_shaper = RoomShaper}, process_groupchat_message(From, Packet, StateData2); true -> StateData1 = if RoomQueueEmpty -> erlang:send_after(RoomShaperInterval, self(), process_room_queue), StateData#state{room_shaper = RoomShaper}; true -> StateData end, NewActivity = Activity#activity{message_time = Now, message_shaper = MessageShaper, message = Packet}, RoomQueue = queue:in({message, From}, StateData#state.room_queue), StateData2 = store_user_activity(From, NewActivity, StateData1), StateData3 = StateData2#state{room_queue = RoomQueue}, {next_state, normal_state, StateData3} end; true -> MessageInterval = (Activity#activity.message_time + MinMessageInterval - Now) div 1000, Interval = lists:max([MessageInterval, MessageShaperInterval]), erlang:send_after(Interval, self(), {process_user_message, From}), NewActivity = Activity#activity{message = Packet, message_shaper = MessageShaper}, StateData1 = store_user_activity(From, NewActivity, StateData), {next_state, normal_state, StateData1} end; <<"error">> -> case is_user_online(From, StateData) of true -> ErrorText = <<"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">>, NewState = expulse_participant(Packet, From, StateData, translate:translate(Lang, ErrorText)), close_room_if_temporary_and_empty(NewState); _ -> {next_state, normal_state, StateData} end; <<"chat">> -> ErrText = <<"It is not allowed to send private messages " "to the conference">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), {next_state, normal_state, StateData}; Type when (Type == <<"">>) or (Type == <<"normal">>) -> IsInvitation = is_invitation(Els), IsVoiceRequest = is_voice_request(Els) and is_visitor(From, StateData), IsVoiceApprovement = is_voice_approvement(Els) and not is_visitor(From, StateData), if IsInvitation -> case catch check_invitation(From, Els, Lang, StateData) of {error, Error} -> Err = jlib:make_error_reply(Packet, Error), ejabberd_router:route(StateData#state.jid, From, Err), {next_state, normal_state, StateData}; IJID -> Config = StateData#state.config, case Config#config.members_only of true -> case get_affiliation(IJID, StateData) of none -> NSD = set_affiliation(IJID, member, StateData), case (NSD#state.config)#config.persistent of true -> mod_muc:store_room(NSD#state.server_host, NSD#state.host, NSD#state.room, make_opts(NSD)); _ -> ok end, {next_state, normal_state, NSD}; _ -> {next_state, normal_state, StateData} end; false -> {next_state, normal_state, StateData} end end; IsVoiceRequest -> NewStateData = case (StateData#state.config)#config.allow_voice_requests of true -> MinInterval = (StateData#state.config)#config.voice_request_min_interval, BareFrom = jid:remove_resource(jid:tolower(From)), NowPriority = -p1_time_compat:system_time(micro_seconds), CleanPriority = NowPriority + MinInterval * 1000000, Times = clean_treap(StateData#state.last_voice_request_time, CleanPriority), case treap:lookup(BareFrom, Times) of error -> Times1 = treap:insert(BareFrom, NowPriority, true, Times), NSD = StateData#state{last_voice_request_time = Times1}, send_voice_request(From, NSD), NSD; {ok, _, _} -> ErrText = <<"Please, wait for a while before sending " "new voice request">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), StateData#state{last_voice_request_time = Times} end; false -> ErrText = <<"Voice requests are disabled in this " "conference">>, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), StateData end, {next_state, normal_state, NewStateData}; IsVoiceApprovement -> NewStateData = case is_moderator(From, StateData) of true -> case extract_jid_from_voice_approvement(Els) of error -> ErrText = <<"Failed to extract JID from your voice " "request approval">>, Err = jlib:make_error_reply(Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), StateData; {ok, TargetJid} -> case is_visitor(TargetJid, StateData) of true -> Reason = <<>>, NSD = set_role(TargetJid, participant, StateData), catch send_new_presence(TargetJid, Reason, NSD, StateData), NSD; _ -> StateData end end; _ -> ErrText = <<"Only moderators can approve voice requests">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), StateData end, {next_state, normal_state, NewStateData}; true -> {next_state, normal_state, StateData} end; _ -> ErrText = <<"Improper message type">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), {next_state, normal_state, StateData} end; _ -> case xml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; _ -> handle_roommessage_from_nonparticipant(Packet, Lang, StateData, From) end, {next_state, normal_state, StateData} end; normal_state({route, From, <<"">>, #xmlel{name = <<"iq">>} = Packet}, StateData) -> case jlib:iq_query_info(Packet) of 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, attrs = Attrs} = 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 -> 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 -> 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}, StateData) -> Activity = get_user_activity(From, StateData), Now = p1_time_compat:system_time(micro_seconds), MinPresenceInterval = trunc(gen_mod:get_module_opt(StateData#state.server_host, mod_muc, min_presence_interval, fun(I) when is_number(I), I>=0 -> I end, 0) * 1000000), if (Now >= Activity#activity.presence_time + MinPresenceInterval) and (Activity#activity.presence == undefined) -> NewActivity = Activity#activity{presence_time = Now}, StateData1 = store_user_activity(From, NewActivity, StateData), process_presence(From, Nick, Packet, StateData1); true -> if Activity#activity.presence == undefined -> Interval = (Activity#activity.presence_time + MinPresenceInterval - Now) div 1000, erlang:send_after(Interval, self(), {process_user_presence, From}); true -> ok end, NewActivity = Activity#activity{presence = {Nick, Packet}}, StateData1 = store_user_activity(From, NewActivity, StateData), {next_state, normal_state, StateData1} end; 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), case decide_fate_message(Type, Packet, From, StateData) of {expulse_sender, Reason} -> ?DEBUG(Reason, []), ErrorText = <<"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">>, NewState = expulse_participant(Packet, From, StateData, translate:translate(Lang, ErrorText)), {next_state, normal_state, NewState}; forget_message -> {next_state, normal_state, StateData}; continue_delivery -> case {(StateData#state.config)#config.allow_private_messages, is_user_online(From, StateData)} of {true, true} -> case Type of <<"groupchat">> -> ErrText = <<"It is not allowed to send private messages " "of type \"groupchat\"">>, Err = jlib:make_error_reply(Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err); _ -> case find_jids_by_nick(ToNick, StateData) of false -> ErrText = <<"Recipient is not in the conference room">>, Err = jlib:make_error_reply(Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err); ToJIDs -> SrcIsVisitor = is_visitor(From, StateData), DstIsModerator = is_moderator(hd(ToJIDs), StateData), PmFromVisitors = (StateData#state.config)#config.allow_private_messages_from_visitors, if SrcIsVisitor == false; PmFromVisitors == anyone; (PmFromVisitors == moderators) and DstIsModerator -> {ok, #user{nick = FromNick}} = (?DICT):find(jid:tolower(From), StateData#state.users), FromNickJID = jid:replace_resource(StateData#state.jid, FromNick), 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 = <<"It is not allowed to send private messages">>, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end end end; {true, false} -> ErrText = <<"Only occupants are allowed to send messages " "to the conference">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err); {false, _} -> ErrText = <<"It is not allowed to send private messages">>, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end, {next_state, normal_state, StateData} end; 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), case {(StateData#state.config)#config.allow_query_users, is_user_online_iq(StanzaId, From, StateData)} of {true, {true, NewId, FromFull}} -> case find_jid_by_nick(ToNick, StateData) of false -> case jlib:iq_query_info(Packet) of reply -> ok; _ -> ErrText = <<"Recipient is not in the conference room">>, Err = jlib:make_error_reply(Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end; ToJID -> {ok, #user{nick = FromNick}} = (?DICT):find(jid:tolower(FromFull), StateData#state.users), {ToJID2, Packet2} = handle_iq_vcard(FromFull, ToJID, StanzaId, NewId, Packet), ejabberd_router:route(jid:replace_resource(StateData#state.jid, FromNick), ToJID2, Packet2) end; {_, {false, _, _}} -> case jlib:iq_query_info(Packet) of reply -> ok; _ -> ErrText = <<"Only occupants are allowed to send queries " "to the conference">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end; _ -> case jlib:iq_query_info(Packet) of reply -> ok; _ -> ErrText = <<"Queries to the conference members are " "not allowed in this room">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end end, {next_state, normal_state, StateData}; normal_state(_Event, StateData) -> {next_state, normal_state, StateData}. handle_event({service_message, Msg}, _StateName, StateData) -> MessagePkt = #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Msg}]}]}, send_multiple( StateData#state.jid, StateData#state.server_host, StateData#state.users, MessagePkt), NSD = add_message_to_history(<<"">>, StateData#state.jid, MessagePkt, StateData), {next_state, normal_state, NSD}; handle_event({destroy, Reason}, _StateName, StateData) -> {result, [], stop} = destroy_room(#xmlel{name = <<"destroy">>, attrs = [{<<"xmlns">>, ?NS_MUC_OWNER}], children = case Reason of none -> []; _Else -> [#xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, Reason}]}] end}, StateData), ?INFO_MSG("Destroyed MUC room ~s with reason: ~p", [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", [jid:to_string(StateData#state.jid)]), handle_event({destroy, none}, StateName, StateData); handle_event({set_affiliations, Affiliations}, StateName, StateData) -> {next_state, StateName, StateData#state{affiliations = Affiliations}}; handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. 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, StateData}; handle_sync_event(get_state, _From, StateName, StateData) -> {reply, {ok, StateData}, StateName, StateData}; handle_sync_event({change_config, Config}, _From, StateName, StateData) -> {result, [], NSD} = change_config(Config, StateData), {reply, {ok, NSD#state.config}, StateName, NSD}; handle_sync_event({change_state, NewStateData}, _From, StateName, _StateData) -> {reply, {ok, NewStateData}, StateName, NewStateData}; handle_sync_event({process_item_change, Item, UJID}, _From, StateName, StateData) -> NSD = process_item_change(Item, StateData, UJID), {reply, {ok, NSD}, StateName, NSD}; handle_sync_event(_Event, _From, StateName, StateData) -> Reply = ok, {reply, Reply, StateName, StateData}. code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. 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), StateData1 = StateData#state{room_queue = RoomQueue}, if RoomQueueEmpty -> StateData2 = prepare_room_queue(StateData1), {next_state, normal_state, StateData2}; true -> {next_state, normal_state, StateData1} end; handle_info({process_user_message, From}, normal_state = _StateName, StateData) -> RoomQueueEmpty = queue:is_empty(StateData#state.room_queue), RoomQueue = queue:in({message, From}, StateData#state.room_queue), StateData1 = StateData#state{room_queue = RoomQueue}, if RoomQueueEmpty -> StateData2 = prepare_room_queue(StateData1), {next_state, normal_state, StateData2}; true -> {next_state, normal_state, StateData1} end; handle_info(process_room_queue, normal_state = StateName, StateData) -> case queue:out(StateData#state.room_queue) of {{value, {message, From}}, RoomQueue} -> Activity = get_user_activity(From, StateData), Packet = Activity#activity.message, NewActivity = Activity#activity{message = undefined}, StateData1 = store_user_activity(From, NewActivity, StateData), StateData2 = StateData1#state{room_queue = RoomQueue}, StateData3 = prepare_room_queue(StateData2), process_groupchat_message(From, Packet, StateData3); {{value, {presence, From}}, RoomQueue} -> Activity = get_user_activity(From, StateData), {Nick, Packet} = Activity#activity.presence, NewActivity = Activity#activity{presence = undefined}, StateData1 = store_user_activity(From, NewActivity, StateData), StateData2 = StateData1#state{room_queue = RoomQueue}, StateData3 = prepare_room_queue(StateData2), process_presence(From, Nick, Packet, StateData3); {empty, _} -> {next_state, StateName, StateData} end; handle_info({captcha_succeed, From}, normal_state, StateData) -> NewState = case (?DICT):find(From, StateData#state.robots) of {ok, {Nick, Packet}} -> Robots = (?DICT):store(From, passed, StateData#state.robots), add_new_user(From, Nick, Packet, StateData#state{robots = Robots}); _ -> StateData end, {next_state, normal_state, NewState}; handle_info({captcha_failed, From}, normal_state, StateData) -> NewState = case (?DICT):find(From, StateData#state.robots) of {ok, {Nick, Packet}} -> Robots = (?DICT):erase(From, StateData#state.robots), Err = jlib:make_error_reply(Packet, ?ERR_NOT_AUTHORIZED), ejabberd_router:route % TODO: s/Nick/""/ (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData#state{robots = Robots}; _ -> StateData end, {next_state, normal_state, NewState}; handle_info(shutdown, _StateName, StateData) -> {stop, shutdown, StateData}; handle_info(_Info, StateName, StateData) -> {next_state, StateName, StateData}. terminate(Reason, _StateName, StateData) -> ?INFO_MSG("Stopping MUC room ~s@~s", [StateData#state.room, StateData#state.host]), ReasonT = case Reason of shutdown -> <<"You are being removed from the room " "because of a system shutdown">>; _ -> <<"Room terminates">> end, ItemAttrs = [{<<"affiliation">>, <<"none">>}, {<<"role">>, <<"none">>}], ReasonEl = #xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, ReasonT}]}, Packet = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs, children = [ReasonEl]}, #xmlel{name = <<"status">>, attrs = [{<<"code">>, <<"332">>}], children = []}]}]}, (?DICT):fold(fun (LJID, Info, _) -> Nick = Info#user.nick, case Reason of shutdown -> ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet); _ -> ok end, tab_remove_online_user(LJID, StateData) end, [], StateData#state.users), add_to_log(room_existence, stopped, StateData), mod_muc:room_destroyed(StateData#state.host, StateData#state.room, self(), StateData#state.server_host), ok. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- route(Pid, From, ToNick, Packet) -> gen_fsm:send_event(Pid, {route, From, ToNick, Packet}). process_groupchat_message(From, #xmlel{name = <<"message">>, attrs = Attrs} = Packet, StateData) -> Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), case is_user_online(From, StateData) orelse is_user_allowed_message_nonparticipant(From, StateData) of true -> {FromNick, Role} = get_participant_data(From, StateData), if (Role == moderator) or (Role == participant) or ((StateData#state.config)#config.moderated == false) -> {NewStateData1, IsAllowed} = case check_subject(Packet) of false -> {StateData, true}; Subject -> case can_change_subject(Role, StateData) of true -> NSD = StateData#state{subject = Subject, subject_author = FromNick}, case (NSD#state.config)#config.persistent of true -> mod_muc:store_room(NSD#state.server_host, NSD#state.host, NSD#state.room, make_opts(NSD)); _ -> ok end, {NSD, true}; _ -> {StateData, false} end end, case IsAllowed of true -> case ejabberd_hooks:run_fold(muc_filter_message, StateData#state.server_host, Packet, [StateData, StateData#state.jid, From, FromNick]) of drop -> {next_state, normal_state, StateData}; NewPacket1 -> NewPacket = xml:remove_subtags(NewPacket1, <<"nick">>, {<<"xmlns">>, ?NS_NICK}), send_multiple(jid:replace_resource(StateData#state.jid, FromNick), StateData#state.server_host, StateData#state.users, NewPacket), NewStateData2 = case has_body_or_subject(NewPacket) of true -> add_message_to_history(FromNick, From, NewPacket, NewStateData1); false -> NewStateData1 end, {next_state, normal_state, NewStateData2} end; _ -> Err = case (StateData#state.config)#config.allow_change_subj of true -> ?ERRT_FORBIDDEN(Lang, <<"Only moderators and participants are " "allowed to change the subject in this " "room">>); _ -> ?ERRT_FORBIDDEN(Lang, <<"Only moderators are allowed to change " "the subject in this room">>) end, ejabberd_router:route(StateData#state.jid, From, jlib:make_error_reply(Packet, Err)), {next_state, normal_state, StateData} end; true -> ErrText = <<"Visitors are not allowed to send messages " "to all occupants">>, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), {next_state, normal_state, StateData} end; false -> ErrText = <<"Only occupants are allowed to send messages " "to the conference">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route(StateData#state.jid, From, Err), {next_state, normal_state, StateData} end. %% @doc Check if this non participant can send message to room. %% %% XEP-0045 v1.23: %% 7.9 Sending a Message to All Occupants %% an implementation MAY allow users with certain privileges %% (e.g., a room owner, room admin, or service-level admin) %% to send messages to the room even if those users are not occupants. is_user_allowed_message_nonparticipant(JID, StateData) -> case get_service_affiliation(JID, StateData) of owner -> true; _ -> false end. %% @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(jid:tolower(From), StateData#state.users) of {ok, #user{nick = FromNick, role = Role}} -> {FromNick, Role}; error -> {<<"">>, moderator} end. process_presence(From, Nick, #xmlel{name = <<"presence">>, attrs = Attrs0} = Packet0, StateData) -> 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(<<"type">>, 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, StateData) 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 = <<"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">>, 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(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(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(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, StateData), 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 andalso (?DICT):to_list(StateData1#state.users) == [] of true -> ?INFO_MSG("Destroyed MUC room ~s because it's temporary " "and empty", [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 = 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. is_occupant_or_admin(JID, StateData) -> FAffiliation = get_affiliation(JID, StateData), FRole = get_role(JID, StateData), case FRole /= none orelse FAffiliation == member orelse FAffiliation == admin orelse FAffiliation == owner of true -> true; _ -> false end. %%% %%% Handle IQ queries of vCard %%% is_user_online_iq(StanzaId, JID, StateData) when JID#jid.lresource /= <<"">> -> {is_user_online(JID, StateData), StanzaId, JID}; is_user_online_iq(StanzaId, JID, StateData) when JID#jid.lresource == <<"">> -> try stanzaid_unpack(StanzaId) of {OriginalId, Resource} -> JIDWithResource = jid:replace_resource(JID, Resource), {is_user_online(JIDWithResource, StateData), OriginalId, JIDWithResource} catch _:_ -> {is_user_online(JID, StateData), StanzaId, JID} end. handle_iq_vcard(FromFull, ToJID, StanzaId, NewId, Packet) -> ToBareJID = jid:remove_resource(ToJID), IQ = jlib:iq_query_info(Packet), handle_iq_vcard2(FromFull, ToJID, ToBareJID, StanzaId, NewId, IQ, Packet). handle_iq_vcard2(_FromFull, ToJID, ToBareJID, StanzaId, _NewId, #iq{type = get, xmlns = ?NS_VCARD}, Packet) when ToBareJID /= ToJID -> {ToBareJID, change_stanzaid(StanzaId, ToJID, Packet)}; handle_iq_vcard2(_FromFull, ToJID, _ToBareJID, _StanzaId, NewId, _IQ, Packet) -> {ToJID, change_stanzaid(NewId, Packet)}. stanzaid_pack(OriginalId, Resource) -> <<"berd", (jlib:encode_base64(<<"ejab\000", OriginalId/binary, "\000", Resource/binary>>))/binary>>. stanzaid_unpack(<<"berd", StanzaIdBase64/binary>>) -> StanzaId = jlib:decode_base64(StanzaIdBase64), [<<"ejab">>, OriginalId, Resource] = str:tokens(StanzaId, <<"\000">>), {OriginalId, Resource}. change_stanzaid(NewId, Packet) -> #xmlel{name = Name, attrs = Attrs, children = Els} = jlib:remove_attr(<<"id">>, Packet), #xmlel{name = Name, attrs = [{<<"id">>, NewId} | Attrs], children = Els}. change_stanzaid(PreviousId, ToJID, Packet) -> NewId = stanzaid_pack(PreviousId, ToJID#jid.lresource), change_stanzaid(NewId, Packet). %%% %%% role_to_list(Role) -> case Role of moderator -> <<"moderator">>; participant -> <<"participant">>; visitor -> <<"visitor">>; none -> <<"none">> end. affiliation_to_list(Affiliation) -> case Affiliation of owner -> <<"owner">>; admin -> <<"admin">>; member -> <<"member">>; outcast -> <<"outcast">>; none -> <<"none">> end. list_to_role(Role) -> case Role of <<"moderator">> -> moderator; <<"participant">> -> participant; <<"visitor">> -> visitor; <<"none">> -> none end. list_to_affiliation(Affiliation) -> case Affiliation of <<"owner">> -> owner; <<"admin">> -> admin; <<"member">> -> member; <<"outcast">> -> outcast; <<"none">> -> none end. %% Decide the fate of the message and its sender %% Returns: continue_delivery | forget_message | {expulse_sender, Reason} decide_fate_message(<<"error">>, Packet, From, StateData) -> PD = case check_error_kick(Packet) of %% If this is an error stanza and its condition matches a criteria true -> Reason = io_lib:format("This participant is considered a ghost " "and is expulsed: ~s", [jid:to_string(From)]), {expulse_sender, Reason}; false -> continue_delivery end, case PD of {expulse_sender, R} -> case is_user_online(From, StateData) of true -> {expulse_sender, R}; false -> forget_message end; Other -> Other end; decide_fate_message(_, _, _, _) -> continue_delivery. %% Check if the elements of this error stanza indicate %% that the sender is a dead participant. %% If so, return true to kick the participant. check_error_kick(Packet) -> case get_error_condition(Packet) of <<"gone">> -> true; <<"internal-server-error">> -> true; <<"item-not-found">> -> true; <<"jid-malformed">> -> true; <<"recipient-unavailable">> -> true; <<"redirect">> -> true; <<"remote-server-not-found">> -> true; <<"remote-server-timeout">> -> true; <<"service-unavailable">> -> true; _ -> false end. get_error_condition(Packet) -> case catch get_error_condition2(Packet) of {condition, ErrorCondition} -> ErrorCondition; {'EXIT', _} -> <<"badformed error stanza">> end. get_error_condition2(Packet) -> #xmlel{children = EEls} = xml:get_subtag(Packet, <<"error">>), [Condition] = [Name || #xmlel{name = Name, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = []} <- EEls], {condition, Condition}. make_reason(Packet, From, StateData, Reason1) -> {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])). expulse_participant(Packet, From, StateData, Reason1) -> Reason2 = make_reason(Packet, From, StateData, Reason1), NewState = add_user_presence_un(From, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"status">>, attrs = [], children = [{xmlcdata, Reason2}]}]}, StateData), send_new_presence(From, NewState, StateData), remove_online_user(From, NewState). set_affiliation(JID, Affiliation, StateData) -> set_affiliation(JID, Affiliation, StateData, <<"">>). set_affiliation(JID, Affiliation, StateData, Reason) -> LJID = jid:remove_resource(jid:tolower(JID)), Affiliations = case Affiliation of none -> (?DICT):erase(LJID, StateData#state.affiliations); _ -> (?DICT):store(LJID, {Affiliation, Reason}, StateData#state.affiliations) end, StateData#state{affiliations = Affiliations}. get_affiliation(JID, StateData) -> {_AccessRoute, _AccessCreate, AccessAdmin, _AccessPersistent} = StateData#state.access, Res = case acl:match_rule(StateData#state.server_host, AccessAdmin, JID) of allow -> owner; _ -> LJID = jid:tolower(JID), case (?DICT):find(LJID, StateData#state.affiliations) of {ok, Affiliation} -> Affiliation; _ -> LJID1 = jid:remove_resource(LJID), case (?DICT):find(LJID1, StateData#state.affiliations) of {ok, Affiliation} -> Affiliation; _ -> LJID2 = setelement(1, LJID, <<"">>), case (?DICT):find(LJID2, StateData#state.affiliations) of {ok, Affiliation} -> Affiliation; _ -> LJID3 = jid:remove_resource(LJID2), case (?DICT):find(LJID3, StateData#state.affiliations) of {ok, Affiliation} -> Affiliation; _ -> none end end end end end, case Res of {A, _Reason} -> A; _ -> Res end. get_service_affiliation(JID, StateData) -> {_AccessRoute, _AccessCreate, AccessAdmin, _AccessPersistent} = StateData#state.access, case acl:match_rule(StateData#state.server_host, AccessAdmin, JID) of allow -> owner; _ -> none end. set_role(JID, Role, StateData) -> LJID = jid:tolower(JID), LJIDs = case LJID of {U, S, <<"">>} -> (?DICT):fold(fun (J, _, Js) -> case J of {U, S, _} -> [J | Js]; _ -> Js end end, [], StateData#state.users); _ -> case (?DICT):is_key(LJID, StateData#state.users) of true -> [LJID]; _ -> [] end end, {Users, Nicks} = case Role of none -> lists:foldl(fun (J, {Us, Ns}) -> NewNs = case (?DICT):find(J, Us) of {ok, #user{nick = Nick}} -> (?DICT):erase(Nick, Ns); _ -> Ns end, {(?DICT):erase(J, Us), NewNs} end, {StateData#state.users, StateData#state.nicks}, LJIDs); _ -> {lists:foldl(fun (J, Us) -> {ok, User} = (?DICT):find(J, Us), (?DICT):store(J, User#user{role = Role}, Us) end, StateData#state.users, LJIDs), StateData#state.nicks} end, StateData#state{users = Users, nicks = Nicks}. get_role(JID, StateData) -> LJID = jid:tolower(JID), case (?DICT):find(LJID, StateData#state.users) of {ok, #user{role = Role}} -> Role; _ -> none end. get_default_role(Affiliation, StateData) -> case Affiliation of owner -> moderator; admin -> moderator; member -> participant; outcast -> none; none -> case (StateData#state.config)#config.members_only of true -> none; _ -> case (StateData#state.config)#config.members_by_default of true -> participant; _ -> visitor end end end. is_visitor(Jid, StateData) -> get_role(Jid, StateData) =:= visitor. is_moderator(Jid, StateData) -> get_role(Jid, StateData) =:= moderator. get_max_users(StateData) -> MaxUsers = (StateData#state.config)#config.max_users, ServiceMaxUsers = get_service_max_users(StateData), if MaxUsers =< ServiceMaxUsers -> MaxUsers; true -> ServiceMaxUsers end. get_service_max_users(StateData) -> gen_mod:get_module_opt(StateData#state.server_host, mod_muc, max_users, fun(I) when is_integer(I), I>0 -> I end, ?MAX_USERS_DEFAULT). get_max_users_admin_threshold(StateData) -> gen_mod:get_module_opt(StateData#state.server_host, mod_muc, max_users_admin_threshold, fun(I) when is_integer(I), I>0 -> I end, 5). get_user_activity(JID, StateData) -> case treap:lookup(jid:tolower(JID), StateData#state.activity) of {ok, _P, A} -> A; error -> MessageShaper = shaper:new(gen_mod:get_module_opt(StateData#state.server_host, mod_muc, user_message_shaper, fun(A) when is_atom(A) -> A end, none)), PresenceShaper = shaper:new(gen_mod:get_module_opt(StateData#state.server_host, mod_muc, user_presence_shaper, fun(A) when is_atom(A) -> A end, none)), #activity{message_shaper = MessageShaper, presence_shaper = PresenceShaper} end. store_user_activity(JID, UserActivity, StateData) -> MinMessageInterval = trunc(gen_mod:get_module_opt(StateData#state.server_host, mod_muc, min_message_interval, fun(I) when is_number(I), I>=0 -> I end, 0) * 1000), MinPresenceInterval = trunc(gen_mod:get_module_opt(StateData#state.server_host, mod_muc, min_presence_interval, fun(I) when is_number(I), I>=0 -> I end, 0) * 1000), Key = jid:tolower(JID), Now = p1_time_compat:system_time(micro_seconds), Activity1 = clean_treap(StateData#state.activity, {1, -Now}), Activity = case treap:lookup(Key, Activity1) of {ok, _P, _A} -> treap:delete(Key, Activity1); error -> Activity1 end, StateData1 = case MinMessageInterval == 0 andalso MinPresenceInterval == 0 andalso UserActivity#activity.message_shaper == none andalso UserActivity#activity.presence_shaper == none andalso UserActivity#activity.message == undefined andalso UserActivity#activity.presence == undefined of true -> StateData#state{activity = Activity}; false -> case UserActivity#activity.message == undefined andalso UserActivity#activity.presence == undefined of true -> {_, MessageShaperInterval} = shaper:update(UserActivity#activity.message_shaper, 100000), {_, PresenceShaperInterval} = shaper:update(UserActivity#activity.presence_shaper, 100000), Delay = lists:max([MessageShaperInterval, PresenceShaperInterval, MinMessageInterval, MinPresenceInterval]) * 1000, Priority = {1, -(Now + Delay)}, StateData#state{activity = treap:insert(Key, Priority, UserActivity, Activity)}; false -> Priority = {0, 0}, StateData#state{activity = treap:insert(Key, Priority, UserActivity, Activity)} end end, StateData1. clean_treap(Treap, CleanPriority) -> case treap:is_empty(Treap) of true -> Treap; false -> {_Key, Priority, _Value} = treap:get_root(Treap), if Priority > CleanPriority -> clean_treap(treap:delete_root(Treap), CleanPriority); true -> Treap end end. prepare_room_queue(StateData) -> case queue:out(StateData#state.room_queue) of {{value, {message, From}}, _RoomQueue} -> Activity = get_user_activity(From, StateData), Packet = Activity#activity.message, Size = element_size(Packet), {RoomShaper, RoomShaperInterval} = shaper:update(StateData#state.room_shaper, Size), erlang:send_after(RoomShaperInterval, self(), process_room_queue), StateData#state{room_shaper = RoomShaper}; {{value, {presence, From}}, _RoomQueue} -> Activity = get_user_activity(From, StateData), {_Nick, Packet} = Activity#activity.presence, Size = element_size(Packet), {RoomShaper, RoomShaperInterval} = shaper:update(StateData#state.room_shaper, Size), erlang:send_after(RoomShaperInterval, self(), process_room_queue), StateData#state{room_shaper = RoomShaper}; {empty, _} -> StateData end. add_online_user(JID, Nick, Role, StateData) -> LJID = jid:tolower(JID), Users = (?DICT):store(LJID, #user{jid = JID, nick = Nick, role = Role}, StateData#state.users), add_to_log(join, Nick, StateData), Nicks = (?DICT):update(Nick, fun (Entry) -> case lists:member(LJID, Entry) of true -> Entry; false -> [LJID | Entry] end end, [LJID], StateData#state.nicks), tab_add_online_user(JID, StateData), StateData#state{users = Users, nicks = Nicks}. remove_online_user(JID, StateData) -> remove_online_user(JID, StateData, <<"">>). remove_online_user(JID, StateData, Reason) -> LJID = jid:tolower(JID), {ok, #user{nick = Nick}} = (?DICT):find(LJID, StateData#state.users), add_to_log(leave, {Nick, Reason}, StateData), tab_remove_online_user(JID, StateData), Users = (?DICT):erase(LJID, StateData#state.users), Nicks = case (?DICT):find(Nick, StateData#state.nicks) of {ok, [LJID]} -> (?DICT):erase(Nick, StateData#state.nicks); {ok, U} -> (?DICT):store(Nick, U -- [LJID], StateData#state.nicks); error -> StateData#state.nicks end, StateData#state{users = Users, nicks = Nicks}. filter_presence(#xmlel{name = <<"presence">>, attrs = Attrs, children = Els}) -> FEls = lists:filter(fun (El) -> case El of {xmlcdata, _} -> false; #xmlel{attrs = Attrs1} -> XMLNS = xml:get_attr_s(<<"xmlns">>, Attrs1), NS_MUC = ?NS_MUC, Size = byte_size(NS_MUC), case XMLNS of <> -> false; _ -> true end end end, Els), #xmlel{name = <<"presence">>, attrs = Attrs, children = FEls}. strip_status(#xmlel{name = <<"presence">>, attrs = Attrs, children = Els}) -> FEls = lists:filter(fun (#xmlel{name = <<"status">>}) -> false; (_) -> true end, Els), #xmlel{name = <<"presence">>, attrs = Attrs, children = FEls}. add_user_presence(JID, Presence, StateData) -> LJID = jid:tolower(JID), FPresence = filter_presence(Presence), Users = (?DICT):update(LJID, fun (#user{} = User) -> User#user{last_presence = FPresence} end, StateData#state.users), StateData#state{users = Users}. add_user_presence_un(JID, Presence, StateData) -> LJID = jid:tolower(JID), FPresence = filter_presence(Presence), Users = (?DICT):update(LJID, fun (#user{} = User) -> User#user{last_presence = FPresence, role = none} end, StateData#state.users), StateData#state{users = Users}. %% Find and return a list of the full JIDs of the users of Nick. %% Return jid record. find_jids_by_nick(Nick, StateData) -> case (?DICT):find(Nick, StateData#state.nicks) of {ok, [User]} -> [jid:make(User)]; {ok, Users} -> [jid:make(LJID) || LJID <- Users]; error -> false end. %% Find and return the full JID of the user of Nick with %% highest-priority presence. Return jid record. find_jid_by_nick(Nick, StateData) -> case (?DICT):find(Nick, StateData#state.nicks) of {ok, [User]} -> jid:make(User); {ok, [FirstUser | Users]} -> #user{last_presence = FirstPresence} = (?DICT):fetch(FirstUser, StateData#state.users), {LJID, _} = lists:foldl(fun (Compare, {HighestUser, HighestPresence}) -> #user{last_presence = P1} = (?DICT):fetch(Compare, StateData#state.users), case higher_presence(P1, HighestPresence) of true -> {Compare, P1}; false -> {HighestUser, HighestPresence} end end, {FirstUser, FirstPresence}, Users), jid:make(LJID); error -> false end. higher_presence(Pres1, Pres2) -> Pri1 = get_priority_from_presence(Pres1), Pri2 = get_priority_from_presence(Pres2), Pri1 > Pri2. get_priority_from_presence(PresencePacket) -> case xml:get_subtag(PresencePacket, <<"priority">>) of false -> 0; SubEl -> case catch jlib:binary_to_integer(xml:get_tag_cdata(SubEl)) of P when is_integer(P) -> P; _ -> 0 end end. find_nick_by_jid(Jid, StateData) -> [{_, #user{nick = Nick}}] = lists:filter(fun ({_, #user{jid = FJid}}) -> FJid == Jid end, (?DICT):to_list(StateData#state.users)), Nick. is_nick_change(JID, Nick, StateData) -> LJID = jid:tolower(JID), case Nick of <<"">> -> false; _ -> {ok, #user{nick = OldNick}} = (?DICT):find(LJID, StateData#state.users), Nick /= OldNick end. nick_collision(User, Nick, StateData) -> UserOfNick = find_jid_by_nick(Nick, StateData), (UserOfNick /= false andalso jid:remove_resource(jid:tolower(UserOfNick)) /= jid:remove_resource(jid:tolower(User))). add_new_user(From, Nick, #xmlel{attrs = Attrs, children = Els} = Packet, StateData) -> Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), MaxUsers = get_max_users(StateData), MaxAdminUsers = MaxUsers + get_max_users_admin_threshold(StateData), NUsers = dict:fold(fun (_, _, Acc) -> Acc + 1 end, 0, StateData#state.users), Affiliation = get_affiliation(From, StateData), ServiceAffiliation = get_service_affiliation(From, StateData), NConferences = tab_count_user(From), MaxConferences = gen_mod:get_module_opt(StateData#state.server_host, mod_muc, max_user_conferences, fun(I) when is_integer(I), I>0 -> I end, 10), Collision = nick_collision(From, Nick, StateData), case {(ServiceAffiliation == owner orelse (Affiliation == admin orelse Affiliation == owner) andalso NUsers < MaxAdminUsers orelse NUsers < MaxUsers) andalso NConferences < MaxConferences, Collision, mod_muc:can_use_nick(StateData#state.server_host, StateData#state.host, From, Nick), get_default_role(Affiliation, StateData)} of {false, _, _, _} -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route % TODO: s/Nick/""/ (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; {_, _, _, none} -> Err = jlib:make_error_reply(Packet, case Affiliation of outcast -> ErrText = <<"You have been banned from this room">>, ?ERRT_FORBIDDEN(Lang, ErrText); _ -> ErrText = <<"Membership is required to enter this room">>, ?ERRT_REGISTRATION_REQUIRED(Lang, ErrText) end), ejabberd_router:route % TODO: s/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(jid:replace_resource(StateData#state.jid, 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(jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; {_, _, _, Role} -> case check_password(ServiceAffiliation, Affiliation, Els, From, StateData) of true -> NewState = add_user_presence(From, Packet, add_online_user(From, Nick, Role, StateData)), send_existing_presences(From, NewState), send_new_presence(From, NewState, StateData), Shift = count_stanza_shift(Nick, Els, NewState), case send_history(From, Shift, NewState) of true -> ok; _ -> send_subject(From, StateData) end, case NewState#state.just_created of true -> NewState#state{just_created = false}; false -> Robots = (?DICT):erase(From, StateData#state.robots), NewState#state{robots = Robots} end; nopass -> ErrText = <<"A password is required to enter this room">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_AUTHORIZED(Lang, ErrText)), ejabberd_router:route % TODO: s/Nick/""/ (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; captcha_required -> SID = xml:get_attr_s(<<"id">>, Attrs), RoomJID = StateData#state.jid, To = jid:replace_resource(RoomJID, Nick), Limiter = {From#jid.luser, From#jid.lserver}, case ejabberd_captcha:create_captcha(SID, RoomJID, To, Lang, Limiter, From) of {ok, ID, CaptchaEls} -> MsgPkt = #xmlel{name = <<"message">>, attrs = [{<<"id">>, ID}], children = CaptchaEls}, Robots = (?DICT):store(From, {Nick, Packet}, StateData#state.robots), ejabberd_router:route(RoomJID, From, MsgPkt), StateData#state{robots = Robots}; {error, limit} -> ErrText = <<"Too many CAPTCHA requests">>, Err = jlib:make_error_reply(Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)), ejabberd_router:route % TODO: s/Nick/""/ (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; _ -> ErrText = <<"Unable to generate a CAPTCHA">>, Err = jlib:make_error_reply(Packet, ?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)), ejabberd_router:route % TODO: s/Nick/""/ (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData end; _ -> ErrText = <<"Incorrect password">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_AUTHORIZED(Lang, ErrText)), ejabberd_router:route % TODO: s/Nick/""/ (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData end end. check_password(owner, _Affiliation, _Els, _From, _StateData) -> %% Don't check pass if user is owner in MUC service (access_admin option) true; check_password(_ServiceAffiliation, Affiliation, Els, From, StateData) -> case (StateData#state.config)#config.password_protected of false -> check_captcha(Affiliation, From, StateData); true -> Pass = extract_password(Els), case Pass of false -> nopass; _ -> case (StateData#state.config)#config.password of Pass -> true; _ -> false end end end. check_captcha(Affiliation, From, StateData) -> case (StateData#state.config)#config.captcha_protected andalso ejabberd_captcha:is_feature_available() of true when Affiliation == none -> case (?DICT):find(From, StateData#state.robots) of {ok, passed} -> true; _ -> WList = (StateData#state.config)#config.captcha_whitelist, #jid{luser = U, lserver = S, lresource = R} = From, case (?SETS):is_element({U, S, R}, WList) of true -> true; false -> case (?SETS):is_element({U, S, <<"">>}, WList) of true -> true; false -> case (?SETS):is_element({<<"">>, S, <<"">>}, WList) of true -> true; false -> captcha_required end end end end; _ -> true end. extract_password([]) -> false; extract_password([#xmlel{attrs = Attrs} = El | Els]) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC -> case xml:get_subtag(El, <<"password">>) of false -> false; SubEl -> xml:get_tag_cdata(SubEl) end; _ -> extract_password(Els) end; extract_password([_ | Els]) -> extract_password(Els). count_stanza_shift(Nick, Els, StateData) -> HL = lqueue_to_list(StateData#state.history), Since = extract_history(Els, <<"since">>), Shift0 = case Since of false -> 0; _ -> Sin = calendar:datetime_to_gregorian_seconds(Since), count_seconds_shift(Sin, HL) end, Seconds = extract_history(Els, <<"seconds">>), Shift1 = case Seconds of false -> 0; _ -> Sec = calendar:datetime_to_gregorian_seconds(calendar:universal_time()) - Seconds, count_seconds_shift(Sec, HL) end, MaxStanzas = extract_history(Els, <<"maxstanzas">>), Shift2 = case MaxStanzas of false -> 0; _ -> count_maxstanzas_shift(MaxStanzas, HL) end, MaxChars = extract_history(Els, <<"maxchars">>), Shift3 = case MaxChars of false -> 0; _ -> count_maxchars_shift(Nick, MaxChars, HL) end, lists:max([Shift0, Shift1, Shift2, Shift3]). count_seconds_shift(Seconds, HistoryList) -> lists:sum(lists:map(fun ({_Nick, _Packet, _HaveSubject, TimeStamp, _Size}) -> T = calendar:datetime_to_gregorian_seconds(TimeStamp), if T < Seconds -> 1; true -> 0 end end, HistoryList)). count_maxstanzas_shift(MaxStanzas, HistoryList) -> S = length(HistoryList) - MaxStanzas, if S =< 0 -> 0; true -> S end. count_maxchars_shift(Nick, MaxSize, HistoryList) -> NLen = byte_size(Nick) + 1, Sizes = lists:map(fun ({_Nick, _Packet, _HaveSubject, _TimeStamp, Size}) -> Size + NLen end, HistoryList), calc_shift(MaxSize, Sizes). calc_shift(MaxSize, Sizes) -> Total = lists:sum(Sizes), calc_shift(MaxSize, Total, 0, Sizes). calc_shift(_MaxSize, _Size, Shift, []) -> Shift; calc_shift(MaxSize, Size, Shift, [S | TSizes]) -> if MaxSize >= Size -> Shift; true -> calc_shift(MaxSize, Size - S, Shift + 1, TSizes) end. extract_history([], _Type) -> false; extract_history([#xmlel{attrs = Attrs} = El | Els], Type) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC -> AttrVal = xml:get_path_s(El, [{elem, <<"history">>}, {attr, Type}]), case Type of <<"since">> -> case jlib:datetime_string_to_timestamp(AttrVal) of undefined -> false; TS -> calendar:now_to_universal_time(TS) end; _ -> case catch jlib:binary_to_integer(AttrVal) of IntVal when is_integer(IntVal) and (IntVal >= 0) -> IntVal; _ -> false end end; _ -> extract_history(Els, Type) end; 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. presence_broadcast_allowed(JID, StateData) -> Role = get_role(JID, StateData), lists:member(Role, (StateData#state.config)#config.presence_broadcast). send_update_presence(JID, StateData, OldStateData) -> send_update_presence(JID, <<"">>, StateData, OldStateData). send_update_presence(JID, Reason, StateData, OldStateData) -> case is_room_overcrowded(StateData) of true -> ok; false -> send_update_presence1(JID, Reason, StateData, OldStateData) end. send_update_presence1(JID, Reason, StateData, OldStateData) -> LJID = jid:tolower(JID), LJIDs = case LJID of {U, S, <<"">>} -> (?DICT):fold(fun (J, _, Js) -> case J of {U, S, _} -> [J | Js]; _ -> Js end end, [], StateData#state.users); _ -> case (?DICT):is_key(LJID, StateData#state.users) of true -> [LJID]; _ -> [] end end, lists:foreach(fun (J) -> send_new_presence(J, Reason, StateData, OldStateData) end, LJIDs). send_new_presence(NJID, StateData, OldStateData) -> send_new_presence(NJID, <<"">>, StateData, OldStateData). send_new_presence(NJID, Reason, StateData, OldStateData) -> case is_room_overcrowded(StateData) of true -> ok; false -> send_new_presence1(NJID, Reason, StateData, OldStateData) end. 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 = 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), 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 of true -> [{<<"jid">>, jid:to_string(RealJID)}, {<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}]; _ -> [{<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}] end, ItemEls = case Reason of <<"">> -> []; _ -> [#xmlel{name = <<"reason">>, attrs = [], 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 of true -> [#xmlel{name = <<"status">>, attrs = [{<<"code">>, <<"170">>}], children = []} | Status3]; false -> Status3 end, Packet = xml:append_subtags(Presence, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs, children = ItemEls} | Status4]}]), ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet) end, UserList). 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 = 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(jid:tolower(LJID), StateData#state.users), PresenceBroadcast = lists:member( FromRole, (StateData#state.config)#config.presence_broadcast), case {RealToJID, PresenceBroadcast} of {FromJID, _} -> ok; {_, false} -> ok; _ -> FromAffiliation = get_affiliation(LJID, StateData), ItemAttrs = case Role == moderator orelse (StateData#state.config)#config.anonymous == false of true -> [{<<"jid">>, jid:to_string(FromJID)}, {<<"affiliation">>, affiliation_to_list(FromAffiliation)}, {<<"role">>, role_to_list(FromRole)}]; _ -> [{<<"affiliation">>, affiliation_to_list(FromAffiliation)}, {<<"role">>, role_to_list(FromRole)}] end, Packet = xml:append_subtags(Presence, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs, children = []}]}]), ejabberd_router:route(jid:replace_resource(StateData#state.jid, FromNick), RealToJID, Packet) end end, (?DICT):to_list(StateData#state.nicks)). change_nick(JID, Nick, StateData) -> LJID = jid:tolower(JID), {ok, #user{nick = OldNick}} = (?DICT):find(LJID, StateData#state.users), Users = (?DICT):update(LJID, fun (#user{} = User) -> User#user{nick = Nick} end, StateData#state.users), OldNickUsers = (?DICT):fetch(OldNick, StateData#state.nicks), NewNickUsers = case (?DICT):find(Nick, StateData#state.nicks) of {ok, U} -> U; error -> [] end, SendOldUnavailable = length(OldNickUsers) == 1, SendNewAvailable = SendOldUnavailable orelse NewNickUsers == [], Nicks = case OldNickUsers of [LJID] -> (?DICT):store(Nick, [LJID | NewNickUsers], (?DICT):erase(OldNick, StateData#state.nicks)); [_ | _] -> (?DICT):store(Nick, [LJID | NewNickUsers], (?DICT):store(OldNick, OldNickUsers -- [LJID], StateData#state.nicks)) end, NewStateData = StateData#state{users = Users, nicks = Nicks}, 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. send_nick_changing(JID, OldNick, StateData, SendOldUnavailable, SendNewAvailable) -> {ok, #user{jid = RealJID, nick = Nick, role = Role, last_presence = Presence}} = (?DICT):find(jid:tolower(JID), StateData#state.users), Affiliation = get_affiliation(JID, StateData), SAffiliation = affiliation_to_list(Affiliation), SRole = role_to_list(Role), lists:foreach(fun ({_LJID, Info}) -> ItemAttrs1 = case Info#user.role == moderator orelse (StateData#state.config)#config.anonymous == false of true -> [{<<"jid">>, jid:to_string(RealJID)}, {<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}, {<<"nick">>, Nick}]; _ -> [{<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}, {<<"nick">>, Nick}] end, ItemAttrs2 = case Info#user.role == moderator orelse (StateData#state.config)#config.anonymous == false of true -> [{<<"jid">>, jid:to_string(RealJID)}, {<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}]; _ -> [{<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}] end, Status110 = case JID == Info#user.jid of true -> [#xmlel{name = <<"status">>, attrs = [{<<"code">>, <<"110">>}] }]; false -> [] end, Packet1 = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs1, children = []}, #xmlel{name = <<"status">>, attrs = [{<<"code">>, <<"303">>}], children = []}|Status110]}]}, Packet2 = xml:append_subtags(Presence, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs2, children = []}|Status110]}]), if SendOldUnavailable -> ejabberd_router:route(jid:replace_resource(StateData#state.jid, OldNick), Info#user.jid, Packet1); true -> ok end, if SendNewAvailable -> ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet2); true -> ok end end, (?DICT):to_list(StateData#state.users)). lqueue_new(Max) -> #lqueue{queue = queue:new(), len = 0, max = Max}. %% If the message queue limit is set to 0, do not store messages. lqueue_in(_Item, LQ = #lqueue{max = 0}) -> LQ; %% Otherwise, rotate messages in the queue store. lqueue_in(Item, #lqueue{queue = Q1, len = Len, max = Max}) -> Q2 = queue:in(Item, Q1), if Len >= Max -> Q3 = lqueue_cut(Q2, Len - Max + 1), #lqueue{queue = Q3, len = Max, max = Max}; true -> #lqueue{queue = Q2, len = Len + 1, max = Max} end. lqueue_cut(Q, 0) -> Q; lqueue_cut(Q, N) -> {_, Q1} = queue:out(Q), lqueue_cut(Q1, N - 1). lqueue_to_list(#lqueue{queue = Q1}) -> queue:to_list(Q1). add_message_to_history(FromNick, FromJID, Packet, StateData) -> HaveSubject = case xml:get_subtag(Packet, <<"subject">>) of false -> false; _ -> true end, TimeStamp = p1_time_compat:timestamp(), AddrPacket = case (StateData#state.config)#config.anonymous of true -> Packet; false -> Address = #xmlel{name = <<"address">>, attrs = [{<<"type">>, <<"ofrom">>}, {<<"jid">>, jid:to_string(FromJID)}], children = []}, Addresses = #xmlel{name = <<"addresses">>, attrs = [{<<"xmlns">>, ?NS_ADDRESS}], children = [Address]}, xml:append_subtags(Packet, [Addresses]) end, TSPacket = jlib:add_delay_info(AddrPacket, StateData#state.jid, TimeStamp), SPacket = jlib:replace_from_to(jid:replace_resource(StateData#state.jid, FromNick), StateData#state.jid, TSPacket), Size = element_size(SPacket), Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, calendar:now_to_universal_time(TimeStamp), Size}, StateData#state.history), add_to_log(text, {FromNick, Packet}, StateData), StateData#state{history = Q1}. send_history(JID, Shift, StateData) -> lists:foldl(fun ({Nick, Packet, HaveSubject, _TimeStamp, _Size}, B) -> ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), JID, Packet), B or HaveSubject end, false, lists:nthtail(Shift, lqueue_to_list(StateData#state.history))). send_subject(_JID, #state{subject_author = <<"">>}) -> ok; 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(jid:replace_resource(StateData#state.jid, Nick), JID, Packet). check_subject(Packet) -> case xml:get_subtag(Packet, <<"subject">>) of false -> false; SubjEl -> xml:get_tag_cdata(SubjEl) end. can_change_subject(Role, StateData) -> case (StateData#state.config)#config.allow_change_subj of true -> Role == moderator orelse Role == participant; _ -> Role == moderator end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Admin stuff 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 false -> {error, ?ERR_BAD_REQUEST}; Item -> FAffiliation = get_affiliation(From, StateData), FRole = get_role(From, StateData), case xml:get_tag_attr(<<"role">>, Item) of false -> case xml:get_tag_attr(<<"affiliation">>, Item) of false -> {error, ?ERR_BAD_REQUEST}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; SAffiliation -> if (FAffiliation == owner) or (FAffiliation == admin) or ((FAffiliation == member) and (SAffiliation == member)) -> Items = items_with_affiliation(SAffiliation, StateData), {result, Items, StateData}; true -> ErrText = <<"Administrator privileges required">>, {error, ?ERRT_FORBIDDEN(Lang, ErrText)} end end end; {value, StrRole} -> case catch list_to_role(StrRole) of {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; SRole -> if FRole == moderator -> Items = items_with_role(SRole, StateData), {result, Items, StateData}; true -> ErrText = <<"Moderator privileges required">>, {error, ?ERRT_FORBIDDEN(Lang, ErrText)} end end end end. items_with_role(SRole, StateData) -> lists:map(fun ({_, U}) -> user_to_item(U, StateData) end, search_role(SRole, StateData)). items_with_affiliation(SAffiliation, StateData) -> lists:map(fun ({JID, {Affiliation, Reason}}) -> #xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, affiliation_to_list(Affiliation)}, {<<"jid">>, jid:to_string(JID)}], children = [#xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, Reason}]}]}; ({JID, Affiliation}) -> #xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, affiliation_to_list(Affiliation)}, {<<"jid">>, jid:to_string(JID)}], children = []} end, search_affiliation(SAffiliation, StateData)). user_to_item(#user{role = Role, nick = Nick, jid = JID}, StateData) -> Affiliation = get_affiliation(JID, StateData), #xmlel{name = <<"item">>, attrs = [{<<"role">>, role_to_list(Role)}, {<<"affiliation">>, affiliation_to_list(Affiliation)}, {<<"nick">>, Nick}, {<<"jid">>, jid:to_string(JID)}], children = []}. search_role(Role, StateData) -> lists:filter(fun ({_, #user{role = R}}) -> Role == R end, (?DICT):to_list(StateData#state.users)). search_affiliation(Affiliation, StateData) -> lists:filter(fun ({_, A}) -> case A of {A1, _Reason} -> Affiliation == A1; _ -> Affiliation == A end end, (?DICT):to_list(StateData#state.affiliations)). process_admin_items_set(UJID, Items, Lang, StateData) -> UAffiliation = get_affiliation(UJID, StateData), URole = get_role(UJID, StateData), case find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, []) of {result, Res} -> ?INFO_MSG("Processing MUC admin query from ~s in " "room ~s:~n ~p", [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 true -> mod_muc:store_room(NSD#state.server_host, NSD#state.host, NSD#state.room, make_opts(NSD)); _ -> ok end, {result, [], NSD}; Err -> Err end. process_item_change(UJID) -> fun(E, SD) -> process_item_change(E, SD, UJID) end. process_item_change(E, SD, UJID) -> case catch case E of {JID, affiliation, owner, _} when JID#jid.luser == <<"">> -> %% If the provided JID does not have username, %% forget the affiliation completely SD; {JID, role, none, Reason} -> catch send_kickban_presence(UJID, JID, Reason, <<"307">>, SD), set_role(JID, none, SD); {JID, affiliation, none, Reason} -> case (SD#state.config)#config.members_only of true -> catch send_kickban_presence(UJID, JID, Reason, <<"321">>, none, SD), SD1 = set_affiliation(JID, none, SD), set_role(JID, none, SD1); _ -> SD1 = set_affiliation(JID, none, SD), send_update_presence(JID, SD1, SD), SD1 end; {JID, affiliation, outcast, Reason} -> catch send_kickban_presence(UJID, JID, Reason, <<"301">>, outcast, SD), set_affiliation(JID, outcast, set_role(JID, none, SD), Reason); {JID, affiliation, A, Reason} 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, 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, SD), SD2; {JID, role, Role, Reason} -> SD1 = set_role(JID, Role, SD), catch send_new_presence(JID, Reason, SD1, SD), SD1; {JID, affiliation, A, _Reason} -> SD1 = set_affiliation(JID, A, SD), send_update_presence(JID, SD1, SD), SD1 end of {'EXIT', ErrReason} -> ?ERROR_MSG("MUC ITEMS SET ERR: ~p~n", [ErrReason]), SD; NSD -> NSD end. find_changed_items(_UJID, _UAffiliation, _URole, [], _Lang, _StateData, Res) -> {result, Res}; find_changed_items(UJID, UAffiliation, URole, [{xmlcdata, _} | Items], Lang, StateData, Res) -> find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, Res); find_changed_items(UJID, UAffiliation, URole, [#xmlel{name = <<"item">>, attrs = Attrs} = Item | Items], Lang, StateData, Res) -> TJID = case xml:get_attr(<<"jid">>, Attrs) of {value, S} -> case jid:from_string(S) of error -> ErrText = iolist_to_binary( io_lib:format(translate:translate( Lang, <<"Jabber ID ~s is invalid">>), [S])), {error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)}; J -> {value, [J]} end; _ -> case xml:get_attr(<<"nick">>, Attrs) of {value, N} -> case find_jids_by_nick(N, StateData) of false -> ErrText = iolist_to_binary( io_lib:format( translate:translate( Lang, <<"Nickname ~s does not exist in the room">>), [N])), {error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)}; J -> {value, J} end; _ -> {error, ?ERR_BAD_REQUEST} end end, case TJID of {value, [JID | _] = JIDs} -> TAffiliation = get_affiliation(JID, StateData), TRole = get_role(JID, StateData), case xml:get_attr(<<"role">>, Attrs) of false -> case xml:get_attr(<<"affiliation">>, Attrs) of false -> {error, ?ERR_BAD_REQUEST}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of {'EXIT', _} -> ErrText1 = iolist_to_binary( io_lib:format( translate:translate( Lang, <<"Invalid affiliation: ~s">>), [StrAffiliation])), {error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText1)}; SAffiliation -> ServiceAf = get_service_affiliation(JID, StateData), CanChangeRA = case can_change_ra(UAffiliation, URole, TAffiliation, TRole, affiliation, SAffiliation, ServiceAf) of nothing -> nothing; true -> true; check_owner -> case search_affiliation(owner, StateData) of [{OJID, _}] -> jid:remove_resource(OJID) /= jid:tolower(jid:remove_resource(UJID)); _ -> true end; _ -> false end, case CanChangeRA of nothing -> find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, Res); true -> Reason = xml:get_path_s(Item, [{elem, <<"reason">>}, cdata]), MoreRes = [{jid:remove_resource(Jidx), affiliation, SAffiliation, Reason} || Jidx <- JIDs], find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, [MoreRes | Res]); false -> {error, ?ERR_NOT_ALLOWED} end end end; {value, StrRole} -> case catch list_to_role(StrRole) of {'EXIT', _} -> ErrText1 = iolist_to_binary( io_lib:format(translate:translate( Lang, <<"Invalid role: ~s">>), [StrRole])), {error, ?ERRT_BAD_REQUEST(Lang, ErrText1)}; SRole -> ServiceAf = get_service_affiliation(JID, StateData), CanChangeRA = case can_change_ra(UAffiliation, URole, TAffiliation, TRole, role, SRole, ServiceAf) of nothing -> nothing; true -> true; check_owner -> case search_affiliation(owner, StateData) of [{OJID, _}] -> jid:remove_resource(OJID) /= jid:tolower(jid:remove_resource(UJID)); _ -> true end; _ -> false end, case CanChangeRA of nothing -> find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, Res); true -> Reason = xml:get_path_s(Item, [{elem, <<"reason">>}, cdata]), MoreRes = [{Jidx, role, SRole, Reason} || Jidx <- JIDs], find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, [MoreRes | Res]); _ -> {error, ?ERR_NOT_ALLOWED} end end end; Err -> Err end; find_changed_items(_UJID, _UAffiliation, _URole, _Items, _Lang, _StateData, _Res) -> {error, ?ERR_BAD_REQUEST}. can_change_ra(_FAffiliation, _FRole, owner, _TRole, affiliation, owner, owner) -> %% A room owner tries to add as persistent owner a %% participant that is already owner because he is MUC admin true; can_change_ra(_FAffiliation, _FRole, _TAffiliation, _TRole, _RoleorAffiliation, _Value, owner) -> %% Nobody can decrease MUC admin's role/affiliation false; can_change_ra(_FAffiliation, _FRole, TAffiliation, _TRole, affiliation, Value, _ServiceAf) when TAffiliation == Value -> nothing; can_change_ra(_FAffiliation, _FRole, _TAffiliation, TRole, role, Value, _ServiceAf) when TRole == Value -> nothing; can_change_ra(FAffiliation, _FRole, outcast, _TRole, affiliation, none, _ServiceAf) when (FAffiliation == owner) or (FAffiliation == admin) -> true; can_change_ra(FAffiliation, _FRole, outcast, _TRole, affiliation, member, _ServiceAf) when (FAffiliation == owner) or (FAffiliation == admin) -> true; can_change_ra(owner, _FRole, outcast, _TRole, affiliation, admin, _ServiceAf) -> true; can_change_ra(owner, _FRole, outcast, _TRole, affiliation, owner, _ServiceAf) -> true; can_change_ra(FAffiliation, _FRole, none, _TRole, affiliation, outcast, _ServiceAf) when (FAffiliation == owner) or (FAffiliation == admin) -> true; can_change_ra(FAffiliation, _FRole, none, _TRole, affiliation, member, _ServiceAf) when (FAffiliation == owner) or (FAffiliation == admin) -> true; can_change_ra(owner, _FRole, none, _TRole, affiliation, admin, _ServiceAf) -> true; can_change_ra(owner, _FRole, none, _TRole, affiliation, owner, _ServiceAf) -> true; can_change_ra(FAffiliation, _FRole, member, _TRole, affiliation, outcast, _ServiceAf) when (FAffiliation == owner) or (FAffiliation == admin) -> true; can_change_ra(FAffiliation, _FRole, member, _TRole, affiliation, none, _ServiceAf) when (FAffiliation == owner) or (FAffiliation == admin) -> true; can_change_ra(owner, _FRole, member, _TRole, affiliation, admin, _ServiceAf) -> true; can_change_ra(owner, _FRole, member, _TRole, affiliation, owner, _ServiceAf) -> true; can_change_ra(owner, _FRole, admin, _TRole, affiliation, _Affiliation, _ServiceAf) -> true; can_change_ra(owner, _FRole, owner, _TRole, affiliation, _Affiliation, _ServiceAf) -> check_owner; can_change_ra(_FAffiliation, _FRole, _TAffiliation, _TRole, affiliation, _Value, _ServiceAf) -> false; can_change_ra(_FAffiliation, moderator, _TAffiliation, visitor, role, none, _ServiceAf) -> true; can_change_ra(_FAffiliation, moderator, _TAffiliation, visitor, role, participant, _ServiceAf) -> true; can_change_ra(FAffiliation, _FRole, _TAffiliation, visitor, role, moderator, _ServiceAf) when (FAffiliation == owner) or (FAffiliation == admin) -> true; can_change_ra(_FAffiliation, moderator, _TAffiliation, participant, role, none, _ServiceAf) -> true; can_change_ra(_FAffiliation, moderator, _TAffiliation, participant, role, visitor, _ServiceAf) -> true; can_change_ra(FAffiliation, _FRole, _TAffiliation, participant, role, moderator, _ServiceAf) when (FAffiliation == owner) or (FAffiliation == admin) -> true; can_change_ra(_FAffiliation, _FRole, owner, moderator, role, visitor, _ServiceAf) -> false; can_change_ra(owner, _FRole, _TAffiliation, moderator, role, visitor, _ServiceAf) -> true; can_change_ra(_FAffiliation, _FRole, admin, moderator, role, visitor, _ServiceAf) -> false; can_change_ra(admin, _FRole, _TAffiliation, moderator, role, visitor, _ServiceAf) -> true; can_change_ra(_FAffiliation, _FRole, owner, moderator, role, participant, _ServiceAf) -> false; can_change_ra(owner, _FRole, _TAffiliation, moderator, role, participant, _ServiceAf) -> true; can_change_ra(_FAffiliation, _FRole, admin, moderator, role, participant, _ServiceAf) -> false; can_change_ra(admin, _FRole, _TAffiliation, moderator, role, participant, _ServiceAf) -> true; can_change_ra(_FAffiliation, _FRole, _TAffiliation, _TRole, role, _Value, _ServiceAf) -> false. send_kickban_presence(UJID, JID, Reason, Code, StateData) -> NewAffiliation = get_affiliation(JID, StateData), send_kickban_presence(UJID, JID, Reason, Code, NewAffiliation, StateData). send_kickban_presence(UJID, JID, Reason, Code, NewAffiliation, StateData) -> LJID = jid:tolower(JID), LJIDs = case LJID of {U, S, <<"">>} -> (?DICT):fold(fun (J, _, Js) -> case J of {U, S, _} -> [J | Js]; _ -> Js end end, [], StateData#state.users); _ -> case (?DICT):is_key(LJID, StateData#state.users) of true -> [LJID]; _ -> [] end end, lists:foreach(fun (J) -> {ok, #user{nick = Nick}} = (?DICT):find(J, StateData#state.users), add_to_log(kickban, {Nick, Reason, Code}, StateData), tab_remove_online_user(J, StateData), send_kickban_presence1(UJID, J, Reason, Code, NewAffiliation, StateData) end, LJIDs). send_kickban_presence1(MJID, UJID, Reason, Code, Affiliation, StateData) -> {ok, #user{jid = RealJID, nick = Nick}} = (?DICT):find(jid:tolower(UJID), StateData#state.users), SAffiliation = affiliation_to_list(Affiliation), BannedJIDString = jid:to_string(RealJID), case MJID /= <<"">> of true -> {ok, #user{nick = ActorNick}} = (?DICT):find(jid:tolower(MJID), StateData#state.users); false -> ActorNick = <<"">> end, lists:foreach(fun ({_LJID, Info}) -> JidAttrList = case Info#user.role == moderator orelse (StateData#state.config)#config.anonymous == false of true -> [{<<"jid">>, BannedJIDString}]; false -> [] end, ItemAttrs = [{<<"affiliation">>, SAffiliation}, {<<"role">>, <<"none">>}] ++ JidAttrList, ItemEls = case Reason of <<"">> -> []; _ -> [#xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, Reason}]}] end, ItemElsActor = case MJID of <<"">> -> []; _ -> [#xmlel{name = <<"actor">>, attrs = [{<<"nick">>, ActorNick}]}] end, Packet = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs, children = ItemElsActor ++ ItemEls}, #xmlel{name = <<"status">>, attrs = [{<<"code">>, Code}], children = []}]}]}, ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet) end, (?DICT):to_list(StateData#state.users)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Owner stuff process_iq_owner(From, set, Lang, SubEl, StateData) -> FAffiliation = get_affiliation(From, StateData), case FAffiliation of owner -> #xmlel{children = Els} = SubEl, 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, [], StateData}; {?NS_XDATA, <<"submit">>} -> case is_allowed_log_change(XEl, StateData, From) andalso is_allowed_persistent_change(XEl, StateData, From) andalso is_allowed_room_name_desc_limits(XEl, StateData) andalso is_password_settings_correct(XEl, StateData) of true -> set_config(XEl, StateData); false -> {error, ?ERR_NOT_ACCEPTABLE} end; _ -> {error, ?ERR_BAD_REQUEST} end; [#xmlel{name = <<"destroy">>} = SubEl1] -> ?INFO_MSG("Destroyed MUC room ~s by the owner ~s", [jid:to_string(StateData#state.jid), jid:to_string(From)]), add_to_log(room_existence, destroyed, StateData), destroy_room(SubEl1, StateData); Items -> process_admin_items_set(From, Items, Lang, StateData) end; _ -> ErrText = <<"Owner privileges required">>, {error, ?ERRT_FORBIDDEN(Lang, ErrText)} end; process_iq_owner(From, get, Lang, SubEl, StateData) -> FAffiliation = get_affiliation(From, StateData), case FAffiliation of owner -> #xmlel{children = Els} = SubEl, case xml:remove_cdata(Els) of [] -> get_config(Lang, StateData, From); [Item] -> case xml:get_tag_attr(<<"affiliation">>, Item) of false -> {error, ?ERR_BAD_REQUEST}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of {'EXIT', _} -> ErrText = iolist_to_binary( io_lib:format( translate:translate( Lang, <<"Invalid affiliation: ~s">>), [StrAffiliation])), {error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)}; SAffiliation -> Items = items_with_affiliation(SAffiliation, StateData), {result, Items, StateData} end end; _ -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} end; _ -> ErrText = <<"Owner privileges required">>, {error, ?ERRT_FORBIDDEN(Lang, ErrText)} end. is_allowed_log_change(XEl, StateData, From) -> case lists:keymember(<<"muc#roomconfig_enablelogging">>, 1, jlib:parse_xdata_submit(XEl)) of false -> true; true -> allow == mod_muc_log:check_access_log(StateData#state.server_host, From) end. is_allowed_persistent_change(XEl, StateData, From) -> case lists:keymember(<<"muc#roomconfig_persistentroom">>, 1, jlib:parse_xdata_submit(XEl)) of false -> true; true -> {_AccessRoute, _AccessCreate, _AccessAdmin, AccessPersistent} = StateData#state.access, allow == acl:match_rule(StateData#state.server_host, AccessPersistent, From) end. %% Check if the Room Name and Room Description defined in the Data Form %% are conformant to the configured limits is_allowed_room_name_desc_limits(XEl, StateData) -> IsNameAccepted = case lists:keysearch(<<"muc#roomconfig_roomname">>, 1, jlib:parse_xdata_submit(XEl)) of {value, {_, [N]}} -> byte_size(N) =< gen_mod:get_module_opt(StateData#state.server_host, mod_muc, max_room_name, fun(infinity) -> infinity; (I) when is_integer(I), I>0 -> I end, infinity); _ -> true end, IsDescAccepted = case lists:keysearch(<<"muc#roomconfig_roomdesc">>, 1, jlib:parse_xdata_submit(XEl)) of {value, {_, [D]}} -> byte_size(D) =< gen_mod:get_module_opt(StateData#state.server_host, mod_muc, max_room_desc, fun(infinity) -> infinity; (I) when is_integer(I), I>0 -> I end, infinity); _ -> true end, IsNameAccepted and IsDescAccepted. %% Return false if: %% "the password for a password-protected room is blank" is_password_settings_correct(XEl, StateData) -> Config = StateData#state.config, OldProtected = Config#config.password_protected, OldPassword = Config#config.password, NewProtected = case lists:keysearch(<<"muc#roomconfig_passwordprotectedroom">>, 1, jlib:parse_xdata_submit(XEl)) of {value, {_, [<<"1">>]}} -> true; {value, {_, [<<"0">>]}} -> false; _ -> undefined end, NewPassword = case lists:keysearch(<<"muc#roomconfig_roomsecret">>, 1, jlib:parse_xdata_submit(XEl)) of {value, {_, [P]}} -> P; _ -> undefined end, case {OldProtected, NewProtected, OldPassword, NewPassword} of {true, undefined, <<"">>, undefined} -> false; {true, undefined, _, <<"">>} -> false; {_, true, <<"">>, undefined} -> false; {_, true, _, <<"">>} -> false; _ -> true 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(PRIVATEXFIELD(Label, Var, Val), ?XFIELD(<<"text-private">>, Label, Var, Val)). -define(JIDMULTIXFIELD(Label, Var, JIDList), #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"jid-multi">>}, {<<"label">>, translate:translate(Lang, Label)}, {<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, jid:to_string(JID)}]} || JID <- JIDList]}). get_default_room_maxusers(RoomState) -> DefRoomOpts = gen_mod:get_module_opt(RoomState#state.server_host, mod_muc, default_room_options, fun(L) when is_list(L) -> L end, []), RoomState2 = set_opts(DefRoomOpts, RoomState), (RoomState2#state.config)#config.max_users. get_config(Lang, StateData, From) -> {_AccessRoute, _AccessCreate, _AccessAdmin, AccessPersistent} = StateData#state.access, ServiceMaxUsers = get_service_max_users(StateData), DefaultRoomMaxUsers = get_default_room_maxusers(StateData), Config = StateData#state.config, {MaxUsersRoomInteger, MaxUsersRoomString} = case get_max_users(StateData) of N when is_integer(N) -> {N, jlib:integer_to_binary(N)}; _ -> {0, <<"none">>} end, Res = [#xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, iolist_to_binary( io_lib:format( translate:translate( Lang, <<"Configuration of room ~s">>), [jid:to_string(StateData#state.jid)]))}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"hidden">>}, {<<"var">>, <<"FORM_TYPE">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"http://jabber.org/protocol/muc#roomconfig">>}]}]}, ?STRINGXFIELD(<<"Room title">>, <<"muc#roomconfig_roomname">>, (Config#config.title)), ?STRINGXFIELD(<<"Room description">>, <<"muc#roomconfig_roomdesc">>, (Config#config.description))] ++ case acl:match_rule(StateData#state.server_host, AccessPersistent, From) of allow -> [?BOOLXFIELD(<<"Make room persistent">>, <<"muc#roomconfig_persistentroom">>, (Config#config.persistent))]; _ -> [] end ++ [?BOOLXFIELD(<<"Make room public searchable">>, <<"muc#roomconfig_publicroom">>, (Config#config.public)), ?BOOLXFIELD(<<"Make participants list public">>, <<"public_list">>, (Config#config.public_list)), ?BOOLXFIELD(<<"Make room password protected">>, <<"muc#roomconfig_passwordprotectedroom">>, (Config#config.password_protected)), ?PRIVATEXFIELD(<<"Password">>, <<"muc#roomconfig_roomsecret">>, case Config#config.password_protected of true -> Config#config.password; false -> <<"">> end), #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"list-single">>}, {<<"label">>, translate:translate(Lang, <<"Maximum Number of Occupants">>)}, {<<"var">>, <<"muc#roomconfig_maxusers">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, MaxUsersRoomString}]}] ++ if is_integer(ServiceMaxUsers) -> []; true -> [#xmlel{name = <<"option">>, attrs = [{<<"label">>, translate:translate(Lang, <<"No limit">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"none">>}]}]}] end ++ [#xmlel{name = <<"option">>, attrs = [{<<"label">>, jlib:integer_to_binary(N)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, jlib:integer_to_binary(N)}]}]} || N <- lists:usort([ServiceMaxUsers, DefaultRoomMaxUsers, MaxUsersRoomInteger | ?MAX_USERS_DEFAULT_LIST]), N =< ServiceMaxUsers]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"list-single">>}, {<<"label">>, translate:translate(Lang, <<"Present real Jabber IDs to">>)}, {<<"var">>, <<"muc#roomconfig_whois">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, if Config#config.anonymous -> <<"moderators">>; true -> <<"anyone">> end}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, translate:translate(Lang, <<"moderators only">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"moderators">>}]}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, translate:translate(Lang, <<"anyone">>)}], children = [#xmlel{name = <<"value">>, attrs = [], 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)), ?BOOLXFIELD(<<"Make room moderated">>, <<"muc#roomconfig_moderatedroom">>, (Config#config.moderated)), ?BOOLXFIELD(<<"Default users as participants">>, <<"members_by_default">>, (Config#config.members_by_default)), ?BOOLXFIELD(<<"Allow users to change the subject">>, <<"muc#roomconfig_changesubject">>, (Config#config.allow_change_subj)), ?BOOLXFIELD(<<"Allow users to send private messages">>, <<"allow_private_messages">>, (Config#config.allow_private_messages)), #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"list-single">>}, {<<"label">>, translate:translate(Lang, <<"Allow visitors to send private messages to">>)}, {<<"var">>, <<"allow_private_messages_from_visitors">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, case Config#config.allow_private_messages_from_visitors of anyone -> <<"anyone">>; moderators -> <<"moderators">>; nobody -> <<"nobody">> end}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, translate:translate(Lang, <<"nobody">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"nobody">>}]}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, translate:translate(Lang, <<"moderators only">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"moderators">>}]}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, translate:translate(Lang, <<"anyone">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"anyone">>}]}]}]}, ?BOOLXFIELD(<<"Allow users to query other users">>, <<"allow_query_users">>, (Config#config.allow_query_users)), ?BOOLXFIELD(<<"Allow users to send invites">>, <<"muc#roomconfig_allowinvites">>, (Config#config.allow_user_invites)), ?BOOLXFIELD(<<"Allow visitors to send status text in " "presence updates">>, <<"muc#roomconfig_allowvisitorstatus">>, (Config#config.allow_visitor_status)), ?BOOLXFIELD(<<"Allow visitors to change nickname">>, <<"muc#roomconfig_allowvisitornickchange">>, (Config#config.allow_visitor_nickchange)), ?BOOLXFIELD(<<"Allow visitors to send voice requests">>, <<"muc#roomconfig_allowvoicerequests">>, (Config#config.allow_voice_requests)), ?STRINGXFIELD(<<"Minimum interval between voice requests " "(in seconds)">>, <<"muc#roomconfig_voicerequestmininterval">>, (jlib:integer_to_binary(Config#config.voice_request_min_interval)))] ++ case ejabberd_captcha:is_feature_available() of true -> [?BOOLXFIELD(<<"Make room CAPTCHA protected">>, <<"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">>, <<"muc#roomconfig_captcha_whitelist">>, ((?SETS):to_list(Config#config.captcha_whitelist)))] ++ case mod_muc_log:check_access_log(StateData#state.server_host, From) of allow -> [?BOOLXFIELD(<<"Enable logging">>, <<"muc#roomconfig_enablelogging">>, (Config#config.logging))]; _ -> [] end, {result, [#xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"You need an x:data capable client to " "configure room">>)}]}, #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = Res}], StateData}. set_config(XEl, StateData) -> XData = jlib:parse_xdata_submit(XEl), case XData of invalid -> {error, ?ERR_BAD_REQUEST}; _ -> case set_xoption(XData, StateData#state.config) of #config{} = Config -> Res = change_config(Config, StateData), {result, _, NSD} = Res, Type = case {(StateData#state.config)#config.logging, Config#config.logging} of {true, false} -> roomconfig_change_disabledlogging; {false, true} -> roomconfig_change_enabledlogging; {_, _} -> roomconfig_change end, Users = [{U#user.jid, U#user.nick, U#user.role} || {_, U} <- (?DICT):to_list(StateData#state.users)], add_to_log(Type, Users, NSD), Res; Err -> Err end end. -define(SET_BOOL_XOPT(Opt, Val), case Val of <<"0">> -> set_xoption(Opts, Config#config{Opt = false}); <<"false">> -> set_xoption(Opts, Config#config{Opt = false}); <<"1">> -> set_xoption(Opts, Config#config{Opt = true}); <<"true">> -> set_xoption(Opts, Config#config{Opt = true}); _ -> {error, ?ERR_BAD_REQUEST} end). -define(SET_NAT_XOPT(Opt, Val), case catch jlib:binary_to_integer(Val) of I when is_integer(I), I > 0 -> set_xoption(Opts, Config#config{Opt = I}); _ -> {error, ?ERR_BAD_REQUEST} end). -define(SET_STRING_XOPT(Opt, Val), set_xoption(Opts, Config#config{Opt = Val})). -define(SET_JIDMULTI_XOPT(Opt, Vals), begin Set = lists:foldl(fun ({U, S, R}, Set1) -> (?SETS):add_element({U, S, R}, Set1); (#jid{luser = U, lserver = S, lresource = R}, Set1) -> (?SETS):add_element({U, S, R}, Set1); (_, Set1) -> Set1 end, (?SETS):empty(), Vals), set_xoption(Opts, Config#config{Opt = Set}) end). set_xoption([], Config) -> Config; set_xoption([{<<"muc#roomconfig_roomname">>, [Val]} | Opts], Config) -> ?SET_STRING_XOPT(title, Val); set_xoption([{<<"muc#roomconfig_roomdesc">>, [Val]} | Opts], Config) -> ?SET_STRING_XOPT(description, Val); set_xoption([{<<"muc#roomconfig_changesubject">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(allow_change_subj, Val); set_xoption([{<<"allow_query_users">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(allow_query_users, Val); set_xoption([{<<"allow_private_messages">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(allow_private_messages, Val); set_xoption([{<<"allow_private_messages_from_visitors">>, [Val]} | Opts], Config) -> case Val of <<"anyone">> -> ?SET_STRING_XOPT(allow_private_messages_from_visitors, anyone); <<"moderators">> -> ?SET_STRING_XOPT(allow_private_messages_from_visitors, moderators); <<"nobody">> -> ?SET_STRING_XOPT(allow_private_messages_from_visitors, nobody); _ -> {error, ?ERR_BAD_REQUEST} end; set_xoption([{<<"muc#roomconfig_allowvisitorstatus">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(allow_visitor_status, Val); set_xoption([{<<"muc#roomconfig_allowvisitornickchange">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(allow_visitor_nickchange, Val); set_xoption([{<<"muc#roomconfig_publicroom">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(public, Val); set_xoption([{<<"public_list">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(public_list, Val); set_xoption([{<<"muc#roomconfig_persistentroom">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(persistent, Val); set_xoption([{<<"muc#roomconfig_moderatedroom">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(moderated, Val); set_xoption([{<<"members_by_default">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(members_by_default, Val); set_xoption([{<<"muc#roomconfig_membersonly">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(members_only, Val); set_xoption([{<<"captcha_protected">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(captcha_protected, Val); set_xoption([{<<"muc#roomconfig_allowinvites">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(allow_user_invites, Val); set_xoption([{<<"muc#roomconfig_passwordprotectedroom">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(password_protected, Val); set_xoption([{<<"muc#roomconfig_roomsecret">>, [Val]} | Opts], Config) -> ?SET_STRING_XOPT(password, 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], Config) -> ?SET_BOOL_XOPT(allow_voice_requests, Val); set_xoption([{<<"muc#roomconfig_voicerequestmininterval">>, [Val]} | Opts], Config) -> ?SET_NAT_XOPT(voice_request_min_interval, Val); set_xoption([{<<"muc#roomconfig_whois">>, [Val]} | Opts], Config) -> case Val of <<"moderators">> -> ?SET_BOOL_XOPT(anonymous, (iolist_to_binary(integer_to_list(1)))); <<"anyone">> -> ?SET_BOOL_XOPT(anonymous, (iolist_to_binary(integer_to_list(0)))); _ -> {error, ?ERR_BAD_REQUEST} end; set_xoption([{<<"muc#roomconfig_maxusers">>, [Val]} | Opts], Config) -> case Val of <<"none">> -> ?SET_STRING_XOPT(max_users, none); _ -> ?SET_NAT_XOPT(max_users, Val) end; 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], Config) -> JIDs = [jid:from_string(Val) || Val <- Vals], ?SET_JIDMULTI_XOPT(captcha_whitelist, JIDs); set_xoption([{<<"FORM_TYPE">>, _} | Opts], Config) -> set_xoption(Opts, Config); 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} of {_, true} -> mod_muc:store_room(NSD#state.server_host, NSD#state.host, NSD#state.room, make_opts(NSD)); {true, false} -> mod_muc:forget_room(NSD#state.server_host, NSD#state.host, NSD#state.room); {false, false} -> ok end, case {(StateData#state.config)#config.members_only, Config#config.members_only} of {false, true} -> NSD1 = remove_nonmembers(NSD), {result, [], NSD1}; _ -> {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), case Affiliation of none -> catch send_kickban_presence(<<"">>, JID, <<"">>, <<"322">>, SD), set_role(JID, none, SD); _ -> SD end end, StateData, (?DICT):to_list(StateData#state.users)). set_opts([], StateData) -> StateData; set_opts([{Opt, Val} | Opts], StateData) -> NSD = case Opt of title -> StateData#state{config = (StateData#state.config)#config{title = Val}}; description -> StateData#state{config = (StateData#state.config)#config{description = Val}}; allow_change_subj -> StateData#state{config = (StateData#state.config)#config{allow_change_subj = Val}}; allow_query_users -> StateData#state{config = (StateData#state.config)#config{allow_query_users = Val}}; allow_private_messages -> StateData#state{config = (StateData#state.config)#config{allow_private_messages = Val}}; allow_private_messages_from_visitors -> StateData#state{config = (StateData#state.config)#config{allow_private_messages_from_visitors = Val}}; allow_visitor_nickchange -> StateData#state{config = (StateData#state.config)#config{allow_visitor_nickchange = Val}}; allow_visitor_status -> StateData#state{config = (StateData#state.config)#config{allow_visitor_status = Val}}; public -> StateData#state{config = (StateData#state.config)#config{public = Val}}; public_list -> StateData#state{config = (StateData#state.config)#config{public_list = Val}}; persistent -> StateData#state{config = (StateData#state.config)#config{persistent = Val}}; moderated -> StateData#state{config = (StateData#state.config)#config{moderated = Val}}; members_by_default -> StateData#state{config = (StateData#state.config)#config{members_by_default = Val}}; members_only -> StateData#state{config = (StateData#state.config)#config{members_only = Val}}; allow_user_invites -> StateData#state{config = (StateData#state.config)#config{allow_user_invites = Val}}; password_protected -> StateData#state{config = (StateData#state.config)#config{password_protected = Val}}; captcha_protected -> StateData#state{config = (StateData#state.config)#config{captcha_protected = Val}}; password -> StateData#state{config = (StateData#state.config)#config{password = Val}}; anonymous -> 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 = Val}}; mam -> StateData#state{config = (StateData#state.config)#config{mam = Val}}; captcha_whitelist -> StateData#state{config = (StateData#state.config)#config{captcha_whitelist = (?SETS):from_list(Val)}}; allow_voice_requests -> StateData#state{config = (StateData#state.config)#config{allow_voice_requests = Val}}; voice_request_min_interval -> StateData#state{config = (StateData#state.config)#config{voice_request_min_interval = Val}}; max_users -> ServiceMaxUsers = get_service_max_users(StateData), MaxUsers = if Val =< ServiceMaxUsers -> Val; true -> ServiceMaxUsers end, StateData#state{config = (StateData#state.config)#config{max_users = MaxUsers}}; vcard -> StateData#state{config = (StateData#state.config)#config{vcard = Val}}; affiliations -> StateData#state{affiliations = (?DICT):from_list(Val)}; subject -> StateData#state{subject = Val}; subject_author -> StateData#state{subject_author = Val}; _ -> StateData end, set_opts(Opts, NSD). -define(MAKE_CONFIG_OPT(Opt), {Opt, Config#config.Opt}). make_opts(StateData) -> Config = StateData#state.config, [?MAKE_CONFIG_OPT(title), ?MAKE_CONFIG_OPT(description), ?MAKE_CONFIG_OPT(allow_change_subj), ?MAKE_CONFIG_OPT(allow_query_users), ?MAKE_CONFIG_OPT(allow_private_messages), ?MAKE_CONFIG_OPT(allow_private_messages_from_visitors), ?MAKE_CONFIG_OPT(allow_visitor_status), ?MAKE_CONFIG_OPT(allow_visitor_nickchange), ?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(captcha_protected), ?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, (?SETS):to_list((StateData#state.config)#config.captcha_whitelist)}, {affiliations, (?DICT):to_list(StateData#state.affiliations)}, {subject, StateData#state.subject}, {subject_author, StateData#state.subject_author}]. destroy_room(DEl, StateData) -> lists:foreach(fun ({_LJID, Info}) -> Nick = Info#user.nick, ItemAttrs = [{<<"affiliation">>, <<"none">>}, {<<"role">>, <<"none">>}], Packet = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs, children = []}, DEl]}]}, ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet) end, (?DICT):to_list(StateData#state.users)), case (StateData#state.config)#config.persistent of true -> mod_muc:forget_room(StateData#state.server_host, StateData#state.host, StateData#state.room); false -> ok end, {result, [], stop}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Disco -define(FEATURE(Var), #xmlel{name = <<"feature">>, attrs = [{<<"var">>, Var}], children = []}). -define(CONFIG_OPT_TO_FEATURE(Opt, Fiftrue, Fiffalse), case Opt of true -> ?FEATURE(Fiftrue); false -> ?FEATURE(Fiffalse) end). process_iq_disco_info(_From, set, _Lang, _StateData) -> {error, ?ERR_NOT_ALLOWED}; process_iq_disco_info(_From, get, Lang, StateData) -> Config = StateData#state.config, {result, [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"conference">>}, {<<"type">>, <<"text">>}, {<<"name">>, get_title(StateData)}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_VCARD}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_MUC}], children = []}, ?CONFIG_OPT_TO_FEATURE((Config#config.public), <<"muc_public">>, <<"muc_hidden">>), ?CONFIG_OPT_TO_FEATURE((Config#config.persistent), <<"muc_persistent">>, <<"muc_temporary">>), ?CONFIG_OPT_TO_FEATURE((Config#config.members_only), <<"muc_membersonly">>, <<"muc_open">>), ?CONFIG_OPT_TO_FEATURE((Config#config.anonymous), <<"muc_semianonymous">>, <<"muc_nonanonymous">>), ?CONFIG_OPT_TO_FEATURE((Config#config.moderated), <<"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}. -define(RFIELDT(Type, Var, Val), #xmlel{name = <<"field">>, attrs = [{<<"type">>, Type}, {<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Val}]}]}). -define(RFIELD(Label, Var, Val), #xmlel{name = <<"field">>, attrs = [{<<"label">>, translate:translate(Lang, Label)}, {<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Val}]}]}). iq_disco_info_extras(Lang, StateData) -> Len = (?DICT):size(StateData#state.users), RoomDescription = (StateData#state.config)#config.description, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}], children = [?RFIELDT(<<"hidden">>, <<"FORM_TYPE">>, <<"http://jabber.org/protocol/muc#roominfo">>), ?RFIELD(<<"Room description">>, <<"muc#roominfo_description">>, RoomDescription), ?RFIELD(<<"Number of occupants">>, <<"muc#roominfo_occupants">>, (iolist_to_binary(integer_to_list(Len))))]}]. process_iq_disco_items(_From, set, _Lang, _StateData) -> {error, ?ERR_NOT_ALLOWED}; process_iq_disco_items(From, get, _Lang, StateData) -> case (StateData#state.config)#config.public_list of true -> {result, get_mucroom_disco_items(StateData), StateData}; _ -> case is_occupant_or_admin(From, StateData) of true -> {result, get_mucroom_disco_items(StateData), StateData}; _ -> {error, ?ERR_FORBIDDEN} end end. process_iq_captcha(_From, get, _Lang, _SubEl, _StateData) -> {error, ?ERR_NOT_ALLOWED}; process_iq_captcha(_From, set, _Lang, SubEl, StateData) -> case ejabberd_captcha:process_reply(SubEl) of ok -> {result, [], StateData}; _ -> {error, ?ERR_NOT_ACCEPTABLE} end. process_iq_vcard(_From, get, _Lang, _SubEl, StateData) -> #state{config = #config{vcard = VCardRaw}} = StateData, case xml_stream:parse_element(VCardRaw) of #xmlel{children = VCardEls} -> {result, VCardEls, StateData}; {error, _} -> {result, [], StateData} end; process_iq_vcard(From, set, Lang, SubEl, StateData) -> case get_affiliation(From, StateData) of owner -> VCardRaw = xml:element_to_binary(SubEl), Config = StateData#state.config, NewConfig = Config#config{vcard = VCardRaw}, change_config(NewConfig, StateData); _ -> ErrText = <<"Owner privileges required">>, {error, ?ERRT_FORBIDDEN(Lang, ErrText)} end. get_title(StateData) -> case (StateData#state.config)#config.title of <<"">> -> StateData#state.room; Name -> Name end. get_roomdesc_reply(JID, StateData, Tail) -> IsOccupantOrAdmin = is_occupant_or_admin(JID, StateData), if (StateData#state.config)#config.public or IsOccupantOrAdmin -> if (StateData#state.config)#config.public_list or IsOccupantOrAdmin -> {item, <<(get_title(StateData))/binary,Tail/binary>>}; true -> {item, get_title(StateData)} end; true -> false end. get_roomdesc_tail(StateData, Lang) -> Desc = case (StateData#state.config)#config.public of true -> <<"">>; _ -> translate:translate(Lang, <<"private, ">>) end, Len = (?DICT):fold(fun (_, _, Acc) -> Acc + 1 end, 0, StateData#state.users), <<" (", Desc/binary, (iolist_to_binary(integer_to_list(Len)))/binary, ")">>. get_mucroom_disco_items(StateData) -> lists:map(fun ({_LJID, Info}) -> Nick = Info#user.nick, #xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string({StateData#state.room, StateData#state.host, Nick})}, {<<"name">>, Nick}], children = []} end, (?DICT):to_list(StateData#state.users)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Voice request support is_voice_request(Els) -> lists:foldl(fun (#xmlel{name = <<"x">>, attrs = Attrs} = El, false) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> case jlib:parse_xdata_submit(El) of [_ | _] = Fields -> case {lists:keysearch(<<"FORM_TYPE">>, 1, Fields), lists:keysearch(<<"muc#role">>, 1, Fields)} of {{value, {_, [<<"http://jabber.org/protocol/muc#request">>]}}, {value, {_, [<<"participant">>]}}} -> true; _ -> false end; _ -> false end; _ -> false end; (_, Acc) -> Acc end, false, Els). prepare_request_form(Requester, Nick, Lang) -> #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"normal">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = [#xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Voice request">>)}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Either approve or decline the voice " "request.">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"FORM_TYPE">>}, {<<"type">>, <<"hidden">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"http://jabber.org/protocol/muc#request">>}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"muc#role">>}, {<<"type">>, <<"hidden">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"participant">>}]}]}, ?STRINGXFIELD(<<"User JID">>, <<"muc#jid">>, (jid:to_string(Requester))), ?STRINGXFIELD(<<"Nickname">>, <<"muc#roomnick">>, Nick), ?BOOLXFIELD(<<"Grant voice to this person?">>, <<"muc#request_allow">>, (jlib:binary_to_atom(<<"false">>)))]}]}. send_voice_request(From, StateData) -> Moderators = search_role(moderator, StateData), FromNick = find_nick_by_jid(From, StateData), lists:foreach(fun ({_, User}) -> ejabberd_router:route(StateData#state.jid, User#user.jid, prepare_request_form(From, FromNick, <<"">>)) end, Moderators). is_voice_approvement(Els) -> lists:foldl(fun (#xmlel{name = <<"x">>, attrs = Attrs} = El, false) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> case jlib:parse_xdata_submit(El) of [_ | _] = Fs -> case {lists:keysearch(<<"FORM_TYPE">>, 1, Fs), lists:keysearch(<<"muc#role">>, 1, Fs), lists:keysearch(<<"muc#request_allow">>, 1, Fs)} of {{value, {_, [<<"http://jabber.org/protocol/muc#request">>]}}, {value, {_, [<<"participant">>]}}, {value, {_, [Flag]}}} when Flag == <<"true">>; Flag == <<"1">> -> true; _ -> false end; _ -> false end; _ -> false end; (_, Acc) -> Acc end, false, Els). extract_jid_from_voice_approvement(Els) -> lists:foldl(fun (#xmlel{name = <<"x">>} = El, error) -> Fields = case jlib:parse_xdata_submit(El) of invalid -> []; Res -> Res end, lists:foldl(fun ({<<"muc#jid">>, [JIDStr]}, error) -> case jid:from_string(JIDStr) of error -> error; J -> {ok, J} end; (_, Acc) -> Acc end, error, Fields); (_, Acc) -> Acc end, error, Els). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Invitation support is_invitation(Els) -> lists:foldl(fun (#xmlel{name = <<"x">>, attrs = Attrs} = El, false) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC_USER -> case xml:get_subtag(El, <<"invite">>) of false -> false; _ -> true end; _ -> false end; (_, Acc) -> Acc end, false, Els). check_invitation(From, Els, Lang, StateData) -> FAffiliation = get_affiliation(From, StateData), CanInvite = (StateData#state.config)#config.allow_user_invites orelse FAffiliation == admin orelse FAffiliation == owner, InviteEl = case xml:remove_cdata(Els) of [#xmlel{name = <<"x">>, children = Els1} = XEl] -> case xml:get_tag_attr_s(<<"xmlns">>, XEl) of ?NS_MUC_USER -> ok; _ -> throw({error, ?ERR_BAD_REQUEST}) end, case xml: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">>, InviteEl)) of error -> throw({error, ?ERR_JID_MALFORMED}); JID1 -> JID1 end, case CanInvite of false -> throw({error, ?ERR_NOT_ALLOWED}); true -> Reason = xml:get_path_s(InviteEl, [{elem, <<"reason">>}, cdata]), ContinueEl = case xml:get_path_s(InviteEl, [{elem, <<"continue">>}]) of <<>> -> []; Continue1 -> [Continue1] end, IEl = [#xmlel{name = <<"invite">>, attrs = [{<<"from">>, jid:to_string(From)}], children = [#xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, Reason}]}] ++ ContinueEl}], PasswdEl = case (StateData#state.config)#config.password_protected of true -> [#xmlel{name = <<"password">>, attrs = [], children = [{xmlcdata, (StateData#state.config)#config.password}]}]; _ -> [] end, Body = #xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, iolist_to_binary( [io_lib:format( translate:translate( Lang, <<"~s invites you to the room ~s">>), [jid:to_string(From), jid:to_string({StateData#state.room, StateData#state.host, <<"">>})]), case (StateData#state.config)#config.password_protected of true -> <<", ", (translate:translate(Lang, <<"the password is">>))/binary, " '", ((StateData#state.config)#config.password)/binary, "'">>; _ -> <<"">> end , case Reason of <<"">> -> <<"">>; _ -> <<" (", Reason/binary, ") ">> end])}]}, Msg = #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"normal">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = IEl ++ PasswdEl}, #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XCONFERENCE}, {<<"jid">>, jid:to_string({StateData#state.room, StateData#state.host, <<"">>})}], children = [{xmlcdata, Reason}]}, Body]}, ejabberd_router:route(StateData#state.jid, JID, Msg), JID end. %% Handle a message sent to the room by a non-participant. %% If it is a decline, send to the inviter. %% Otherwise, an error message is sent to the sender. handle_roommessage_from_nonparticipant(Packet, Lang, StateData, From) -> case catch check_decline_invitation(Packet) of {true, Decline_data} -> send_decline_invitation(Decline_data, StateData#state.jid, From); _ -> send_error_only_occupants(Packet, Lang, StateData#state.jid, From) end. %% Check in the packet is a decline. %% If so, also returns the splitted packet. %% This function must be catched, %% 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), ToJID = jid:from_string(ToString), {true, {Packet, XEl, DEl, ToJID}}. %% Send the decline to the inviter user. %% The original stanza must be slightly modified. send_decline_invitation({Packet, XEl, DEl, ToJID}, RoomJID, FromJID) -> FromString = jid:to_string(jid:remove_resource(FromJID)), #xmlel{name = <<"decline">>, attrs = DAttrs, children = DEls} = DEl, DAttrs2 = lists:keydelete(<<"to">>, 1, DAttrs), DAttrs3 = [{<<"from">>, FromString} | DAttrs2], DEl2 = #xmlel{name = <<"decline">>, attrs = DAttrs3, children = DEls}, XEl2 = replace_subelement(XEl, DEl2), Packet2 = replace_subelement(Packet, XEl2), ejabberd_router:route(RoomJID, ToJID, Packet2). %% 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}, NewSubEl) -> {_, NameNewSubEl, _, _} = NewSubEl, SubEls2 = lists:keyreplace(NameNewSubEl, 2, SubEls, NewSubEl), #xmlel{name = Name, attrs = Attrs, children = SubEls2}. send_error_only_occupants(Packet, Lang, RoomJID, From) -> ErrText = <<"Only occupants are allowed to send messages " "to the conference">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route(RoomJID, From, Err). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Logging add_to_log(Type, Data, StateData) when Type == roomconfig_change_disabledlogging -> mod_muc_log:add_to_log(StateData#state.server_host, roomconfig_change, Data, StateData#state.jid, make_opts(StateData)); add_to_log(Type, Data, StateData) -> case (StateData#state.config)#config.logging of true -> mod_muc_log:add_to_log(StateData#state.server_host, Type, Data, StateData#state.jid, make_opts(StateData)); false -> ok end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Users number checking tab_add_online_user(JID, StateData) -> {LUser, LServer, LResource} = jid:tolower(JID), US = {LUser, LServer}, Room = StateData#state.room, Host = StateData#state.host, catch ets:insert(muc_online_users, #muc_online_users{us = US, resource = LResource, room = Room, host = Host}). tab_remove_online_user(JID, StateData) -> {LUser, LServer, LResource} = jid:tolower(JID), US = {LUser, LServer}, Room = StateData#state.room, Host = StateData#state.host, catch ets:delete_object(muc_online_users, #muc_online_users{us = US, resource = LResource, room = Room, host = Host}). tab_count_user(JID) -> {LUser, LServer, _} = jid:tolower(JID), US = {LUser, LServer}, case catch ets:select(muc_online_users, [{#muc_online_users{us = US, _ = '_'}, [], [[]]}]) of Res when is_list(Res) -> length(Res); _ -> 0 end. 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 has_body_or_subject(Packet) -> [] /= lists:dropwhile(fun (#xmlel{name = <<"body">>}) -> false; (#xmlel{name = <<"subject">>}) -> false; (_) -> true end, Packet#xmlel.children). ejabberd-16.01/src/odbc_queries.erl0000644000232200023220000005616112645157216017606 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : odbc_queries.erl %%% Author : Mickael Remond %%% Purpose : ODBC queries dependind on back-end %%% Created : by Mickael Remond %%% %%% %%% 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(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, 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, 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_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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). %% Almost a copy of string:join/2. %% We use this version because string:join/2 is relatively %% new function (introduced in R12B-0). join([], _Sep) -> []; join([H | T], Sep) -> [H, [[Sep, X] || X <- T]]. get_db_type() -> generic. %% Safe atomic update. update_t(Table, Fields, Vals, Where) -> UPairs = lists:zipwith(fun (A, B) -> <> end, Fields, Vals), case ejabberd_odbc:sql_query_t([<<"update ">>, Table, <<" set ">>, join(UPairs, <<", ">>), <<" where ">>, Where, <<";">>]) of {updated, 1} -> ok; _ -> Res = ejabberd_odbc:sql_query_t([<<"insert into ">>, Table, <<"(">>, join(Fields, <<", ">>), <<") values ('">>, join(Vals, <<"', '">>), <<"');">>]), case Res of {updated,1} -> ok; _ -> Res end end. 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} -> ok; _ -> Res = ejabberd_odbc:sql_query(LServer, [<<"insert into ">>, Table, <<"(">>, join(Fields, <<", ">>), <<") values ('">>, join(Vals, <<"', '">>), <<"');">>]), case Res of {updated,1} -> ok; _ -> Res end end. %% F can be either a fun or a list of queries %% TODO: We should probably move the list of queries transaction %% wrapper from the ejabberd_odbc module to this one (odbc_queries) 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, <<"'">>]). set_last_t(LServer, Username, Seconds, State) -> update(LServer, <<"last">>, [<<"username">>, <<"seconds">>, <<"state">>], [Username, Seconds, State], [<<"username='">>, Username, <<"'">>]). del_last(LServer, Username) -> ejabberd_odbc:sql_query(LServer, [<<"delete from last where username='">>, Username, <<"'">>]). get_password(LServer, Username) -> ejabberd_odbc:sql_query(LServer, [<<"select password from users where username='">>, Username, <<"';">>]). get_password_scram(LServer, Username) -> ejabberd_odbc:sql_query( LServer, [<<"select password, serverkey, salt, iterationcount from users where " "username='">>, Username, <<"';">>]). set_password_t(LServer, Username, Pass) -> ejabberd_odbc:sql_transaction(LServer, fun () -> update_t(<<"users">>, [<<"username">>, <<"password">>], [Username, Pass], [<<"username='">>, Username, <<"'">>]) end). set_password_scram_t(LServer, Username, 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). add_user(LServer, Username, Pass) -> ejabberd_odbc:sql_query(LServer, [<<"insert into users(username, password) " "values ('">>, Username, <<"', '">>, Pass, <<"');">>]). add_user_scram(LServer, Username, 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, <<"';">>]). del_user_return_password(_LServer, Username, Pass) -> 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, <<"';">>]), P. list_users(LServer) -> ejabberd_odbc:sql_query(LServer, [<<"select username from users">>]). list_users(LServer, [{from, Start}, {to, End}]) when is_integer(Start) and is_integer(End) -> list_users(LServer, [{limit, End - Start + 1}, {offset, Start - 1}]); list_users(LServer, [{prefix, Prefix}, {from, Start}, {to, End}]) when is_binary(Prefix) and is_integer(Start) and is_integer(End) -> list_users(LServer, [{prefix, Prefix}, {limit, End - Start + 1}, {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]))]); 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]))]). 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">>]) end; _ -> ejabberd_odbc:sql_query(LServer, [<<"select count(*) 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]))]); users_number(LServer, []) -> users_number(LServer). add_spool_sql(Username, XML) -> [<<"insert into spool(username, xml) values ('">>, Username, <<"', '">>, XML, <<"');">>]. add_spool(LServer, Queries) -> ejabberd_odbc:sql_transaction(LServer, Queries). get_and_del_spool_msg_t(LServer, Username) -> 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, <<"';">>]), Result end, ejabberd_odbc:sql_transaction(LServer, F). del_spool_msg(LServer, Username) -> ejabberd_odbc:sql_query(LServer, [<<"delete from spool where username='">>, Username, <<"';">>]). 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, <<"';">>]). 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_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_rostergroup_by_jid(LServer, Username, SJID) -> ejabberd_odbc:sql_query(LServer, [<<"select grp from rostergroups where username='">>, Username, <<"' and jid='">>, SJID, <<"'">>]). 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_sql(Username, SJID) -> [[<<"delete from rosterusers where " "username='">>, Username, <<"' and jid='">>, SJID, <<"';">>], [<<"delete from rostergroups where " "username='">>, Username, <<"' and jid='">>, SJID, <<"';">>]]. update_roster(_LServer, Username, 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). update_roster_sql(Username, SJID, ItemVals, ItemGroups) -> [[<<"delete from rosterusers where " "username='">>, Username, <<"' and jid='">>, SJID, <<"';">>], [<<"insert into rosterusers( " " username, jid, nick, " " subscription, ask, askmessage, " " server, subscribe, type) " "values ('">>, join(ItemVals, <<"', '">>), <<"');">>], [<<"delete from rostergroups where " "username='">>, Username, <<"' and jid='">>, SJID, <<"';">>]] ++ [[<<"insert into rostergroups( " " username, jid, grp) values ('">>, 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, <<"'">>]). get_subscription(LServer, Username, SJID) -> ejabberd_odbc:sql_query(LServer, [<<"select subscription from rosterusers " "where username='">>, Username, <<"' and jid='">>, SJID, <<"'">>]). 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_sql(Username, LXMLNS, SData) -> [[<<"delete from private_storage where username='">>, Username, <<"' and namespace='">>, LXMLNS, <<"';">>], [<<"insert into private_storage(username, " "namespace, data) values ('">>, 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, Username) -> ejabberd_odbc:sql_query(LServer, [<<"select namespace, data from private_storage " "where username='">>, Username, <<"';">>]). del_user_private_storage(LServer, Username) -> ejabberd_odbc:sql_query(LServer, [<<"delete from private_storage where username='">>, 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_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, <<"';">>]). get_default_privacy_list(LServer, Username) -> ejabberd_odbc:sql_query(LServer, [<<"select name from privacy_default_list " "where username='">>, Username, <<"';">>]). get_default_privacy_list_t(Username) -> ejabberd_odbc:sql_query_t([<<"select name from privacy_default_list " "where username='">>, Username, <<"';">>]). get_privacy_list_names(LServer, Username) -> ejabberd_odbc:sql_query(LServer, [<<"select name from privacy_list where " "username='">>, Username, <<"';">>]). get_privacy_list_names_t(Username) -> ejabberd_odbc:sql_query_t([<<"select name from privacy_list where " "username='">>, Username, <<"';">>]). 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_t(Username, SName) -> ejabberd_odbc:sql_query_t([<<"select id from privacy_list where username='">>, Username, <<"' and name='">>, SName, <<"';">>]). 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_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;">>]). 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, <<"';">>]). remove_privacy_list(Username, SName) -> ejabberd_odbc:sql_query_t([<<"delete from privacy_list where username='">>, Username, <<"' and name='">>, SName, <<"';">>]). add_privacy_list(Username, SName) -> ejabberd_odbc:sql_query_t([<<"insert into privacy_list(username, name) " "values ('">>, Username, <<"', '">>, SName, <<"');">>]). 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, <<"', '">>), <<"');">>]) 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, <<"';">>]). escape($\000) -> <<"\\0">>; escape($\n) -> <<"\\n">>; escape($\t) -> <<"\\t">>; escape($\b) -> <<"\\b">>; escape($\r) -> <<"\\r">>; escape($') -> <<"''">>; escape($") -> <<"\\\"">>; escape($\\) -> <<"\\\\">>; escape(C) -> <>. count_records_where(LServer, Table, WhereClause) -> ejabberd_odbc:sql_query(LServer, [<<"select count(*) from ">>, Table, <<" ">>, WhereClause, <<";">>]). get_roster_version(LServer, LUser) -> ejabberd_odbc:sql_query(LServer, [<<"select version from roster_version where " "username = '">>, LUser, <<"'">>]). set_roster_version(LUser, Version) -> update_t(<<"roster_version">>, [<<"username">>, <<"version">>], [LUser, Version], [<<"username = '">>, LUser, <<"'">>]). opt_type(odbc_type) -> fun (pgsql) -> pgsql; (mysql) -> mysql; (sqlite) -> sqlite; (mssql) -> mssql; (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]. ejabberd-16.01/src/mod_vcard_xupdate.erl0000644000232200023220000001733012645157216020625 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_vcard_xupdate.erl %%% Author : Igor Goryachev %%% Purpose : Add avatar hash in presence on behalf of client (XEP-0153) %%% Created : 9 Mar 2007 by Igor Goryachev %%%---------------------------------------------------------------------- -module(mod_vcard_xupdate). -behaviour(gen_mod). %% gen_mod callbacks -export([start/2, stop/1]). -export([update_presence/3, vcard_set/3, export/1, import/1, import/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -record(vcard_xupdate, {us = {<<>>, <<>>} :: {binary(), binary()}, hash = <<>> :: binary()}). %%==================================================================== %% gen_mod callbacks %%==================================================================== start(Host, Opts) -> case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(vcard_xupdate, [{disc_copies, [node()]}, {attributes, record_info(fields, vcard_xupdate)}]), update_table(); _ -> ok end, ejabberd_hooks:add(c2s_update_presence, Host, ?MODULE, update_presence, 100), ejabberd_hooks:add(vcard_set, Host, ?MODULE, vcard_set, 100), ok. stop(Host) -> ejabberd_hooks:delete(c2s_update_presence, Host, ?MODULE, update_presence, 100), ejabberd_hooks:delete(vcard_set, Host, ?MODULE, vcard_set, 100), ok. %%==================================================================== %% Hooks %%==================================================================== update_presence(#xmlel{name = <<"presence">>, attrs = Attrs} = Packet, User, Host) -> case xml:get_attr_s(<<"type">>, Attrs) of <<>> -> presence_with_xupdate(Packet, User, Host); _ -> Packet end; update_presence(Packet, _User, _Host) -> Packet. vcard_set(LUser, LServer, VCARD) -> US = {LUser, LServer}, case xml:get_path_s(VCARD, [{elem, <<"PHOTO">>}, {elem, <<"BINVAL">>}, cdata]) of <<>> -> remove_xupdate(LUser, LServer); BinVal -> add_xupdate(LUser, LServer, p1_sha:sha(jlib:decode_base64(BinVal))) end, ejabberd_sm:force_update_presence(US). %%==================================================================== %% Storage %%==================================================================== add_xupdate(LUser, LServer, Hash) -> add_xupdate(LUser, LServer, Hash, gen_mod:db_type(LServer, ?MODULE)). add_xupdate(LUser, LServer, Hash, mnesia) -> F = fun () -> mnesia:write(#vcard_xupdate{us = {LUser, LServer}, hash = Hash}) end, mnesia:transaction(F); add_xupdate(LUser, LServer, Hash, riak) -> {atomic, ejabberd_riak:put(#vcard_xupdate{us = {LUser, LServer}, hash = Hash}, vcard_xupdate_schema())}; add_xupdate(LUser, LServer, Hash, odbc) -> Username = ejabberd_odbc:escape(LUser), SHash = ejabberd_odbc:escape(Hash), F = fun () -> odbc_queries:update_t(<<"vcard_xupdate">>, [<<"username">>, <<"hash">>], [Username, SHash], [<<"username='">>, Username, <<"'">>]) end, ejabberd_odbc:sql_transaction(LServer, F). get_xupdate(LUser, LServer) -> get_xupdate(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). get_xupdate(LUser, LServer, mnesia) -> case mnesia:dirty_read(vcard_xupdate, {LUser, LServer}) of [#vcard_xupdate{hash = Hash}] -> Hash; _ -> undefined end; get_xupdate(LUser, LServer, riak) -> case ejabberd_riak:get(vcard_xupdate, vcard_xupdate_schema(), {LUser, LServer}) of {ok, #vcard_xupdate{hash = Hash}} -> Hash; _ -> undefined end; get_xupdate(LUser, LServer, odbc) -> Username = ejabberd_odbc:escape(LUser), case ejabberd_odbc:sql_query(LServer, [<<"select hash from vcard_xupdate where " "username='">>, Username, <<"';">>]) of {selected, [<<"hash">>], [[Hash]]} -> Hash; _ -> undefined end. remove_xupdate(LUser, LServer) -> remove_xupdate(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). remove_xupdate(LUser, LServer, mnesia) -> F = fun () -> mnesia:delete({vcard_xupdate, {LUser, LServer}}) end, mnesia:transaction(F); remove_xupdate(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete(vcard_xupdate, {LUser, LServer})}; remove_xupdate(LUser, LServer, odbc) -> Username = ejabberd_odbc:escape(LUser), F = fun () -> ejabberd_odbc:sql_query_t([<<"delete from vcard_xupdate where username='">>, Username, <<"';">>]) end, ejabberd_odbc:sql_transaction(LServer, F). %%%---------------------------------------------------------------------- %%% Presence stanza rebuilding %%%---------------------------------------------------------------------- presence_with_xupdate(#xmlel{name = <<"presence">>, attrs = Attrs, children = Els}, User, Host) -> XPhotoEl = build_xphotoel(User, Host), Els2 = presence_with_xupdate2(Els, [], XPhotoEl), #xmlel{name = <<"presence">>, attrs = Attrs, children = Els2}. presence_with_xupdate2([], Els2, XPhotoEl) -> lists:reverse([XPhotoEl | Els2]); %% This clause assumes that the x element contains only the XMLNS attribute: presence_with_xupdate2([#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_VCARD_UPDATE}]} | Els], Els2, XPhotoEl) -> presence_with_xupdate2(Els, Els2, XPhotoEl); presence_with_xupdate2([El | Els], Els2, XPhotoEl) -> presence_with_xupdate2(Els, [El | Els2], XPhotoEl). build_xphotoel(User, Host) -> Hash = get_xupdate(User, Host), PhotoSubEls = case Hash of Hash when is_binary(Hash) -> [{xmlcdata, Hash}]; _ -> [] end, PhotoEl = [#xmlel{name = <<"photo">>, attrs = [], children = PhotoSubEls}], #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_VCARD_UPDATE}], children = PhotoEl}. vcard_xupdate_schema() -> {record_info(fields, vcard_xupdate), #vcard_xupdate{}}. update_table() -> Fields = record_info(fields, vcard_xupdate), case mnesia:table_info(vcard_xupdate, attributes) of Fields -> ejabberd_config:convert_table_to_binary( vcard_xupdate, Fields, set, fun(#vcard_xupdate{us = {U, _}}) -> U end, fun(#vcard_xupdate{us = {U, S}, hash = Hash} = R) -> R#vcard_xupdate{us = {iolist_to_binary(U), iolist_to_binary(S)}, hash = iolist_to_binary(Hash)} end); _ -> ?INFO_MSG("Recreating vcard_xupdate table", []), mnesia:transform_table(vcard_xupdate, ignore, Fields) end. export(_Server) -> [{vcard_xupdate, fun(Host, #vcard_xupdate{us = {LUser, LServer}, hash = Hash}) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), SHash = ejabberd_odbc:escape(Hash), [[<<"delete from vcard_xupdate where username='">>, Username, <<"';">>], [<<"insert into vcard_xupdate(username, " "hash) values ('">>, Username, <<"', '">>, SHash, <<"');">>]]; (_Host, _R) -> [] end}]. import(LServer) -> [{<<"select username, hash from vcard_xupdate;">>, fun([LUser, Hash]) -> #vcard_xupdate{us = {LUser, LServer}, hash = Hash} end}]. import(_LServer, mnesia, #vcard_xupdate{} = R) -> mnesia:dirty_write(R); 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]. ejabberd-16.01/src/ejabberd_system_monitor.erl0000644000232200023220000002777712645157216022066 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% File : ejabberd_system_monitor.erl %%% Author : Alexey Shchepin %%% Description : Ejabberd watchdog %%% Created : 21 Mar 2007 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_system_monitor). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_server). %% API -export([start_link/0, process_command/3, register_hook/1, process_remote_command/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -record(state, {}). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link() -> LH = ejabberd_config:get_option( watchdog_large_heap, fun(I) when is_integer(I), I > 0 -> I end, 1000000), Opts = [{large_heap, LH}], gen_server:start_link({local, ?MODULE}, ?MODULE, Opts, []). process_command(From, To, Packet) -> case To of #jid{luser = <<"">>, lresource = <<"watchdog">>} -> #xmlel{name = Name} = Packet, case Name of <<"message">> -> LFrom = jid:tolower(jid:remove_resource(From)), case lists:member(LFrom, get_admin_jids()) of true -> Body = xml:get_path_s(Packet, [{elem, <<"body">>}, cdata]), spawn(fun () -> process_flag(priority, high), process_command1(From, To, Body) end), stop; false -> ok end; _ -> ok end; _ -> ok end. register_hook(Host) -> ejabberd_hooks:add(local_send_to_resource_hook, Host, ?MODULE, process_command, 50). %%==================================================================== %% gen_server callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- init(Opts) -> LH = proplists:get_value(large_heap, Opts), process_flag(priority, high), erlang:system_monitor(self(), [{large_heap, LH}]), lists:foreach(fun register_hook/1, ?MYHOSTS), {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({get, large_heap}, _From, State) -> {reply, get_large_heap(), State}; handle_call({set, large_heap, NewValue}, _From, State) -> MonSettings = erlang:system_monitor(self(), [{large_heap, NewValue}]), OldLH = get_large_heap(MonSettings), NewLH = get_large_heap(), {reply, {lh_changed, OldLH, NewLH}, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. get_large_heap() -> MonSettings = erlang:system_monitor(), get_large_heap(MonSettings). get_large_heap(MonSettings) -> {_MonitorPid, Options} = MonSettings, proplists:get_value(large_heap, Options). %%-------------------------------------------------------------------- %% 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({monitor, Pid, large_heap, Info}, State) -> spawn(fun () -> process_flag(priority, high), process_large_heap(Pid, Info) 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. %%-------------------------------------------------------------------- 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 %%-------------------------------------------------------------------- process_large_heap(Pid, Info) -> Host = (?MYNAME), JIDs = get_admin_jids(), DetailedInfo = detailed_info(Pid), Body = iolist_to_binary( io_lib:format("(~w) The process ~w is consuming too " "much memory:~n~p~n~s", [node(), Pid, Info, DetailedInfo])), From = jid:make(<<"">>, Host, <<"watchdog">>), lists:foreach(fun (JID) -> send_message(From, jid:make(JID), Body) end, JIDs). send_message(From, To, Body) -> ejabberd_router:route(From, To, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Body}]}]}). get_admin_jids() -> ejabberd_config:get_option( watchdog_admins, fun(JIDs) -> [jid:tolower( jid:from_string( iolist_to_binary(S))) || S <- JIDs] end, []). detailed_info(Pid) -> case process_info(Pid, dictionary) of {dictionary, Dict} -> case lists:keysearch('$ancestors', 1, Dict) of {value, {'$ancestors', [Sup | _]}} -> case Sup of ejabberd_c2s_sup -> c2s_info(Pid); ejabberd_s2s_out_sup -> s2s_out_info(Pid); ejabberd_service_sup -> service_info(Pid); _ -> detailed_info1(Pid) end; _ -> detailed_info1(Pid) end; _ -> detailed_info1(Pid) end. detailed_info1(Pid) -> io_lib:format("~p", [[process_info(Pid, current_function), process_info(Pid, initial_call), process_info(Pid, message_queue_len), process_info(Pid, links), process_info(Pid, dictionary), process_info(Pid, heap_size), process_info(Pid, stack_size)]]). c2s_info(Pid) -> [<<"Process type: c2s">>, check_send_queue(Pid), <<"\n">>, io_lib:format("Command to kill this process: kill ~s ~w", [iolist_to_binary(atom_to_list(node())), Pid])]. s2s_out_info(Pid) -> FromTo = mnesia:dirty_select(s2s, [{{s2s, '$1', Pid, '_'}, [], ['$1']}]), [<<"Process type: s2s_out">>, case FromTo of [{From, To}] -> <<"\n", (io_lib:format("S2S connection: from ~s to ~s", [From, To]))/binary>>; _ -> <<"">> end, check_send_queue(Pid), <<"\n">>, io_lib:format("Command to kill this process: kill ~s ~w", [iolist_to_binary(atom_to_list(node())), Pid])]. service_info(Pid) -> Routes = mnesia:dirty_select(route, [{{route, '$1', Pid, '_'}, [], ['$1']}]), [<<"Process type: s2s_out">>, case Routes of [Route] -> <<"\nServiced domain: ", Route/binary>>; _ -> <<"">> end, check_send_queue(Pid), <<"\n">>, io_lib:format("Command to kill this process: kill ~s ~w", [iolist_to_binary(atom_to_list(node())), Pid])]. check_send_queue(Pid) -> case {process_info(Pid, current_function), process_info(Pid, message_queue_len)} of {{current_function, MFA}, {message_queue_len, MLen}} -> if MLen > 100 -> case MFA of {prim_inet, send, 2} -> <<"\nPossible reason: the process is blocked " "trying to send data over its TCP connection.">>; {M, F, A} -> [<<"\nPossible reason: the process can't " "process messages faster than they arrive. ">>, io_lib:format("Current function is ~w:~w/~w", [M, F, A])] end; true -> <<"">> end; _ -> <<"">> end. process_command1(From, To, Body) -> process_command2(str:tokens(Body, <<" ">>), From, To). process_command2([<<"kill">>, SNode, SPid], From, To) -> Node = jlib:binary_to_atom(SNode), remote_command(Node, [kill, SPid], From, To); process_command2([<<"showlh">>, SNode], From, To) -> Node = jlib:binary_to_atom(SNode), remote_command(Node, [showlh], From, To); process_command2([<<"setlh">>, SNode, NewValueString], From, To) -> Node = jlib:binary_to_atom(SNode), NewValue = jlib:binary_to_integer(NewValueString), remote_command(Node, [setlh, NewValue], From, To); process_command2([<<"help">>], From, To) -> send_message(To, From, help()); process_command2(_, From, To) -> send_message(To, From, help()). help() -> <<"Commands:\n kill \n showlh " "\n setlh ">>. remote_command(Node, Args, From, To) -> Message = case ejabberd_cluster:call(Node, ?MODULE, process_remote_command, [Args]) of {badrpc, Reason} -> io_lib:format("Command failed:~n~p", [Reason]); Result -> Result end, send_message(To, From, iolist_to_binary(Message)). process_remote_command([kill, SPid]) -> exit(list_to_pid(SPid), kill), <<"ok">>; process_remote_command([showlh]) -> Res = gen_server:call(ejabberd_system_monitor, {get, large_heap}), io_lib:format("Current large heap: ~p", [Res]); process_remote_command([setlh, NewValue]) -> {lh_changed, OldLH, NewLH} = gen_server:call(ejabberd_system_monitor, {set, large_heap, 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) -> [jid:tolower(jid:from_string(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]. ejabberd-16.01/src/ext_mod.erl0000644000232200023220000005202312645157216016572 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ext_mod.erl %%% Author : Christophe Romain %%% Purpose : external modules management %%% Created : 19 Feb 2015 by Christophe Romain %%% %%% %%% ejabberd, Copyright (C) 2006-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(ext_mod). -behaviour(ejabberd_config). -author("Christophe Romain "). -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, config_dir/0, opt_type/1]). -include("ejabberd_commands.hrl"). -include("logger.hrl"). -define(REPOS, "https://github.com/processone/ejabberd-contrib"). %% -- ejabberd init and commands start() -> [code:add_patha(module_ebin_dir(Module)) || {Module, _} <- installed()], application:start(inets), ejabberd_commands:register_commands(commands()). stop() -> ejabberd_commands:unregister_commands(commands()). commands() -> [#ejabberd_commands{name = modules_update_specs, tags = [admin,modules], desc = "", longdesc = "", module = ?MODULE, function = update, args = [], result = {res, integer}}, #ejabberd_commands{name = modules_available, tags = [admin,modules], desc = "", longdesc = "", module = ?MODULE, function = available_command, args = [], result = {modules, {list, {module, {tuple, [{name, atom}, {summary, string}]}}}}}, #ejabberd_commands{name = modules_installed, tags = [admin,modules], desc = "", longdesc = "", module = ?MODULE, function = installed_command, args = [], result = {modules, {list, {module, {tuple, [{name, atom}, {summary, string}]}}}}}, #ejabberd_commands{name = module_install, tags = [admin,modules], desc = "", longdesc = "", module = ?MODULE, function = install, args = [{module, binary}], result = {res, integer}}, #ejabberd_commands{name = module_uninstall, tags = [admin,modules], desc = "", longdesc = "", module = ?MODULE, function = uninstall, args = [{module, binary}], result = {res, integer}}, #ejabberd_commands{name = module_upgrade, tags = [admin,modules], desc = "", longdesc = "", module = ?MODULE, function = upgrade, args = [{module, binary}], result = {res, integer}}, #ejabberd_commands{name = module_check, tags = [admin,modules], desc = "", longdesc = "", module = ?MODULE, function = check, args = [{module, binary}], result = {res, integer}} ]. %% -- public modules functions update() -> add_sources(?REPOS), Res = lists:foldl(fun({Package, Spec}, Acc) -> Path = proplists:get_value(url, Spec, ""), 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(), "*/*"), Standalone = modules_spec(sources_dir(), "*"), lists:keysort(1, lists:foldl(fun({Key, Val}, Acc) -> lists:keystore(Key, 1, Acc, {Key, Val}) end, Jungle, Standalone)). available(Module) when is_atom(Module) -> available(jlib:atom_to_binary(Module)); available(Package) when is_binary(Package) -> Available = [jlib:atom_to_binary(K) || K<-proplists:get_keys(available())], lists:member(Package, Available). available_command() -> [short_spec(Item) || Item <- available()]. installed() -> modules_spec(modules_dir(), "*"). installed(Module) when is_atom(Module) -> installed(jlib:atom_to_binary(Module)); installed(Package) when is_binary(Package) -> Installed = [jlib:atom_to_binary(K) || K<-proplists:get_keys(installed())], lists:member(Package, Installed). installed_command() -> [short_spec(Item) || Item <- installed()]. install(Module) when is_atom(Module) -> install(jlib:atom_to_binary(Module)); install(Package) when is_binary(Package) -> Spec = [S || {Mod, S} <- available(), jlib:atom_to_binary(Mod)==Package], case {Spec, installed(Package), is_contrib_allowed()} of {_, _, false} -> {error, not_allowed}; {[], _, _} -> {error, not_available}; {_, true, _} -> {error, conflict}; {[Attrs], _, _} -> Module = jlib:binary_to_atom(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)), Error end end. uninstall(Module) when is_atom(Module) -> uninstall(jlib:atom_to_binary(Module)); uninstall(Package) when is_binary(Package) -> case installed(Package) of true -> Module = jlib:binary_to_atom(Package), [catch gen_mod:stop_module(Host, Module) || Host <- ejabberd_config:get_myhosts()], code:purge(Module), code:delete(Module), code:del_path(module_ebin_dir(Module)), delete_path(module_lib_dir(Module)), ejabberd_config:reload_file(); false -> {error, not_installed} end. upgrade() -> [{Package, upgrade(Package)} || {Package, _Spec} <- installed()]. upgrade(Module) when is_atom(Module) -> upgrade(jlib:atom_to_binary(Module)); upgrade(Package) when is_binary(Package) -> uninstall(Package), install(Package). add_sources(Path) when is_list(Path) -> add_sources(iolist_to_binary(module_name(Path)), Path). add_sources(_, "") -> {error, no_url}; add_sources(Module, Path) when is_atom(Module), is_list(Path) -> add_sources(jlib:atom_to_binary(Module), Path); add_sources(Package, Path) when is_binary(Package), is_list(Path) -> DestDir = sources_dir(), RepDir = filename:join(DestDir, module_name(Path)), delete_path(RepDir), case filelib:ensure_dir(RepDir) of ok -> case {string:left(Path, 4), string:right(Path, 2)} of {"http", "ip"} -> extract(zip, geturl(Path), DestDir); {"http", "gz"} -> extract(tar, geturl(Path), DestDir); {"http", _} -> extract_url(Path, DestDir); {"git@", _} -> extract_github_master(Path, DestDir); {_, "ip"} -> extract(zip, Path, DestDir); {_, "gz"} -> extract(tar, Path, DestDir); _ -> {error, unsupported_source} end; Error -> Error end. del_sources(Module) when is_atom(Module) -> del_sources(jlib:atom_to_binary(Module)); del_sources(Package) when is_binary(Package) -> case uninstall(Package) of ok -> SrcDir = module_src_dir(jlib:binary_to_atom(Package)), delete_path(SrcDir); Error -> Error end. check(Module) when is_atom(Module) -> check(jlib:atom_to_binary(Module)); check(Package) when is_binary(Package) -> case {available(Package), installed(Package)} of {false, _} -> {error, not_available}; {_, false} -> Status = install(Package), uninstall(Package), case Status of ok -> check_sources(jlib:binary_to_atom(Package)); Error -> Error end; _ -> check_sources(jlib:binary_to_atom(Package)) end. %% -- archives and variables functions geturl(Url) -> geturl(Url, []). geturl(Url, UsrOpts) -> geturl(Url, [], UsrOpts). geturl(Url, Hdrs, UsrOpts) -> Host = case getenv("PROXY_SERVER", "", ":") of [H, Port] -> [{proxy_host, H}, {proxy_port, list_to_integer(Port)}]; [H] -> [{proxy_host, H}, {proxy_port, 8080}]; _ -> [] end, User = case getenv("PROXY_USER", "", [4]) of [U, Pass] -> [{proxy_user, U}, {proxy_password, Pass}]; _ -> [] end, case httpc:request(get, {Url, Hdrs}, Host++User++UsrOpts, []) of {ok, {{_, 200, _}, Headers, Response}} -> {ok, Headers, Response}; {ok, {{_, Code, _}, _Headers, Response}} -> {error, {Code, Response}}; {error, Reason} -> {error, Reason} end. getenv(Env) -> getenv(Env, ""). getenv(Env, Default) -> case os:getenv(Env) of false -> Default; "" -> Default; Value -> Value end. getenv(Env, Default, Separator) -> string:tokens(getenv(Env, Default), Separator). extract(zip, {ok, _, Body}, DestDir) -> extract(zip, iolist_to_binary(Body), DestDir); extract(tar, {ok, _, Body}, DestDir) -> extract(tar, {binary, iolist_to_binary(Body)}, DestDir); extract(_, {error, Reason}, _) -> {error, Reason}; extract(zip, Zip, DestDir) -> case zip:extract(Zip, [{cwd, DestDir}]) of {ok, _} -> ok; Error -> Error end; extract(tar, Tar, DestDir) -> erl_tar:extract(Tar, [compressed, {cwd, DestDir}]). extract_url(Path, DestDir) -> hd([extract_github_master(Path, DestDir) || string:str(Path, "github") > 0] ++[{error, unsupported_source}]). extract_github_master(Repos, DestDir) -> 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); Error -> Error end. 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 true -> [delete_path(SubPath) || SubPath <- filelib:wildcard(Path++"/*")], file:del_dir(Path); false -> file:delete(Path) end. modules_dir() -> DefaultDir = filename:join(getenv("HOME"), ".ejabberd-modules"), getenv("CONTRIB_MODULES_PATH", DefaultDir). 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). module_ebin_dir(Package) -> filename:join(module_lib_dir(Package), "ebin"). module_src_dir(Package) -> Rep = module_name(Package), SrcDir = sources_dir(), Standalone = filelib:wildcard(Rep, SrcDir), Jungle = filelib:wildcard("*/"++Rep, SrcDir), case Standalone++Jungle of [RepDir|_] -> filename:join(SrcDir, RepDir); _ -> filename:join(SrcDir, Rep) end. module_name(Id) -> filename:basename(filename:rootname(Id)). module(Id) -> jlib:binary_to_atom(iolist_to_binary(module_name(Id))). module_spec(Spec) -> [{path, filename:dirname(Spec)} | case consult(Spec) of {ok, Meta} -> Meta; _ -> [] end]. modules_spec(Dir, Path) -> Wildcard = filename:join(Path, "*.spec"), lists:sort( [{module(Match), module_spec(filename:join(Dir, Match))} || Match <- filelib:wildcard(Wildcard, Dir)]). short_spec({Module, Attrs}) when is_atom(Module), is_list(Attrs) -> {Module, proplists:get_value(summary, Attrs, "")}. is_contrib_allowed() -> ejabberd_config:get_option(allow_contrib_modules, fun(false) -> false; (no) -> false; (_) -> true end, true). %% -- build functions check_sources(Module) -> SrcDir = module_src_dir(Module), SpecFile = filename:flatten([Module, ".spec"]), {ok, Dir} = file:get_cwd(), file:set_cwd(SrcDir), HaveSrc = case filelib:is_dir("src") or filelib:is_dir("lib") of true -> []; false -> [{missing, "src (Erlang) or lib (Elixir) sources directory"}] end, DirCheck = lists:foldl( fun({Type, Name}, Acc) -> case filelib:Type(Name) of true -> Acc; false -> [{missing, Name}|Acc] end end, HaveSrc, [{is_file, "README.txt"}, {is_file, "COPYING"}, {is_file, SpecFile}]), SpecCheck = case consult(SpecFile) of {ok, Spec} -> lists:foldl( fun(Key, Acc) -> case lists:keysearch(Key, 1, Spec) of false -> [{missing_meta, Key}|Acc]; {value, {Key, [_NoEmpty|_]}} -> Acc; {value, {Key, Val}} -> [{invalid_meta, {Key, Val}}|Acc] end end, [], [author, summary, home, url]); {error, Error} -> [{invalid_spec, Error}] end, file:set_cwd(Dir), Result = DirCheck ++ SpecCheck, case Result of [] -> ok; _ -> {error, Result} end. compile_and_install(Module, Spec) -> SrcDir = module_src_dir(Module), LibDir = module_lib_dir(Module), case filelib:is_dir(SrcDir) of true -> {ok, Dir} = file:get_cwd(), file:set_cwd(SrcDir), 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; false -> Path = proplists:get_value(url, Spec, ""), case add_sources(Module, Path) of ok -> compile_and_install(Module, Spec); Error -> Error 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, ".")), 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], ExtLib = [{d, 'NO_EXT_LIB'} || filelib:is_file(XmlHrl)], 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; {ok, _, _, _} -> ok; error -> {error, {compilation_failed, File}}; Error -> Error end || File <- filelib:wildcard("src/*.erl")], case lists:dropwhile( fun(ok) -> true; (_) -> false end, Result) of [] -> ok; [Error|_] -> Error end. 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. %% -- 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) -> case p1_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)} end. 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]. ejabberd-16.01/src/ejabberd_hooks.erl0000644000232200023220000003203312645157216020073 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_hooks.erl %%% Author : Alexey Shchepin %%% Purpose : Manage hooks %%% Created : 8 Aug 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_hooks). -author('alexey@process-one.net'). -behaviour(gen_server). %% External exports -export([start_link/0, add/3, add/4, add/5, add_dist/5, add_dist/6, delete/3, delete/4, delete/5, delete_dist/5, delete_dist/6, run/2, run/3, run_fold/3, run_fold/4, get_handlers/2]). -export([delete_all_hooks/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, code_change/3, handle_info/2, terminate/2]). -include("logger.hrl"). -record(state, {}). -type local_hook() :: { Seq :: integer(), Module :: atom(), Function :: atom()}. -type distributed_hook() :: { Seq :: integer(), Node :: atom(), Module :: atom(), Function :: atom()}. %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ejabberd_hooks}, ejabberd_hooks, [], []). -spec add(atom(), fun(), number()) -> ok. %% @doc See add/4. add(Hook, Function, Seq) when is_function(Function) -> add(Hook, global, undefined, Function, Seq). -spec add(atom(), HostOrModule :: binary() | atom(), fun() | atom() , number()) -> ok. add(Hook, Host, Function, Seq) when is_function(Function) -> add(Hook, Host, undefined, Function, Seq); %% @doc Add a module and function to this hook. %% The integer sequence is used to sort the calls: low number is called before high number. add(Hook, Module, Function, Seq) -> add(Hook, global, Module, Function, Seq). -spec add(atom(), binary() | global, atom(), atom() | fun(), number()) -> ok. add(Hook, Host, Module, Function, Seq) -> gen_server:call(ejabberd_hooks, {add, Hook, Host, Module, Function, Seq}). -spec add_dist(atom(), atom(), atom(), atom() | fun(), number()) -> ok. add_dist(Hook, Node, Module, Function, Seq) -> gen_server:call(ejabberd_hooks, {add, Hook, global, Node, Module, Function, Seq}). -spec add_dist(atom(), binary() | global, atom(), atom(), atom() | fun(), number()) -> ok. add_dist(Hook, Host, Node, Module, Function, Seq) -> gen_server:call(ejabberd_hooks, {add, Hook, Host, Node, Module, Function, Seq}). -spec delete(atom(), fun(), number()) -> ok. %% @doc See del/4. delete(Hook, Function, Seq) when is_function(Function) -> delete(Hook, global, undefined, Function, Seq). -spec delete(atom(), binary() | atom(), atom() | fun(), number()) -> ok. delete(Hook, Host, Function, Seq) when is_function(Function) -> delete(Hook, Host, undefined, Function, Seq); %% @doc Delete a module and function from this hook. %% It is important to indicate exactly the same information than when the call was added. delete(Hook, Module, Function, Seq) -> delete(Hook, global, Module, Function, Seq). -spec delete(atom(), binary() | global, atom(), atom() | fun(), number()) -> ok. delete(Hook, Host, Module, Function, Seq) -> gen_server:call(ejabberd_hooks, {delete, Hook, Host, Module, Function, Seq}). -spec delete_dist(atom(), atom(), atom(), atom() | fun(), number()) -> ok. delete_dist(Hook, Node, Module, Function, Seq) -> delete_dist(Hook, global, Node, Module, Function, Seq). -spec delete_dist(atom(), binary() | global, atom(), atom(), atom() | fun(), number()) -> ok. delete_dist(Hook, Host, Node, Module, Function, Seq) -> gen_server:call(ejabberd_hooks, {delete, Hook, Host, Node, Module, Function, Seq}). -spec delete_all_hooks() -> true. %% @doc Primarily for testing / instrumentation delete_all_hooks() -> gen_server:call(ejabberd_hooks, {delete_all}). -spec get_handlers(atom(), binary() | global) -> [local_hook() | distributed_hook()]. %% @doc Returns currently set handler for hook name get_handlers(Hookname, Host) -> gen_server:call(ejabberd_hooks, {get_handlers, Hookname, Host}). -spec run(atom(), list()) -> ok. %% @doc Run the calls of this hook in order, don't care about function results. %% If a call returns stop, no more calls are performed. run(Hook, Args) -> run(Hook, global, Args). -spec run(atom(), binary() | global, list()) -> ok. run(Hook, Host, Args) -> case ets:lookup(hooks, {Hook, Host}) of [{_, Ls}] -> run1(Ls, Hook, Args); [] -> ok end. -spec run_fold(atom(), any(), list()) -> any(). %% @doc Run the calls of this hook in order. %% The arguments passed to the function are: [Val | Args]. %% The result of a call is used as Val for the next call. %% If a call returns 'stop', no more calls are performed and 'stopped' is returned. %% If a call returns {stop, NewVal}, no more calls are performed and NewVal is returned. run_fold(Hook, Val, Args) -> run_fold(Hook, global, Val, Args). -spec run_fold(atom(), binary() | global, any(), list()) -> any(). run_fold(Hook, Host, Val, Args) -> case ets:lookup(hooks, {Hook, Host}) of [{_, Ls}] -> run_fold1(Ls, Hook, Val, Args); [] -> Val end. %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%---------------------------------------------------------------------- init([]) -> ets:new(hooks, [named_table]), {ok, #state{}}. %%---------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_call({add, Hook, Host, Module, Function, Seq}, _From, State) -> HookFormat = {Seq, Module, Function}, Reply = handle_add(Hook, Host, HookFormat), {reply, Reply, State}; handle_call({add, Hook, Host, Node, Module, Function, Seq}, _From, State) -> HookFormat = {Seq, Node, Module, Function}, Reply = handle_add(Hook, Host, HookFormat), {reply, Reply, State}; handle_call({delete, Hook, Host, Module, Function, Seq}, _From, State) -> HookFormat = {Seq, Module, Function}, Reply = handle_delete(Hook, Host, HookFormat), {reply, Reply, State}; handle_call({delete, Hook, Host, Node, Module, Function, Seq}, _From, State) -> HookFormat = {Seq, Node, Module, Function}, Reply = handle_delete(Hook, Host, HookFormat), {reply, Reply, State}; handle_call({get_handlers, Hook, Host}, _From, State) -> Reply = case ets:lookup(hooks, {Hook, Host}) of [{_, Handlers}] -> Handlers; [] -> [] end, {reply, Reply, State}; handle_call({delete_all}, _From, State) -> Reply = ets:delete_all_objects(hooks), {reply, Reply, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. -spec handle_add(atom(), atom(), local_hook() | distributed_hook()) -> ok. %% in-memory storage operation: Handle adding hook in ETS table handle_add(Hook, Host, El) -> case ets:lookup(hooks, {Hook, Host}) of [{_, Ls}] -> case lists:member(El, Ls) of true -> ok; false -> NewLs = lists:merge(Ls, [El]), ets:insert(hooks, {{Hook, Host}, NewLs}), ok end; [] -> NewLs = [El], ets:insert(hooks, {{Hook, Host}, NewLs}), ok end. -spec handle_delete(atom(), atom(), local_hook() | distributed_hook()) -> ok. %% in-memory storage operation: Handle deleting hook from ETS table handle_delete(Hook, Host, El) -> case ets:lookup(hooks, {Hook, Host}) of [{_, Ls}] -> NewLs = lists:delete(El, Ls), ets:insert(hooks, {{Hook, Host}, NewLs}), ok; [] -> ok end. %%---------------------------------------------------------------------- %% Func: handle_cast/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_cast(_Msg, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_info(_Info, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any (ignored by gen_server) %%---------------------------------------------------------------------- terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- -spec run1([local_hook()|distributed_hook()], atom(), list()) -> ok. run1([], _Hook, _Args) -> ok; %% Run distributed hook on target node. %% 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 ejabberd_cluster:call(Node, Module, Function, Args) of timeout -> ?ERROR_MSG("Timeout on RPC to ~p~nrunning hook: ~p", [Node, {Hook, Args}]), run1(Ls, Hook, Args); {badrpc, Reason} -> ?ERROR_MSG("Bad RPC error to ~p: ~p~nrunning hook: ~p", [Node, Reason, {Hook, Args}]), run1(Ls, Hook, Args); stop -> ?INFO_MSG("~nThe process ~p in node ~p ran a hook in node ~p.~n" "Stop.", [self(), node(), Node]), % debug code ok; Res -> ?INFO_MSG("~nThe process ~p in node ~p ran a hook in node ~p.~n" "The response is:~n~s", [self(), node(), Node, Res]), % debug code run1(Ls, Hook, Args) end; run1([{_Seq, Module, Function} | Ls], Hook, Args) -> Res = safe_apply(Module, Function, Args), case Res of {'EXIT', Reason} -> ?ERROR_MSG("~p~nrunning hook: ~p", [Reason, {Hook, Args}]), run1(Ls, Hook, Args); stop -> ok; _ -> run1(Ls, Hook, Args) end. run_fold1([], _Hook, Val, _Args) -> Val; run_fold1([{_Seq, Node, Module, Function} | Ls], Hook, Val, Args) -> 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}]), run_fold1(Ls, Hook, Val, Args); timeout -> ?ERROR_MSG("Timeout on RPC to ~p~nrunning hook: ~p", [Node, {Hook, Args}]), run_fold1(Ls, Hook, Val, Args); stop -> stopped; {stop, NewVal} -> ?INFO_MSG("~nThe process ~p in node ~p ran a hook in node ~p.~n" "Stop, and the NewVal is:~n~p", [self(), node(), Node, NewVal]), % debug code NewVal; NewVal -> ?INFO_MSG("~nThe process ~p in node ~p ran a hook in node ~p.~n" "The NewVal is:~n~p", [self(), node(), Node, NewVal]), % debug code run_fold1(Ls, Hook, NewVal, Args) end; run_fold1([{_Seq, Module, Function} | Ls], Hook, Val, Args) -> Res = safe_apply(Module, Function, [Val | Args]), case Res of {'EXIT', Reason} -> ?ERROR_MSG("~p~nrunning hook: ~p", [Reason, {Hook, Args}]), run_fold1(Ls, Hook, Val, Args); stop -> stopped; {stop, NewVal} -> NewVal; NewVal -> run_fold1(Ls, Hook, NewVal, Args) end. safe_apply(Module, Function, Args) -> if is_function(Function) -> catch apply(Function, Args); true -> catch apply(Module, Function, Args) end. ejabberd-16.01/src/mod_proxy65.erl0000644000232200023220000000742312645157216017332 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_proxy65.erl %%% Author : Evgeniy Khramtsov %%% Purpose : Main supervisor. %%% Created : 12 Oct 2006 by Evgeniy 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(mod_proxy65). -author('xram@jabber.ru'). -protocol({xep, 65, '1.8'}). -behaviour(gen_mod). -behaviour(supervisor). %% gen_mod callbacks. -export([start/2, stop/1, transform_module_options/1]). %% supervisor callbacks. -export([init/1]). -export([start_link/2, mod_opt_type/1]). -define(PROCNAME, ejabberd_mod_proxy65). start(Host, Opts) -> case mod_proxy65_service:add_listener(Host, Opts) of {error, _} = Err -> erlang:error(Err); _ -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, transient, infinity, supervisor, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec) end. stop(Host) -> mod_proxy65_service:delete_listener(Host), Proc = gen_mod:get_module_proc(Host, ?PROCNAME), supervisor:terminate_child(ejabberd_sup, Proc), supervisor:delete_child(ejabberd_sup, Proc). start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), supervisor:start_link({local, Proc}, ?MODULE, [Host, Opts]). transform_module_options(Opts) -> mod_proxy65_service:transform_module_options(Opts). init([Host, Opts]) -> Service = {mod_proxy65_service, {mod_proxy65_service, start_link, [Host, Opts]}, transient, 5000, worker, [mod_proxy65_service]}, StreamSupervisor = {ejabberd_mod_proxy65_sup, {ejabberd_tmp_sup, start_link, [gen_mod:get_module_proc(Host, ejabberd_mod_proxy65_sup), mod_proxy65_stream]}, transient, infinity, supervisor, [ejabberd_tmp_sup]}, StreamManager = {mod_proxy65_sm, {mod_proxy65_sm, start_link, [Host, Opts]}, transient, 5000, worker, [mod_proxy65_sm]}, {ok, {{one_for_one, 10, 1}, [StreamManager, StreamSupervisor, Service]}}. 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]. ejabberd-16.01/src/mod_irc.erl0000644000232200023220000013432312645157216016553 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_irc.erl %%% Author : Alexey Shchepin %%% Purpose : IRC transport %%% Created : 15 Feb 2003 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(mod_irc). -author('alexey@process-one.net'). -behaviour(gen_server). -behaviour(gen_mod). %% API -export([start_link/2, start/2, stop/1, export/1, import/1, import/3, closed_connection/3, get_connection_params/3]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("adhoc.hrl"). -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-15">>, <<"iso8859-1">>, <<"iso8859-2">>, <<"utf-8">>, <<"utf-8+latin-1">>]). -type conn_param() :: {binary(), binary(), inet:port_number(), binary()} | {binary(), binary(), inet:port_number()} | {binary(), binary()} | {binary()}. -record(irc_connection, {jid_server_host = {#jid{}, <<"">>, <<"">>} :: {jid(), binary(), binary()}, pid = self() :: pid()}). -record(irc_custom, {us_host = {{<<"">>, <<"">>}, <<"">>} :: {{binary(), binary()}, binary()}, data = [] :: [{username, binary()} | {connections_params, [conn_param()]}]}). -record(state, {host = <<"">> :: binary(), server_host = <<"">> :: binary(), access = all :: atom()}). -define(PROCNAME, ejabberd_mod_irc). %%==================================================================== %% 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) -> start_supervisor(Host), Proc = gen_mod:get_module_proc(Host, ?PROCNAME), ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, temporary, 1000, worker, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop(Host) -> stop_supervisor(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 %%-------------------------------------------------------------------- init([Host, Opts]) -> ejabberd:start_app(p1_iconv), MyHost = gen_mod:get_opt_host(Host, Opts, <<"irc.@HOST@">>), case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(irc_custom, [{disc_copies, [node()]}, {attributes, record_info(fields, irc_custom)}]), update_table(); _ -> ok end, Access = gen_mod:get_opt(access, Opts, fun(A) when is_atom(A) -> A end, all), catch ets:new(irc_connection, [named_table, public, {keypos, #irc_connection.jid_server_host}]), ejabberd_router:register_route(MyHost), {ok, #state{host = MyHost, server_host = Host, access = Access}}. %%-------------------------------------------------------------------- %% 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}. %%-------------------------------------------------------------------- %% 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} = State) -> case catch do_route(Host, ServerHost, Access, 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. %%-------------------------------------------------------------------- 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}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- start_supervisor(Host) -> Proc = gen_mod:get_module_proc(Host, ejabberd_mod_irc_sup), ChildSpec = {Proc, {ejabberd_tmp_sup, start_link, [Proc, mod_irc_connection]}, permanent, infinity, supervisor, [ejabberd_tmp_sup]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop_supervisor(Host) -> Proc = gen_mod:get_module_proc(Host, ejabberd_mod_irc_sup), supervisor:terminate_child(ejabberd_sup, Proc), supervisor:delete_child(ejabberd_sup, Proc). do_route(Host, ServerHost, Access, From, To, Packet) -> case acl:match_rule(ServerHost, Access, From) of allow -> do_route1(Host, ServerHost, From, To, Packet); _ -> #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)), ejabberd_router:route(To, From, Err) end. do_route1(Host, ServerHost, From, To, Packet) -> #jid{user = ChanServ, resource = Resource} = To, #xmlel{} = Packet, case ChanServ of <<"">> -> case Resource of <<"">> -> case jlib:iq_query_info(Packet) of #iq{type = get, xmlns = (?NS_DISCO_INFO) = XMLNS, sub_el = SubEl, lang = Lang} = IQ -> Node = xml:get_tag_attr_s(<<"node">>, SubEl), Info = ejabberd_hooks:run_fold(disco_info, ServerHost, [], [ServerHost, ?MODULE, <<"">>, <<"">>]), case iq_disco(ServerHost, Node, Lang) of [] -> Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = []}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); DiscoInfo -> Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = DiscoInfo ++ Info}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)) end; #iq{type = get, xmlns = (?NS_DISCO_ITEMS) = XMLNS, sub_el = SubEl, lang = Lang} = IQ -> Node = xml:get_tag_attr_s(<<"node">>, SubEl), case Node of <<>> -> ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = []}]}, Res = jlib:iq_to_xml(ResIQ); <<"join">> -> ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = []}]}, Res = jlib:iq_to_xml(ResIQ); <<"register">> -> ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = []}]}, Res = jlib:iq_to_xml(ResIQ); ?NS_COMMANDS -> ResIQ = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}, {<<"node">>, Node}], children = command_items(ServerHost, Host, Lang)}]}, Res = jlib:iq_to_xml(ResIQ); _ -> Res = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND) end, ejabberd_router:route(To, From, Res); #iq{xmlns = ?NS_REGISTER} = IQ -> process_register(ServerHost, Host, From, To, IQ); #iq{type = get, xmlns = (?NS_VCARD) = XMLNS, lang = Lang} = 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, lang = _Lang, sub_el = SubEl} = IQ -> Request = adhoc:parse_request(IQ), case lists:keysearch(Request#adhoc_request.node, 1, commands(ServerHost)) of {value, {_, _, Function}} -> case catch Function(From, To, Request) of {'EXIT', Reason} -> ?ERROR_MSG("~p~nfor ad-hoc handler of ~p", [Reason, {From, To, IQ}]), Res = IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}; ignore -> Res = ignore; {error, Error} -> Res = IQ#iq{type = error, sub_el = [SubEl, Error]}; Command -> Res = IQ#iq{type = result, sub_el = [Command]} end, if Res /= ignore -> ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); true -> ok end; _ -> Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND), ejabberd_router:route(To, From, Err) end; #iq{} = _IQ -> Err = jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED), ejabberd_router:route(To, From, Err); _ -> ok end; _ -> Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), ejabberd_router:route(To, From, Err) end; _ -> case str:tokens(ChanServ, <<"%">>) of [<<_, _/binary>> = Channel, <<_, _/binary>> = Server] -> case ets:lookup(irc_connection, {From, Server, Host}) of [] -> ?DEBUG("open new connection~n", []), {Username, Encoding, Port, Password} = get_connection_params(Host, ServerHost, From, Server), ConnectionUsername = case Packet of %% If the user tries to join a %% chatroom, the packet for sure %% contains the desired username. #xmlel{name = <<"presence">>} -> Resource; %% Otherwise, there is no firm %% conclusion from the packet. %% Better to use the configured %% username (which defaults to the %% 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, Ident, RemoteAddr, RealName, WebircPassword, ?MODULE), ets:insert(irc_connection, #irc_connection{jid_server_host = {From, Server, Host}, pid = Pid}), mod_irc_connection:route_chan(Pid, Channel, Resource, Packet), ok; [R] -> Pid = R#irc_connection.pid, ?DEBUG("send to process ~p~n", [Pid]), mod_irc_connection:route_chan(Pid, Channel, Resource, Packet), ok end; _ -> case str:tokens(ChanServ, <<"!">>) of [<<_, _/binary>> = Nick, <<_, _/binary>> = Server] -> case ets:lookup(irc_connection, {From, Server, Host}) of [] -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err); [R] -> Pid = R#irc_connection.pid, ?DEBUG("send to process ~p~n", [Pid]), mod_irc_connection:route_nick(Pid, Nick, Packet), ok end; _ -> Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), ejabberd_router:route(To, From, Err) end end end. closed_connection(Host, From, Server) -> ets:delete(irc_connection, {From, Server, Host}). iq_disco(_ServerHost, <<>>, Lang) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"conference">>}, {<<"type">>, <<"irc">>}, {<<"name">>, translate:translate(Lang, <<"IRC Transport">>)}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_DISCO_INFO}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_MUC}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_REGISTER}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_VCARD}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_COMMANDS}], children = []}]; iq_disco(ServerHost, Node, Lang) -> case lists:keysearch(Node, 1, commands(ServerHost)) of {value, {_, Name, _}} -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"automation">>}, {<<"type">>, <<"command-node">>}, {<<"name">>, translate:translate(Lang, Name)}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_COMMANDS}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_XDATA}], children = []}]; _ -> [] end. iq_get_vcard(Lang) -> [#xmlel{name = <<"FN">>, attrs = [], children = [{xmlcdata, <<"ejabberd/mod_irc">>}]}, #xmlel{name = <<"URL">>, attrs = [], children = [{xmlcdata, ?EJABBERD_URI}]}, #xmlel{name = <<"DESC">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd IRC module">>))/binary, "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. command_items(ServerHost, Host, Lang) -> lists:map(fun ({Node, Name, _Function}) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Host}, {<<"node">>, Node}, {<<"name">>, translate:translate(Lang, Name)}], children = []} end, commands(ServerHost)). commands(ServerHost) -> [{<<"join">>, <<"Join channel">>, fun adhoc_join/3}, {<<"register">>, <<"Configure username, encoding, port and " "password">>, fun (From, To, Request) -> adhoc_register(ServerHost, From, To, Request) end}]. process_register(ServerHost, Host, From, To, #iq{} = IQ) -> case catch process_irc_register(ServerHost, Host, From, To, IQ) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); ResIQ -> if ResIQ /= ignore -> ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)); true -> ok end end. find_xdata_el(#xmlel{children = SubEls}) -> find_xdata_el1(SubEls). find_xdata_el1([]) -> false; find_xdata_el1([#xmlel{name = Name, attrs = Attrs, children = SubEls} | Els]) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> #xmlel{name = Name, attrs = Attrs, children = SubEls}; _ -> find_xdata_el1(Els) end; find_xdata_el1([_ | Els]) -> find_xdata_el1(Els). process_irc_register(ServerHost, Host, From, _To, #iq{type = Type, xmlns = XMLNS, lang = Lang, sub_el = SubEl} = IQ) -> case Type of set -> XDataEl = find_xdata_el(SubEl), case XDataEl of false -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ACCEPTABLE]}; #xmlel{attrs = Attrs} -> case xml:get_attr_s(<<"type">>, Attrs) of <<"cancel">> -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = []}]}; <<"submit">> -> XData = jlib:parse_xdata_submit(XDataEl), case XData of invalid -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; _ -> Node = str:tokens(xml:get_tag_attr_s(<<"node">>, SubEl), <<"/">>), case set_form(ServerHost, Host, From, Node, Lang, XData) of {result, Res} -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = Res}]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end end; _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end end; get -> Node = str:tokens(xml:get_tag_attr_s(<<"node">>, SubEl), <<"/">>), case get_form(ServerHost, Host, From, Node, Lang) of {result, Res} -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = Res}]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end end. get_data(ServerHost, Host, From) -> LServer = jid:nameprep(ServerHost), get_data(LServer, Host, From, gen_mod:db_type(LServer, ?MODULE)). get_data(_LServer, Host, From, mnesia) -> #jid{luser = LUser, lserver = LServer} = From, US = {LUser, LServer}, case catch mnesia:dirty_read({irc_custom, {US, Host}}) of {'EXIT', _Reason} -> error; [] -> empty; [#irc_custom{data = Data}] -> Data end; get_data(LServer, Host, From, riak) -> #jid{luser = LUser, lserver = LServer} = From, US = {LUser, LServer}, case ejabberd_riak:get(irc_custom, irc_custom_schema(), {US, Host}) of {ok, #irc_custom{data = Data}} -> Data; {error, notfound} -> empty; _Err -> error end; get_data(LServer, Host, From, odbc) -> SJID = 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='">>, SJID, <<"' and host='">>, SHost, <<"';">>]) of {selected, [<<"data">>], [[SData]]} -> data_to_binary(From, ejabberd_odbc:decode_term(SData)); {'EXIT', _} -> error; {selected, _, _} -> empty end. get_form(ServerHost, Host, From, [], Lang) -> #jid{user = User, server = Server} = From, DefaultEncoding = get_default_encoding(Host), Customs = case get_data(ServerHost, Host, From) of error -> {error, ?ERR_INTERNAL_SERVER_ERROR}; empty -> {User, []}; Data -> get_username_and_connection_params(Data) end, case Customs of {error, _Error} -> Customs; {Username, ConnectionsParams} -> {result, [#xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"You need an x:data capable client to " "configure mod_irc settings">>)}]}, #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [#xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"Registration in mod_irc for ">>))/binary, User/binary, "@", Server/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Enter username, encodings, ports and " "passwords you wish to use for connecting " "to IRC servers">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-single">>}, {<<"label">>, translate:translate(Lang, <<"IRC Username">>)}, {<<"var">>, <<"username">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Username}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"fixed">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, iolist_to_binary( io_lib:format( translate:translate( Lang, <<"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.">>), [DefaultEncoding, ?DEFAULT_IRC_PORT]))}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"fixed">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Example: [{\"irc.lucky.net\", \"koi8-r\", " "6667, \"secret\"}, {\"vendetta.fef.net\", " "\"iso8859-1\", 7000}, {\"irc.sometestserver.n" "et\", \"utf-8\"}].">>)}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-multi">>}, {<<"label">>, translate:translate(Lang, <<"Connections parameters">>)}, {<<"var">>, <<"connections_params">>}], children = lists:map(fun (S) -> #xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, S}]} end, str:tokens(list_to_binary( io_lib:format( "~p.", [conn_params_to_list( ConnectionsParams)])), <<"\n">>))}]}]} end; get_form(_ServerHost, _Host, _, _, _Lang) -> {error, ?ERR_SERVICE_UNAVAILABLE}. set_data(ServerHost, Host, From, Data) -> 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, _} = jid:tolower(From), US = {LUser, LServer}, F = fun () -> mnesia:write(#irc_custom{us_host = {US, Host}, data = Data}) end, mnesia:transaction(F); set_data(LServer, Host, From, Data, riak) -> {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(jid:to_string(jid:tolower(jid:remove_resource(From)))), SHost = ejabberd_odbc:escape(Host), SData = ejabberd_odbc:encode_term(Data), F = fun () -> odbc_queries:update_t(<<"irc_custom">>, [<<"jid">>, <<"host">>, <<"data">>], [SJID, SHost, SData], [<<"jid='">>, SJID, <<"' and host='">>, SHost, <<"'">>]), ok end, ejabberd_odbc:sql_transaction(LServer, F). set_form(ServerHost, Host, From, [], _Lang, XData) -> case {lists:keysearch(<<"username">>, 1, XData), lists:keysearch(<<"connections_params">>, 1, XData)} of {{value, {_, [Username]}}, {value, {_, Strings}}} -> EncString = lists:foldl(fun (S, Res) -> <> end, <<"">>, Strings), case erl_scan:string(binary_to_list(EncString)) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens) of {ok, ConnectionsParams} -> case set_data(ServerHost, Host, From, [{username, Username}, {connections_params, ConnectionsParams}]) of {atomic, _} -> {result, []}; _ -> {error, ?ERR_NOT_ACCEPTABLE} end; _ -> {error, ?ERR_NOT_ACCEPTABLE} end; _ -> {error, ?ERR_NOT_ACCEPTABLE} end; _ -> {error, ?ERR_NOT_ACCEPTABLE} end; set_form(_ServerHost, _Host, _, _, _Lang, _XData) -> {error, ?ERR_SERVICE_UNAVAILABLE}. get_connection_params(Host, From, IRCServer) -> [_ | HostTail] = str:tokens(Host, <<".">>), ServerHost = str:join(HostTail, <<".">>), get_connection_params(Host, ServerHost, From, IRCServer). get_default_encoding(ServerHost) -> Result = gen_mod:get_module_opt(ServerHost, ?MODULE, default_encoding, fun iolist_to_binary/1, ?DEFAULT_IRC_ENCODING), ?INFO_MSG("The default_encoding configured for " "host ~p is: ~p~n", [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, DefaultEncoding = get_default_encoding(ServerHost), case get_data(ServerHost, Host, From) of error -> {User, DefaultEncoding, ?DEFAULT_IRC_PORT, <<"">>}; empty -> {User, DefaultEncoding, ?DEFAULT_IRC_PORT, <<"">>}; Data -> {Username, ConnParams} = get_username_and_connection_params(Data), {NewUsername, NewEncoding, NewPort, NewPassword} = case lists:keysearch(IRCServer, 1, ConnParams) of {value, {_, Encoding, Port, Password}} -> {Username, Encoding, Port, Password}; {value, {_, Encoding, Port}} -> {Username, Encoding, Port, <<"">>}; {value, {_, Encoding}} -> {Username, Encoding, ?DEFAULT_IRC_PORT, <<"">>}; _ -> {Username, DefaultEncoding, ?DEFAULT_IRC_PORT, <<"">>} end, {iolist_to_binary(NewUsername), iolist_to_binary(NewEncoding), if NewPort >= 0 andalso NewPort =< 65535 -> NewPort; true -> ?DEFAULT_IRC_PORT end, iolist_to_binary(NewPassword)} end. adhoc_join(_From, _To, #adhoc_request{action = <<"cancel">>} = Request) -> adhoc:produce_response(Request, #adhoc_response{status = canceled}); adhoc_join(From, To, #adhoc_request{lang = Lang, node = _Node, action = _Action, xdata = XData} = Request) -> if XData == false -> Form = #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = [#xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Join IRC channel">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"channel">>}, {<<"type">>, <<"text-single">>}, {<<"label">>, translate:translate(Lang, <<"IRC channel (don't put the first #)">>)}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"server">>}, {<<"type">>, <<"text-single">>}, {<<"label">>, translate:translate(Lang, <<"IRC server">>)}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}]}, adhoc:produce_response(Request, #adhoc_response{status = executing, elements = [Form]}); true -> case jlib:parse_xdata_submit(XData) of invalid -> {error, ?ERR_BAD_REQUEST}; Fields -> Channel = case lists:keysearch(<<"channel">>, 1, Fields) of {value, {<<"channel">>, [C]}} -> C; _ -> false end, Server = case lists:keysearch(<<"server">>, 1, Fields) of {value, {<<"server">>, [S]}} -> S; _ -> false end, if Channel /= false, Server /= false -> RoomJID = <>, Invite = #xmlel{name = <<"message">>, attrs = [], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"invite">>, attrs = [{<<"from">>, jid:to_string(From)}], children = [#xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Join the IRC channel here.">>)}]}]}]}, #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XCONFERENCE}], children = [{xmlcdata, translate:translate(Lang, <<"Join the IRC channel here.">>)}]}, #xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, iolist_to_binary( io_lib:format( translate:translate( Lang, <<"Join the IRC channel in this Jabber ID: ~s">>), [RoomJID]))}]}]}, ejabberd_router:route(jid:from_string(RoomJID), From, Invite), adhoc:produce_response(Request, #adhoc_response{status = completed}); true -> {error, ?ERR_BAD_REQUEST} end end end. adhoc_register(_ServerHost, _From, _To, #adhoc_request{action = <<"cancel">>} = Request) -> adhoc:produce_response(Request, #adhoc_response{status = canceled}); adhoc_register(ServerHost, From, To, #adhoc_request{lang = Lang, node = _Node, xdata = XData, action = Action} = Request) -> #jid{user = User} = From, #jid{lserver = Host} = To, if XData == false -> case get_data(ServerHost, Host, From) of error -> Username = User, ConnectionsParams = []; empty -> Username = User, ConnectionsParams = []; Data -> {Username, ConnectionsParams} = get_username_and_connection_params(Data) end, Error = false; true -> case jlib:parse_xdata_submit(XData) of invalid -> Error = {error, ?ERR_BAD_REQUEST}, Username = false, ConnectionsParams = false; Fields -> Username = case lists:keysearch(<<"username">>, 1, Fields) of {value, {<<"username">>, U}} -> U; _ -> User end, ConnectionsParams = parse_connections_params(Fields), Error = false end end, if Error /= false -> Error; Action == <<"complete">> -> case set_data(ServerHost, Host, From, [{username, Username}, {connections_params, ConnectionsParams}]) of {atomic, _} -> adhoc:produce_response(Request, #adhoc_response{status = completed}); _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end; true -> Form = generate_adhoc_register_form(Lang, Username, ConnectionsParams), adhoc:produce_response(Request, #adhoc_response{status = executing, elements = [Form], actions = [<<"next">>, <<"complete">>]}) end. generate_adhoc_register_form(Lang, Username, ConnectionsParams) -> #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = [#xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"IRC settings">>)}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"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.">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"username">>}, {<<"type">>, <<"text-single">>}, {<<"label">>, translate:translate(Lang, <<"IRC username">>)}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}, #xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Username}]}]}] ++ generate_connection_params_fields(Lang, ConnectionsParams, 1, [])}. generate_connection_params_fields(Lang, [], Number, Acc) -> Field = generate_connection_params_field(Lang, <<"">>, <<"">>, -1, <<"">>, Number), lists:reverse(Field ++ Acc); generate_connection_params_fields(Lang, [ConnectionParams | ConnectionsParams], Number, Acc) -> case ConnectionParams of {Server, Encoding, Port, Password} -> Field = generate_connection_params_field(Lang, Server, Encoding, Port, Password, Number), generate_connection_params_fields(Lang, ConnectionsParams, Number + 1, Field ++ Acc); {Server, Encoding, Port} -> Field = generate_connection_params_field(Lang, Server, Encoding, Port, <<"">>, Number), generate_connection_params_fields(Lang, ConnectionsParams, Number + 1, Field ++ Acc); {Server, Encoding} -> Field = generate_connection_params_field(Lang, Server, Encoding, -1, <<"">>, Number), generate_connection_params_fields(Lang, ConnectionsParams, Number + 1, Field ++ Acc); _ -> [] end. generate_connection_params_field(Lang, Server, Encoding, Port, Password, Number) -> EncodingUsed = case Encoding of <<>> -> get_default_encoding(Server); _ -> Encoding end, PortUsedInt = if Port >= 0 andalso Port =< 65535 -> Port; true -> ?DEFAULT_IRC_PORT end, PortUsed = iolist_to_binary(integer_to_list(PortUsedInt)), PasswordUsed = case Password of <<>> -> <<>>; _ -> Password end, NumberString = iolist_to_binary(integer_to_list(Number)), [#xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"password", NumberString/binary>>}, {<<"type">>, <<"text-single">>}, {<<"label">>, iolist_to_binary( io_lib:format( translate:translate(Lang, <<"Password ~b">>), [Number]))}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, PasswordUsed}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"port", NumberString/binary>>}, {<<"type">>, <<"text-single">>}, {<<"label">>, iolist_to_binary( io_lib:format(translate:translate(Lang, <<"Port ~b">>), [Number]))}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, PortUsed}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"encoding", NumberString/binary>>}, {<<"type">>, <<"list-single">>}, {<<"label">>, list_to_binary( io_lib:format(translate:translate( Lang, <<"Encoding for server ~b">>), [Number]))}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, EncodingUsed}]} | lists:map(fun (E) -> #xmlel{name = <<"option">>, attrs = [{<<"label">>, E}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, E}]}]} end, ?POSSIBLE_ENCODINGS)]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"server", NumberString/binary>>}, {<<"type">>, <<"text-single">>}, {<<"label">>, list_to_binary( io_lib:format(translate:translate(Lang, <<"Server ~b">>), [Number]))}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Server}]}]}]. parse_connections_params(Fields) -> Servers = lists:flatmap( fun({<<"server", Var/binary>>, Value}) -> [{Var, Value}]; (_) -> [] end, Fields), Encodings = lists:flatmap( fun({<<"encoding", Var/binary>>, Value}) -> [{Var, Value}]; (_) -> [] end, Fields), Ports = lists:flatmap( fun({<<"port", Var/binary>>, Value}) -> [{Var, Value}]; (_) -> [] end, Fields), Passwords = lists:flatmap( fun({<<"password", Var/binary>>, Value}) -> [{Var, Value}]; (_) -> [] end, Fields), parse_connections_params(Servers, Encodings, Ports, Passwords). retrieve_connections_params(ConnectionParams, ServerN) -> case ConnectionParams of [{ConnectionParamN, ConnectionParam} | ConnectionParamsTail] -> if ServerN == ConnectionParamN -> {ConnectionParam, ConnectionParamsTail}; ServerN < ConnectionParamN -> {[], [{ConnectionParamN, ConnectionParam} | ConnectionParamsTail]}; ServerN > ConnectionParamN -> {[], ConnectionParamsTail} end; _ -> {[], []} end. parse_connections_params([], _, _, _) -> []; parse_connections_params(_, [], [], []) -> []; parse_connections_params([{ServerN, Server} | Servers], Encodings, Ports, Passwords) -> {NewEncoding, NewEncodings} = retrieve_connections_params(Encodings, ServerN), {NewPort, NewPorts} = retrieve_connections_params(Ports, ServerN), {NewPassword, NewPasswords} = retrieve_connections_params(Passwords, ServerN), [{Server, NewEncoding, NewPort, NewPassword} | parse_connections_params(Servers, NewEncodings, NewPorts, NewPasswords)]. get_username_and_connection_params(Data) -> Username = case lists:keysearch(username, 1, Data) of {value, {_, U}} when is_binary(U) -> U; _ -> <<"">> end, ConnParams = case lists:keysearch(connections_params, 1, Data) of {value, {_, L}} when is_list(L) -> L; _ -> [] end, {Username, ConnParams}. data_to_binary(JID, Data) -> lists:map( fun({username, U}) -> {username, iolist_to_binary(U)}; ({connections_params, Params}) -> {connections_params, lists:flatmap( fun(Param) -> try [conn_param_to_binary(Param)] catch _:_ -> if JID /= error -> ?ERROR_MSG("failed to convert " "parameter ~p for user ~s", [Param, jid:to_string(JID)]); true -> ?ERROR_MSG("failed to convert " "parameter ~p", [Param]) end, [] end end, Params)}; (Opt) -> Opt end, Data). conn_param_to_binary({S}) -> {iolist_to_binary(S)}; conn_param_to_binary({S, E}) -> {iolist_to_binary(S), iolist_to_binary(E)}; conn_param_to_binary({S, E, Port}) when is_integer(Port) -> {iolist_to_binary(S), iolist_to_binary(E), Port}; conn_param_to_binary({S, E, Port, P}) when is_integer(Port) -> {iolist_to_binary(S), iolist_to_binary(E), Port, iolist_to_binary(P)}. conn_params_to_list(Params) -> lists:map( fun({S}) -> {binary_to_list(S)}; ({S, E}) -> {binary_to_list(S), binary_to_list(E)}; ({S, E, Port}) -> {binary_to_list(S), binary_to_list(E), Port}; ({S, E, Port, P}) -> {binary_to_list(S), binary_to_list(E), Port, binary_to_list(P)} end, Params). irc_custom_schema() -> {record_info(fields, irc_custom), #irc_custom{}}. update_table() -> Fields = record_info(fields, irc_custom), case mnesia:table_info(irc_custom, attributes) of Fields -> ejabberd_config:convert_table_to_binary( irc_custom, Fields, set, fun(#irc_custom{us_host = {_, H}}) -> H end, fun(#irc_custom{us_host = {{U, S}, H}, data = Data} = R) -> JID = jid:make(U, S, <<"">>), R#irc_custom{us_host = {{iolist_to_binary(U), iolist_to_binary(S)}, iolist_to_binary(H)}, data = data_to_binary(JID, Data)} end); _ -> ?INFO_MSG("Recreating irc_custom table", []), mnesia:transform_table(irc_custom, ignore, Fields) end. export(_Server) -> [{irc_custom, fun(Host, #irc_custom{us_host = {{U, S}, IRCHost}, data = Data}) -> case str:suffix(Host, IRCHost) of true -> SJID = ejabberd_odbc:escape( 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, <<"' and host='">>, SIRCHost, <<"';">>], [<<"insert into irc_custom(jid, host, " "data) values ('">>, SJID, <<"', '">>, SIRCHost, <<"', '">>, SData, <<"');">>]]; false -> [] end end}]. import(_LServer) -> [{<<"select jid, host, data from irc_custom;">>, fun([SJID, IRCHost, SData]) -> #jid{luser = U, lserver = S} = jid:from_string(SJID), Data = ejabberd_odbc:decode_term(SData), #irc_custom{us_host = {{U, S}, IRCHost}, data = Data} end}]. import(_LServer, mnesia, #irc_custom{} = R) -> mnesia:dirty_write(R); 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]. 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. ejabberd-16.01/src/pubsub_subscription_odbc.erl0000644000232200023220000002752612645157216022240 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% 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 %%% %%% %%% 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(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, make_subid/0, 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_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(DB_MOD, pubsub_db_odbc). %%==================================================================== %% API %%==================================================================== init() -> ok = create_table(). -spec(subscribe_node/3 :: ( _JID :: _, _NodeId :: _, Options :: [] | mod_pubsub:subOptions()) -> {result, mod_pubsub:subId()} ). subscribe_node(_JID, _NodeId, Options) -> SubID = make_subid(), (?DB_MOD):add_subscription(#pubsub_subscription{subid = SubID, options = Options}), {result, SubID}. -spec(unsubscribe_node/3 :: ( _JID :: _, _NodeId :: _, SubID :: mod_pubsub:subId()) -> {result, mod_pubsub:subscription()} | {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} end. -spec(get_subscription/3 :: ( _JID :: _, _NodeId :: _, SubId :: mod_pubsub:subId()) -> {result, mod_pubsub:subscription()} | {error, notfound} ). get_subscription(_JID, _NodeId, SubID) -> case (?DB_MOD):read_subscription(SubID) of {ok, Sub} -> {result, Sub}; notfound -> {error, notfound} end. -spec(set_subscription/4 :: ( _JID :: _, _NodeId :: _, SubId :: mod_pubsub:subId(), Options :: mod_pubsub:subOptions()) -> {result, ok} ). 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} end. get_options_xform(Lang, Options) -> Keys = [deliver, show_values, subscription_type, subscription_depth], XFields = [get_option_xfield(Lang, Key, Options) || Key <- Keys], {result, #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}}. 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, []} end. %%==================================================================== %% Internal functions %%==================================================================== create_table() -> ok. -spec(make_subid/0 :: () -> mod_pubsub:subId()). make_subid() -> {T1, T2, T3} = p1_time_compat:timestamp(), iolist_to_binary(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). %% %% Subscription XForm processing. %% %% Return processed options, with types converted and so forth, using %% Opts as defaults. 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, 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_SHOW_VALUES) -> show_values; 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]) -> 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} end. %% Convert XForm booleans to Erlang booleans. xopt_to_bool(<<"0">>) -> false; xopt_to_bool(<<"1">>) -> true; xopt_to_bool(<<"false">>) -> false; xopt_to_bool(<<"true">>) -> true; xopt_to_bool(_) -> {error, ?ERR_NOT_ACCEPTABLE}. %% 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), Vals = case lists:keysearch(Key, 1, Options) of {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}. type_and_options({Type, Options}, Lang) -> {Type, [tr_xfield_options(O, Lang) || O <- Options]}; 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}]}]}. tr_xfield_values(Value) -> %% 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}]}. xfield_var(deliver) -> ?PUBSUB_DELIVER; %xfield_var(digest) -> ?PUBSUB_DIGEST; %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_type(deliver) -> <<"boolean">>; %xfield_type(digest) -> <<"boolean">>; %xfield_type(digest_frequency) -> <<"text-single">>; %xfield_type(expire) -> <<"text-single">>; %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}]}; xfield_type(subscription_type) -> {<<"list-single">>, [{<<"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}]}. %% 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(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_val(deliver, Val) -> [bool_to_xopt(Val)]; %xfield_val(digest, Val) -> [bool_to_xopt(Val)]; %xfield_val(digest_frequency, 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(show_values, Val) -> Val; xfield_val(subscription_type, items) -> [<<"items">>]; xfield_val(subscription_type, nodes) -> [<<"nodes">>]; xfield_val(subscription_depth, all) -> [<<"all">>]; xfield_val(subscription_depth, N) -> [iolist_to_binary(integer_to_list(N))]. bool_to_xopt(false) -> <<"false">>; bool_to_xopt(true) -> <<"true">>. ejabberd-16.01/src/ejabberd_ctl.erl0000644000232200023220000006560712645157216017547 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_ctl.erl %%% Author : Alexey Shchepin %%% Purpose : ejabberd command line admin tool %%% Created : 11 Jan 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. %%% %%%---------------------------------------------------------------------- %%% @headerfile "ejabberd_ctl.hrl" %%% @doc Management of ejabberdctl commands and frontend to ejabberd commands. %%% %%% An ejabberdctl command is an abstract function identified by a %%% name, with a defined number of calling arguments, that can be %%% defined in any Erlang module and executed using ejabberdctl %%% administration script. %%% %%% Note: strings cannot have blankspaces %%% %%% Does not support commands that have arguments with ctypes: list, tuple %%% %%% TODO: Update the guide %%% TODO: Mention this in the release notes %%% Note: the commands with several words use now the underline: _ %%% It is still possible to call the commands with dash: - %%% but this is deprecated, and may be removed in a future version. -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, opt_type/1]). -include("ejabberd_ctl.hrl"). -include("ejabberd_commands.hrl"). -include("ejabberd.hrl"). -include("logger.hrl"). %%----------------------------- %% Module %%----------------------------- start() -> [SNode, Timeout, Args] = case init:get_plain_arguments() of [SNode2, "--no-timeout" | Args2] -> [SNode2, infinity, Args2]; [SNode3 | Args3] -> [SNode3, 60000, 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]), ets:new(ejabberd_ctl_host_cmds, [named_table, set, public]). %%----------------------------- %% ejabberdctl Command managment %%----------------------------- register_commands(CmdDescs, Module, Function) -> ets:insert(ejabberd_ctl_cmds, CmdDescs), ejabberd_hooks:add(ejabberd_ctl_process, Module, Function, 50), ok. unregister_commands(CmdDescs, Module, Function) -> lists:foreach(fun(CmdDesc) -> ets:delete_object(ejabberd_ctl_cmds, CmdDesc) end, CmdDescs), ejabberd_hooks:delete(ejabberd_ctl_process, Module, Function, 50), ok. %%----------------------------- %% Process %%----------------------------- -spec process([string()]) -> non_neg_integer(). %% The commands status, stop and restart are defined here to ensure %% they are usable even if ejabberd is completely stopped. process(["status"]) -> {InternalStatus, ProvidedStatus} = init:get_status(), print("The node ~p is ~p with status: ~p~n", [node(), InternalStatus, ProvidedStatus]), case lists:keysearch(ejabberd, 1, application:which_applications()) of false -> EjabberdLogPath = ejabberd_logger:get_log_path(), print("ejabberd is not running in that node~n" "Check for error messages: ~s~n" "or other files in that directory.~n", [EjabberdLogPath]), ?STATUS_ERROR; {value, {_, _, Version}} -> print("ejabberd ~s is running in that node~n", [Version]), ?STATUS_SUCCESS end; process(["stop"]) -> %%ejabberd_cover:stop(), init:stop(), ?STATUS_SUCCESS; process(["restart"]) -> init:restart(), ?STATUS_SUCCESS; process(["mnesia"]) -> print("~p~n", [mnesia:system_info(all)]), ?STATUS_SUCCESS; process(["mnesia", "info"]) -> mnesia:info(), ?STATUS_SUCCESS; process(["mnesia", Arg]) -> case catch mnesia:system_info(list_to_atom(Arg)) of {'EXIT', Error} -> print("Error: ~p~n", [Error]); Return -> print("~p~n", [Return]) end, ?STATUS_SUCCESS; %% The arguments --long and --dual are not documented because they are %% automatically selected depending in the number of columns of the shell process(["help" | Mode]) -> {MaxC, ShCode} = get_shell_info(), case Mode of [] -> print_usage(dual, MaxC, ShCode), ?STATUS_USAGE; ["--dual"] -> print_usage(dual, MaxC, ShCode), ?STATUS_USAGE; ["--long"] -> print_usage(long, MaxC, ShCode), ?STATUS_USAGE; ["--tags"] -> print_usage_tags(MaxC, ShCode), ?STATUS_SUCCESS; ["--tags", Tag] -> print_usage_tags(Tag, MaxC, ShCode), ?STATUS_SUCCESS; ["help"] -> print_usage_help(MaxC, ShCode), ?STATUS_SUCCESS; [CmdString | _] -> CmdStringU = ejabberd_regexp:greplace( list_to_binary(CmdString), <<"-">>, <<"_">>), print_usage_commands(binary_to_list(CmdStringU), MaxC, ShCode), ?STATUS_SUCCESS end; process(Args) -> AccessCommands = get_accesscommands(), {String, Code} = process2(Args, AccessCommands), case String of [] -> ok; _ -> io:format("~s~n", [String]) end, Code. %% @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), true}, AccessCommands); process2(Args, AccessCommands) -> process2(Args, admin, AccessCommands). process2(Args, Auth, AccessCommands) -> case try_run_ctp(Args, Auth, AccessCommands) of {String, wrong_command_arguments} when is_list(String) -> io:format(lists:flatten(["\n" | String]++["\n"])), [CommandString | _] = Args, process(["help" | [CommandString]]), {lists:flatten(String), ?STATUS_ERROR}; {String, Code} when is_list(String) and is_integer(Code) -> {lists:flatten(String), Code}; String when is_list(String) -> {lists:flatten(String), ?STATUS_SUCCESS}; Code when is_integer(Code) -> {"", Code}; Other -> {"Erroneous result: " ++ io_lib:format("~p", [Other]), ?STATUS_ERROR} end. get_accesscommands() -> ejabberd_config:get_option(ejabberdctl_access_commands, fun(V) when is_list(V) -> V end, []). %%----------------------------- %% Command calling %%----------------------------- %% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} try_run_ctp(Args, Auth, AccessCommands) -> try ejabberd_hooks:run_fold(ejabberd_ctl_process, false, [Args]) of false when Args /= [] -> try_call_command(Args, Auth, AccessCommands); false -> print_usage(), {"", ?STATUS_USAGE}; Status -> {"", Status} catch exit:Why -> print_usage(), {io_lib:format("Error in ejabberd ctl process: ~p", [Why]), ?STATUS_USAGE}; Error:Why -> %% In this case probably ejabberd is not started, so let's show Status process(["status"]), print("~n", []), {io_lib:format("Error in ejabberd ctl process: '~p' ~p", [Error, Why]), ?STATUS_USAGE} end. %% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} try_call_command(Args, Auth, AccessCommands) -> try call_command(Args, Auth, AccessCommands) of {error, command_unknown} -> {io_lib:format("Error: command ~p not known.", [hd(Args)]), ?STATUS_ERROR}; {error, wrong_command_arguments} -> {"Error: wrong arguments", ?STATUS_ERROR}; Res -> Res catch A:Why -> Stack = erlang:get_stacktrace(), {io_lib:format("Problem '~p ~p' occurred executing the command.~nStacktrace: ~p", [A, Why, Stack]), ?STATUS_ERROR} end. %% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} | {error, ErrorType} 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, Auth) of {error, command_unknown} -> {error, command_unknown}; {ArgsFormat, ResultFormat} -> case (catch format_args(Args, ArgsFormat)) of ArgsFormatted when is_list(ArgsFormatted) -> Result = ejabberd_commands:execute_command(AccessCommands, Auth, Command, ArgsFormatted), format_result(Result, ResultFormat); {'EXIT', {function_clause,[{lists,zip,[A1, A2], _} | _]}} -> {NumCompa, TextCompa} = case {length(A1), length(A2)} of {L1, L2} when L1 < L2 -> {L2-L1, "less argument"}; {L1, L2} when L1 > L2 -> {L1-L2, "more argument"} end, {io_lib:format("Error: the command ~p requires ~p ~s.", [CmdString, NumCompa, TextCompa]), wrong_command_arguments} end end. %%----------------------------- %% Format arguments %%----------------------------- format_args(Args, ArgsFormat) -> lists:foldl( fun({{_ArgName, ArgFormat}, Arg}, Res) -> Formatted = format_arg(Arg, ArgFormat), Res ++ [Formatted] end, [], lists:zip(ArgsFormat, Args)). format_arg(Arg, integer) -> format_arg2(Arg, "~d"); format_arg(Arg, binary) -> list_to_binary(format_arg(Arg, string)); format_arg("", string) -> ""; format_arg(Arg, string) -> NumChars = integer_to_list(length(Arg)), Parse = "~" ++ NumChars ++ "c", format_arg2(Arg, Parse). format_arg2(Arg, Parse)-> {ok, [Arg2], _RemainingArguments} = io_lib:fread(Parse, Arg), Arg2. %%----------------------------- %% Format result %%----------------------------- format_result({error, ErrorAtom}, _) -> {io_lib:format("Error: ~p", [ErrorAtom]), make_status(error)}; format_result(Atom, {_Name, atom}) -> io_lib:format("~p", [Atom]); format_result(Int, {_Name, integer}) -> io_lib:format("~p", [Int]); format_result(String, {_Name, string}) when is_list(String) -> io_lib:format("~s", [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); format_result({Code, Text}, {_Name, restuple}) -> {io_lib:format("~s", [Text]), make_status(Code)}; %% The result is a list of something: [something()] format_result([], {_Name, {list, _ElementsDef}}) -> ""; format_result([FirstElement | Elements], {_Name, {list, ElementsDef}}) -> %% Start formatting the first element [format_result(FirstElement, ElementsDef) | %% If there are more elements, put always first a newline character lists:map( fun(Element) -> ["\n" | format_result(Element, ElementsDef)] end, Elements)]; %% The result is a tuple with several elements: {something1(), something2(),...} %% NOTE: the elements in the tuple are separated with tabular characters, %% if a string is empty, it will be difficult to notice in the shell, %% maybe a different separation character should be used, like ;;? format_result(ElementsTuple, {_Name, {tuple, ElementsDef}}) -> ElementsList = tuple_to_list(ElementsTuple), [{FirstE, FirstD} | ElementsAndDef] = lists:zip(ElementsList, ElementsDef), [format_result(FirstE, FirstD) | lists:map( fun({Element, ElementDef}) -> ["\t" | format_result(Element, ElementDef)] end, ElementsAndDef)]; format_result(404, {_Name, _}) -> make_status(not_found). make_status(ok) -> ?STATUS_SUCCESS; make_status(true) -> ?STATUS_SUCCESS; make_status(_Error) -> ?STATUS_ERROR. get_list_commands() -> try ejabberd_commands:list_commands() of Commands -> [tuple_command_help(Command) || {N,_,_}=Command <- Commands, %% Don't show again those commands, because they are already %% announced by ejabberd_ctl itself N /= status, N /= stop, N /= restart] catch exit:_ -> [] end. %% Return: {string(), [string()], string()} 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 -> ""; false -> "*" end, CallString = atom_to_list(Name), {CallString, Arguments, Prepend ++ Desc}. is_supported_args(Args) -> lists:all( fun({_Name, Format}) -> (Format == integer) or (Format == string) or (Format == binary) end, Args). get_list_ctls() -> case catch ets:tab2list(ejabberd_ctl_cmds) of {'EXIT', _} -> []; Cs -> [{NameArgs, [], Desc} || {NameArgs, Desc} <- Cs] end. %%----------------------------- %% Print help %%----------------------------- %% Bold -define(B1, "\e[1m"). -define(B2, "\e[22m"). -define(B(S), case ShCode of true -> [?B1, S, ?B2]; false -> S end). %% Underline -define(U1, "\e[4m"). -define(U2, "\e[24m"). -define(U(S), case ShCode of true -> [?U1, S, ?U2]; false -> S end). print_usage() -> {MaxC, ShCode} = get_shell_info(), print_usage(dual, MaxC, ShCode). print_usage(HelpMode, MaxC, ShCode) -> AllCommands = [ {"status", [], "Get ejabberd status"}, {"stop", [], "Stop ejabberd"}, {"restart", [], "Restart ejabberd"}, {"help", ["[--tags [tag] | com?*]"], "Show help (try: ejabberdctl help help)"}, {"mnesia", ["[info]"], "show information of Mnesia system"}] ++ get_list_commands() ++ get_list_ctls(), print( ["Usage: ", ?B("ejabberdctl"), " [--no-timeout] [--node ", ?U("nodename"), "] [--auth ", ?U("user"), " ", ?U("host"), " ", ?U("password"), "] ", ?U("command"), " [", ?U("options"), "]\n" "\n" "Available commands in this ejabberd node:\n"], []), print_usage_commands(HelpMode, MaxC, ShCode, AllCommands), print( ["\n" "Examples:\n" " ejabberdctl restart\n" " ejabberdctl --node ejabberd@host restart\n"], []). print_usage_commands(HelpMode, MaxC, ShCode, Commands) -> CmdDescsSorted = lists:keysort(1, Commands), %% What is the length of the largest command? {CmdArgsLenDescsSorted, Lens} = lists:mapfoldl( fun({Cmd, Args, Desc}, Lengths) -> Len = length(Cmd) + lists:foldl(fun(Arg, R) -> R + 1 + length(Arg) end, 0, Args), {{Cmd, Args, Len, Desc}, [Len | Lengths]} end, [], CmdDescsSorted), MaxCmdLen = case Lens of [] -> 80; _ -> lists:max(Lens) end, %% For each command in the list of commands %% Convert its definition to a line FmtCmdDescs = format_command_lines(CmdArgsLenDescsSorted, MaxCmdLen, MaxC, ShCode, HelpMode), print([FmtCmdDescs], []). %% Get some info about the shell: %% how many columns of width %% and guess if it supports text formatting codes. get_shell_info() -> %% This function was introduced in OTP R12B-0 try io:columns() of {ok, C} -> {C-2, true}; {error, enotsup} -> {78, false} catch _:_ -> {78, false} end. %% Split this command description in several lines of proper length prepare_description(DescInit, MaxC, Desc) -> Words = string:tokens(Desc, " "), prepare_long_line(DescInit, MaxC, Words). prepare_long_line(DescInit, MaxC, Words) -> MaxSegmentLen = MaxC - DescInit, MarginString = lists:duplicate(DescInit, $\s), % Put spaces [FirstSegment | MoreSegments] = split_desc_segments(MaxSegmentLen, Words), MoreSegmentsMixed = mix_desc_segments(MarginString, MoreSegments), [FirstSegment | MoreSegmentsMixed]. mix_desc_segments(MarginString, Segments) -> [["\n", MarginString, Segment] || Segment <- Segments]. split_desc_segments(MaxL, Words) -> join(MaxL, Words). %% Join words in a segment, %% but stop adding to a segment if adding this word would pass L join(L, Words) -> join(L, Words, 0, [], []). join(_Len, [], _CurSegLen, CurSeg, AllSegs) -> lists:reverse([CurSeg | AllSegs]); join(Len, [Word | Tail], CurSegLen, CurSeg, AllSegs) -> WordLen = length(Word), SegSize = WordLen + CurSegLen + 1, {NewCurSeg, NewAllSegs, NewCurSegLen} = if SegSize < Len -> {[CurSeg, " ", Word], AllSegs, SegSize}; true -> {Word, [CurSeg | AllSegs], WordLen} end, NewLen = case string:str(Word, "\n") of 0 -> NewCurSegLen; _ -> 0 end, join(Len, Tail, NewLen, NewCurSeg, NewAllSegs). format_command_lines(CALD, MaxCmdLen, MaxC, ShCode, dual) when MaxC - MaxCmdLen < 40 -> %% If the space available for descriptions is too narrow, enforce long help mode format_command_lines(CALD, MaxCmdLen, MaxC, ShCode, long); format_command_lines(CALD, MaxCmdLen, MaxC, ShCode, dual) -> lists:map( fun({Cmd, Args, CmdArgsL, Desc}) -> DescFmt = prepare_description(MaxCmdLen+4, MaxC, Desc), [" ", ?B(Cmd), " ", [[?U(Arg), " "] || Arg <- Args], string:chars($\s, MaxCmdLen - CmdArgsL + 1), DescFmt, "\n"] end, CALD); format_command_lines(CALD, _MaxCmdLen, MaxC, ShCode, long) -> lists:map( fun({Cmd, Args, _CmdArgsL, Desc}) -> DescFmt = prepare_description(8, MaxC, Desc), ["\n ", ?B(Cmd), " ", [[?U(Arg), " "] || Arg <- Args], "\n", " ", DescFmt, "\n"] end, CALD). %%----------------------------- %% Print Tags %%----------------------------- print_usage_tags(MaxC, ShCode) -> print("Available tags and commands:", []), TagsCommands = ejabberd_commands:get_tags_commands(), lists:foreach( fun({Tag, Commands} = _TagCommands) -> print(["\n\n ", ?B(Tag), "\n "], []), Words = lists:sort(Commands), Desc = prepare_long_line(5, MaxC, Words), print(Desc, []) end, TagsCommands), print("\n\n", []). print_usage_tags(Tag, MaxC, ShCode) -> print(["Available commands with tag ", ?B(Tag), ":", "\n"], []), HelpMode = long, TagsCommands = ejabberd_commands:get_tags_commands(), CommandsNames = case lists:keysearch(Tag, 1, TagsCommands) of {value, {Tag, CNs}} -> CNs; false -> [] end, CommandsList = lists:map( fun(NameString) -> C = ejabberd_commands:get_command_definition( list_to_atom(NameString)), #ejabberd_commands{name = Name, args = Args, desc = Desc} = C, tuple_command_help({Name, Args, Desc}) end, CommandsNames), print_usage_commands(HelpMode, MaxC, ShCode, CommandsList), print("\n", []). %%----------------------------- %% Print usage of 'help' command %%----------------------------- print_usage_help(MaxC, ShCode) -> LongDesc = ["The special 'help' ejabberdctl command provides help of ejabberd commands.\n\n" "The format is:\n ", ?B("ejabberdctl"), " ", ?B("help"), " [", ?B("--tags"), " ", ?U("[tag]"), " | ", ?U("com?*"), "]\n\n" "The optional arguments:\n" " ",?B("--tags")," Show all tags and the names of commands in each tag\n" " ",?B("--tags"), " ", ?U("tag")," Show description of commands in this tag\n" " ",?U("command")," Show detailed description of the command\n" " ",?U("com?*")," Show detailed description of commands that match this glob.\n" " You can use ? to match a simple character,\n" " and * to match several characters.\n" "\n", "Some example usages:\n", " ejabberdctl help\n", " ejabberdctl help --tags\n", " ejabberdctl help --tags accounts\n", " ejabberdctl help register\n", " ejabberdctl help regist*\n", "\n", "Please note that 'ejabberdctl help' shows all ejabberd commands,\n", "even those that cannot be used in the shell with ejabberdctl.\n", "Those commands can be identified because the description starts with: *"], ArgsDef = [], C = #ejabberd_commands{ desc = "Show help of ejabberd commands", longdesc = lists:flatten(LongDesc), args = ArgsDef, result = {help, string}}, print_usage_command("help", C, MaxC, ShCode). %%----------------------------- %% Print usage command %%----------------------------- %% @spec (CmdSubString::string(), MaxC::integer(), ShCode::boolean()) -> ok print_usage_commands(CmdSubString, MaxC, ShCode) -> %% Get which command names match this substring AllCommandsNames = [atom_to_list(Name) || {Name, _, _} <- ejabberd_commands:list_commands()], Cmds = filter_commands(AllCommandsNames, CmdSubString), case Cmds of [] -> io:format("Error: not command found that match: ~p~n", [CmdSubString]); _ -> print_usage_commands2(lists:sort(Cmds), MaxC, ShCode) end. print_usage_commands2(Cmds, MaxC, ShCode) -> %% Then for each one print it lists:mapfoldl( fun(Cmd, Remaining) -> print_usage_command(Cmd, MaxC, ShCode), case Remaining > 1 of true -> print([" ", lists:duplicate(MaxC, 126), " \n"], []); false -> ok end, {ok, Remaining-1} end, length(Cmds), Cmds). filter_commands(All, SubString) -> case lists:member(SubString, All) of true -> [SubString]; false -> filter_commands_regexp(All, SubString) end. filter_commands_regexp(All, Glob) -> RegExp = ejabberd_regexp:sh_to_awk(list_to_binary(Glob)), lists:filter( fun(Command) -> case ejabberd_regexp:run(list_to_binary(Command), RegExp) of match -> true; nomatch -> false end end, All). %% @spec (Cmd::string(), MaxC::integer(), ShCode::boolean()) -> ok print_usage_command(Cmd, MaxC, ShCode) -> Name = list_to_atom(Cmd), case ejabberd_commands:get_command_definition(Name) of command_not_found -> io:format("Error: command ~p not known.~n", [Cmd]); C -> print_usage_command(Cmd, C, MaxC, ShCode) end. print_usage_command(Cmd, C, MaxC, ShCode) -> #ejabberd_commands{ tags = TagsAtoms, desc = Desc, longdesc = LongDesc, 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 [] -> "\n"; _ -> [ [Arg, "\n", ArgsMargin] || Arg <- Args] end, ArgsFmt = [" ", ?B("Arguments"), ": ", ArgsListFmt], %% Initial indentation of result is 11 = length(" Returns: ") ResultFmt = format_usage_ctype(ResultDef, 11), ReturnsFmt = [" ",?B("Returns"),": ", ResultFmt], XmlrpcFmt = "", %%+++ [" ",?B("XML-RPC"),": ", format_usage_xmlrpc(ArgsDef, ResultDef), "\n\n"], TagsFmt = [" ",?B("Tags"),": ", prepare_long_line(8, MaxC, [atom_to_list(TagA) || TagA <- TagsAtoms])], DescFmt = [" ",?B("Description"),": ", prepare_description(15, MaxC, Desc)], LongDescFmt = case LongDesc of "" -> ""; _ -> ["", prepare_description(0, MaxC, LongDesc), "\n\n"] end, NoteEjabberdctl = case is_supported_args(ArgsDef) of true -> ""; false -> [" ", ?B("Note:"), " This command cannot be executed using ejabberdctl. Try ejabberd_xmlrpc.\n\n"] end, print(["\n", NameFmt, "\n", ArgsFmt, "\n", ReturnsFmt, "\n\n", XmlrpcFmt, TagsFmt, "\n\n", DescFmt, "\n\n", LongDescFmt, NoteEjabberdctl], []). format_usage_ctype(Type, _Indentation) when (Type==atom) or (Type==integer) or (Type==string) or (Type==binary) or (Type==rescode) or (Type==restuple)-> io_lib:format("~p", [Type]); format_usage_ctype({Name, Type}, _Indentation) when (Type==atom) or (Type==integer) or (Type==string) or (Type==binary) or (Type==rescode) or (Type==restuple)-> io_lib:format("~p::~p", [Name, Type]); format_usage_ctype({Name, {list, ElementDef}}, Indentation) -> NameFmt = atom_to_list(Name), Indentation2 = Indentation + length(NameFmt) + 4, ElementFmt = format_usage_ctype(ElementDef, Indentation2), [NameFmt, "::[ ", ElementFmt, " ]"]; format_usage_ctype({Name, {tuple, ElementsDef}}, Indentation) -> NameFmt = atom_to_list(Name), Indentation2 = Indentation + length(NameFmt) + 4, ElementsFmt = format_usage_tuple(ElementsDef, Indentation2), [NameFmt, "::{ " | ElementsFmt]. format_usage_tuple([], _Indentation) -> []; format_usage_tuple([ElementDef], Indentation) -> [format_usage_ctype(ElementDef, Indentation) , " }"]; format_usage_tuple([ElementDef | ElementsDef], Indentation) -> ElementFmt = format_usage_ctype(ElementDef, Indentation), MarginString = lists:duplicate(Indentation, $\s), % Put spaces [ElementFmt, ",\n", MarginString, format_usage_tuple(ElementsDef, Indentation)]. print(Format, Args) -> io:format(lists:flatten(Format), Args). %%----------------------------- %% Command managment %%----------------------------- %%+++ %% Struct(Integer res) create_account(Struct(String user, String server, String password)) %%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]. ejabberd-16.01/src/mod_time.erl0000644000232200023220000000562712645157216016740 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_time.erl %%% Author : Alexey Shchepin %%% Purpose : %%% Purpose : %%% Created : 18 Jan 2003 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(mod_time). -author('alexey@process-one.net'). -protocol({xep, 202, '2.0'}). -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). 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_TIME, ?MODULE, process_local_iq, IQDisc). stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_TIME). process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> case Type of set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; get -> 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 = calendar:datetime_to_gregorian_seconds(Now_local) - calendar:datetime_to_gregorian_seconds(Now_universal), {Hd, Md, _} = calendar:seconds_to_time(abs(Seconds_diff)), {_, TZO_diff} = jlib:timestamp_to_iso({{0, 1, 1}, {0, 0, 0}}, {sign(Seconds_diff), {Hd, Md}}), IQ#iq{type = result, sub_el = [#xmlel{name = <<"time">>, attrs = [{<<"xmlns">>, ?NS_TIME}], children = [#xmlel{name = <<"tzo">>, attrs = [], children = [{xmlcdata, TZO_diff}]}, #xmlel{name = <<"utc">>, attrs = [], children = [{xmlcdata, <>}]}]}]} end. sign(N) when N < 0 -> <<"-">>; sign(_) -> <<"+">>. mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; mod_opt_type(_) -> [iqdisc]. ejabberd-16.01/src/mod_muc.erl0000644000232200023220000013146612645157216016567 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_muc.erl %%% Author : Alexey Shchepin %%% Purpose : MUC support (XEP-0045) %%% Created : 19 Mar 2003 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(mod_muc). -author('alexey@process-one.net'). -protocol({xep, 45, '1.25'}). -behaviour(gen_server). -behaviour(gen_mod). %% API -export([start_link/2, start/2, stop/1, room_destroyed/4, store_room/4, restore_room/3, forget_room/3, create_room/5, shutdown_rooms/1, process_iq_disco_items/4, broadcast_service_message/2, export/1, import/1, import/3, can_use_nick/4]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, mod_opt_type/1]). -include("ejabberd.hrl"). -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()}). -record(state, {host = <<"">> :: binary(), server_host = <<"">> :: binary(), access = {none, none, none, none} :: {atom(), atom(), atom(), atom()}, history_size = 20 :: non_neg_integer(), default_room_opts = [] :: list(), room_shaper = none :: shaper:shaper()}). -define(PROCNAME, ejabberd_mod_muc). -define(MAX_ROOMS_DISCOITEMS, 100). %%==================================================================== %% 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, 1000, worker, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop(Host) -> Rooms = shutdown_rooms(Host), Proc = gen_mod:get_module_proc(Host, ?PROCNAME), gen_server:call(Proc, stop), supervisor:delete_child(ejabberd_sup, Proc), {wait, Rooms}. shutdown_rooms(Host) -> MyHost = gen_mod:get_module_opt_host(Host, mod_muc, <<"conference.@HOST@">>), Rooms = mnesia:dirty_select(muc_online_room, [{#muc_online_room{name_host = '$1', pid = '$2'}, [{'==', {element, 2, '$1'}, MyHost}, {'==', {node, '$2'}, node()}], ['$2']}]), [Pid ! shutdown || Pid <- Rooms], Rooms. %% This function is called by a room in three situations: %% A) The owner of the room destroyed it %% B) The only participant of a temporary room leaves it %% C) mod_muc:stop was called, and each room is being terminated %% In this case, the mod_muc process died before the room processes %% So the message sending must be catched room_destroyed(Host, Room, Pid, ServerHost) -> catch gen_mod:get_module_proc(ServerHost, ?PROCNAME) ! {room_destroyed, {Room, Host}, Pid}, ok. %% @doc Create a room. %% If Opts = default, the default room options are used. %% Else use the passed options as defined in mod_muc_room. create_room(Host, Name, From, Nick, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), gen_server:call(Proc, {create, Name, From, Nick, Opts}). store_room(ServerHost, Host, Name, Opts) -> LServer = jid:nameprep(ServerHost), store_room(LServer, Host, Name, Opts, gen_mod:db_type(LServer, ?MODULE)). store_room(_LServer, Host, Name, Opts, mnesia) -> F = fun () -> mnesia:write(#muc_room{name_host = {Name, Host}, opts = Opts}) end, mnesia:transaction(F); store_room(_LServer, Host, Name, Opts, riak) -> {atomic, ejabberd_riak:put(#muc_room{name_host = {Name, Host}, opts = Opts}, muc_room_schema())}; store_room(LServer, Host, Name, Opts, odbc) -> SName = ejabberd_odbc:escape(Name), SHost = ejabberd_odbc:escape(Host), SOpts = ejabberd_odbc:encode_term(Opts), F = fun () -> odbc_queries:update_t(<<"muc_room">>, [<<"name">>, <<"host">>, <<"opts">>], [SName, SHost, SOpts], [<<"name='">>, SName, <<"' and host='">>, SHost, <<"'">>]) end, ejabberd_odbc:sql_transaction(LServer, F). restore_room(ServerHost, Host, Name) -> LServer = jid:nameprep(ServerHost), restore_room(LServer, Host, Name, gen_mod:db_type(LServer, ?MODULE)). restore_room(_LServer, Host, Name, mnesia) -> case catch mnesia:dirty_read(muc_room, {Name, Host}) of [#muc_room{opts = Opts}] -> Opts; _ -> error end; restore_room(_LServer, Host, Name, riak) -> case ejabberd_riak:get(muc_room, muc_room_schema(), {Name, Host}) of {ok, #muc_room{opts = Opts}} -> Opts; _ -> error end; restore_room(LServer, Host, Name, odbc) -> SName = ejabberd_odbc:escape(Name), SHost = ejabberd_odbc:escape(Host), case catch ejabberd_odbc:sql_query(LServer, [<<"select opts from muc_room where name='">>, SName, <<"' and host='">>, SHost, <<"';">>]) of {selected, [<<"opts">>], [[Opts]]} -> opts_to_binary(ejabberd_odbc:decode_term(Opts)); _ -> error end. forget_room(ServerHost, Host, Name) -> LServer = jid:nameprep(ServerHost), forget_room(LServer, Host, Name, gen_mod:db_type(LServer, ?MODULE)). 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) -> 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 () -> ejabberd_odbc:sql_query_t([<<"delete from muc_room where name='">>, SName, <<"' and host='">>, SHost, <<"';">>]) end, ejabberd_odbc:sql_transaction(LServer, F). remove_room_mam(LServer, Host, Name) -> case gen_mod:is_loaded(LServer, mod_mam) of true -> U = jid:nodeprep(Name), S = jid:nameprep(Host), DBType = gen_mod:db_type(LServer, mod_mam), if DBType == odbc -> mod_mam:remove_user(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), 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, DiscoNode, Rsm)}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)). can_use_nick(_ServerHost, _Host, _JID, <<"">>) -> false; can_use_nick(ServerHost, Host, JID, Nick) -> 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, _} = jid:tolower(JID), LUS = {LUser, LServer}, case catch mnesia:dirty_select(muc_registered, [{#muc_registered{us_host = '$1', nick = Nick, _ = '_'}, [{'==', {element, 2, '$1'}, Host}], ['$_']}]) of {'EXIT', _Reason} -> true; [] -> true; [#muc_registered{us_host = {U, _Host}}] -> U == LUS end; can_use_nick(LServer, Host, JID, Nick, riak) -> {LUser, LServer, _} = jid:tolower(JID), LUS = {LUser, LServer}, case ejabberd_riak:get_by_index(muc_registered, muc_registered_schema(), <<"nick_host">>, {Nick, Host}) of {ok, []} -> true; {ok, [#muc_registered{us_host = {U, _Host}}]} -> U == LUS; {error, _} -> true end; can_use_nick(LServer, Host, JID, Nick, odbc) -> SJID = 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, [<<"select jid from muc_registered ">>, <<"where nick='">>, SNick, <<"' and host='">>, SHost, <<"';">>]) of {selected, [<<"jid">>], [[SJID1]]} -> SJID == SJID1; _ -> true end. %%==================================================================== %% gen_server callbacks %%==================================================================== init([Host, Opts]) -> MyHost = gen_mod:get_opt_host(Host, Opts, <<"conference.@HOST@">>), case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(muc_room, [{disc_copies, [node()]}, {attributes, record_info(fields, muc_room)}]), mnesia:create_table(muc_registered, [{disc_copies, [node()]}, {attributes, record_info(fields, muc_registered)}]), update_tables(MyHost), mnesia:add_table_index(muc_registered, nick); _ -> ok end, mnesia:create_table(muc_online_room, [{ram_copies, [node()]}, {attributes, record_info(fields, muc_online_room)}]), mnesia:add_table_copy(muc_online_room, node(), ram_copies), 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) 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:flatmap( fun({Opt, Val}) -> Bool = fun(B) when is_boolean(B) -> B end, VFun = case Opt of 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; mam -> Bool; 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; 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]), fun(_) -> undefined end end, 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, none), ejabberd_router:register_route(MyHost), load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin, AccessPersistent}, HistorySize, RoomShaper), {ok, #state{host = MyHost, server_host = Host, access = {Access, AccessCreate, AccessAdmin, AccessPersistent}, default_room_opts = DefRoomOpts, history_size = HistorySize, room_shaper = RoomShaper}}. handle_call(stop, _From, State) -> {stop, normal, ok, State}; handle_call({create, Room, From, Nick, Opts}, _From, #state{host = Host, server_host = ServerHost, access = Access, default_room_opts = DefOpts, history_size = HistorySize, room_shaper = RoomShaper} = State) -> ?DEBUG("MUC: create new room '~s'~n", [Room]), NewOpts = case Opts of default -> DefOpts; _ -> Opts end, {ok, Pid} = mod_muc_room:start( Host, ServerHost, Access, Room, HistorySize, RoomShaper, From, Nick, NewOpts), register_room(Host, Room, Pid), {reply, ok, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({route, From, To, Packet}, #state{host = Host, server_host = ServerHost, access = Access, default_room_opts = DefRoomOpts, history_size = HistorySize, room_shaper = RoomShaper} = State) -> case catch do_route(Host, ServerHost, Access, HistorySize, RoomShaper, From, To, Packet, DefRoomOpts) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); _ -> ok end, {noreply, State}; handle_info({room_destroyed, RoomHost, Pid}, State) -> F = fun () -> mnesia:delete_object(#muc_online_room{name_host = RoomHost, pid = Pid}) end, mnesia:transaction(F), {noreply, State}; handle_info({mnesia_system_event, {mnesia_down, Node}}, State) -> clean_table_from_bad_node(Node), {noreply, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, State) -> ejabberd_router:unregister_route(State#state.host), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- do_route(Host, ServerHost, Access, HistorySize, RoomShaper, From, To, Packet, DefRoomOpts) -> {AccessRoute, _AccessCreate, _AccessAdmin, _AccessPersistent} = Access, case acl:match_rule(ServerHost, AccessRoute, From) of allow -> do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, 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)), ejabberd_router:route_error(To, From, Err, Packet) end. do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, From, To, Packet, DefRoomOpts) -> {_AccessRoute, AccessCreate, AccessAdmin, _AccessPersistent} = Access, {Room, _, Nick} = jid:tolower(To), #xmlel{name = Name, attrs = Attrs} = Packet, case Room of <<"">> -> case Nick of <<"">> -> case Name of <<"iq">> -> case jlib:iq_query_info(Packet) of #iq{type = get, xmlns = (?NS_DISCO_INFO) = XMLNS, sub_el = _SubEl, lang = Lang} = IQ -> Info = ejabberd_hooks:run_fold(disco_info, ServerHost, [], [ServerHost, ?MODULE, <<"">>, <<"">>]), Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = iq_disco_info( ServerHost, Lang) ++ Info}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); #iq{type = get, xmlns = ?NS_DISCO_ITEMS} = IQ -> spawn(?MODULE, process_iq_disco_items, [Host, From, To, IQ]); #iq{type = get, xmlns = (?NS_REGISTER) = XMLNS, lang = Lang, sub_el = _SubEl} = IQ -> Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = iq_get_register_info(ServerHost, Host, From, Lang)}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); #iq{type = set, xmlns = (?NS_REGISTER) = XMLNS, lang = Lang, sub_el = SubEl} = IQ -> case process_iq_register_set(ServerHost, Host, From, SubEl, Lang) of {result, IQRes} -> Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = IQRes}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); {error, Error} -> Err = jlib:make_error_reply(Packet, Error), ejabberd_router:route(To, From, Err) end; #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 = get, xmlns = ?NS_MUC_UNIQUE} = IQ -> Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"unique">>, attrs = [{<<"xmlns">>, ?NS_MUC_UNIQUE}], children = [iq_get_unique(From)]}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(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 acl:match_rule(ServerHost, AccessAdmin, From) of allow -> Msg = xml:get_path_s(Packet, [{elem, <<"body">>}, cdata]), broadcast_service_message(Host, Msg); _ -> Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), ErrText = <<"Only service administrators are allowed " "to send service messages">>, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), ejabberd_router:route(To, From, Err) end end; <<"presence">> -> 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; _ -> 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 true -> {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; false -> Lang = xml: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), 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, 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); _ -> false end. get_rooms(ServerHost, Host) -> LServer = jid:nameprep(ServerHost), get_rooms(LServer, Host, gen_mod:db_type(LServer, ?MODULE)). get_rooms(_LServer, Host, mnesia) -> case catch mnesia:dirty_select(muc_room, [{#muc_room{name_host = {'_', Host}, _ = '_'}, [], ['$_']}]) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), []; Rs -> Rs end; get_rooms(_LServer, Host, riak) -> case ejabberd_riak:get(muc_room, muc_room_schema()) of {ok, Rs} -> lists:filter( fun(#muc_room{name_host = {_, H}}) -> Host == H end, Rs); _Err -> [] end; get_rooms(LServer, Host, odbc) -> SHost = ejabberd_odbc:escape(Host), case catch ejabberd_odbc:sql_query(LServer, [<<"select name, opts from muc_room ">>, <<"where host='">>, SHost, <<"';">>]) of {selected, [<<"name">>, <<"opts">>], RoomOpts} -> lists:map(fun ([Room, Opts]) -> #muc_room{name_host = {Room, Host}, opts = opts_to_binary( ejabberd_odbc:decode_term(Opts))} end, RoomOpts); Err -> ?ERROR_MSG("failed to get rooms: ~p", [Err]), [] end. 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)). start_new_room(Host, ServerHost, Access, Room, HistorySize, RoomShaper, From, Nick, DefRoomOpts) -> case restore_room(ServerHost, Host, Room) of error -> ?DEBUG("MUC: open new room '~s'~n", [Room]), 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) end. register_room(Host, Room, Pid) -> F = fun() -> mnesia:write(#muc_online_room{name_host = {Room, Host}, pid = Pid}) end, mnesia:transaction(F). iq_disco_info(ServerHost, Lang) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"conference">>}, {<<"type">>, <<"text">>}, {<<"name">>, translate:translate(Lang, <<"Chatrooms">>)}], 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_MUC}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_MUC_UNIQUE}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_REGISTER}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_RSM}], children = []}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_VCARD}], children = []}] ++ case gen_mod:is_loaded(ServerHost, mod_mam) of true -> [#xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_MAM_0}]}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_MAM_1}]}]; false -> [] 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">>}, {<<"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, Query, 100) of {item, Desc} -> flush(), {true, #xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string({Name, Host, <<"">>})}, {<<"name">>, Desc}], children = []}}; _ -> false end end, Rooms). get_vh_rooms(Host, #rsm_in{max=M, direction=Direction, id=I, index=Index})-> AllRooms = lists:sort(get_vh_rooms(Host)), Count = erlang:length(AllRooms), Guard = case Direction of _ when Index =/= undefined -> [{'==', {element, 2, '$1'}, Host}]; aft -> [{'==', {element, 2, '$1'}, Host}, {'>=',{element, 1, '$1'} ,I}]; before when I =/= []-> [{'==', {element, 2, '$1'}, Host}, {'=<',{element, 1, '$1'} ,I}]; _ -> [{'==', {element, 2, '$1'}, Host}] end, L = lists:sort( mnesia:dirty_select(muc_online_room, [{#muc_online_room{name_host = '$1', _ = '_'}, Guard, ['$_']}])), L2 = if Index == undefined andalso Direction == before -> lists:reverse(lists:sublist(lists:reverse(L), 1, M)); Index == undefined -> lists:sublist(L, 1, M); Index > Count orelse Index < 0 -> []; true -> lists:sublist(L, Index+1, M) end, if L2 == [] -> {L2, #rsm_out{count = Count}}; true -> H = hd(L2), NewIndex = get_room_pos(H, AllRooms), T = lists:last(L2), {F, _} = H#muc_online_room.name_host, {Last, _} = T#muc_online_room.name_host, {L2, #rsm_out{first = F, last = Last, count = Count, index = NewIndex}} end. %% @doc Return the position of desired room in the list of rooms. %% The room must exist in the list. The count starts in 0. %% @spec (Desired::muc_online_room(), Rooms::[muc_online_room()]) -> integer() get_room_pos(Desired, Rooms) -> get_room_pos(Desired, Rooms, 0). get_room_pos(Desired, [HeadRoom | _], HeadPosition) when Desired#muc_online_room.name_host == HeadRoom#muc_online_room.name_host -> HeadPosition; get_room_pos(Desired, [_ | Rooms], HeadPosition) -> get_room_pos(Desired, Rooms, HeadPosition + 1). flush() -> receive _ -> flush() after 0 -> ok 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}]}]}). iq_get_unique(From) -> {xmlcdata, p1_sha:sha(term_to_binary([From, p1_time_compat:timestamp(), randoms:get_string()]))}. get_nick(ServerHost, Host, From) -> LServer = jid:nameprep(ServerHost), get_nick(LServer, Host, From, gen_mod:db_type(LServer, ?MODULE)). get_nick(_LServer, Host, From, mnesia) -> {LUser, LServer, _} = jid:tolower(From), LUS = {LUser, LServer}, case catch mnesia:dirty_read(muc_registered, {LUS, Host}) of {'EXIT', _Reason} -> error; [] -> error; [#muc_registered{nick = Nick}] -> Nick end; get_nick(LServer, Host, From, riak) -> {LUser, LServer, _} = jid:tolower(From), US = {LUser, LServer}, case ejabberd_riak:get(muc_registered, muc_registered_schema(), {US, Host}) of {ok, #muc_registered{nick = Nick}} -> Nick; {error, _} -> error end; get_nick(LServer, Host, From, odbc) -> SJID = 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 " "jid='">>, SJID, <<"' and host='">>, SHost, <<"';">>]) of {selected, [<<"nick">>], [[Nick]]} -> Nick; _ -> error end. iq_get_register_info(ServerHost, Host, From, Lang) -> {Nick, Registered} = case get_nick(ServerHost, Host, From) of error -> {<<"">>, []}; N -> {N, [#xmlel{name = <<"registered">>, attrs = [], children = []}]} end, Registered ++ [#xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"You need a client that supports x:data " "to register the nickname">>)}]}, #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = [#xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"Nickname Registration at ">>))/binary, Host/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Enter nickname you want to register">>)}]}, ?XFIELD(<<"text-single">>, <<"Nickname">>, <<"nick">>, Nick)]}]. set_nick(ServerHost, Host, From, Nick) -> 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, _} = jid:tolower(From), LUS = {LUser, LServer}, F = fun () -> case Nick of <<"">> -> mnesia:delete({muc_registered, {LUS, Host}}), ok; _ -> Allow = case mnesia:select(muc_registered, [{#muc_registered{us_host = '$1', nick = Nick, _ = '_'}, [{'==', {element, 2, '$1'}, Host}], ['$_']}]) of [] -> true; [#muc_registered{us_host = {U, _Host}}] -> U == LUS end, if Allow -> mnesia:write(#muc_registered{us_host = {LUS, Host}, nick = Nick}), ok; true -> false end end end, mnesia:transaction(F); set_nick(LServer, Host, From, Nick, riak) -> {LUser, LServer, _} = jid:tolower(From), LUS = {LUser, LServer}, {atomic, case Nick of <<"">> -> ejabberd_riak:delete(muc_registered, {LUS, Host}); _ -> Allow = case ejabberd_riak:get_by_index( muc_registered, muc_registered_schema(), <<"nick_host">>, {Nick, Host}) of {ok, []} -> true; {ok, [#muc_registered{us_host = {U, _Host}}]} -> U == LUS; {error, _} -> false end, if Allow -> ejabberd_riak:put(#muc_registered{us_host = {LUS, Host}, nick = Nick}, muc_registered_schema(), [{'2i', [{<<"nick_host">>, {Nick, Host}}]}]); true -> false end end}; set_nick(LServer, Host, From, Nick, odbc) -> JID = jid:to_string(jid:tolower(jid:remove_resource(From))), SJID = ejabberd_odbc:escape(JID), SNick = ejabberd_odbc:escape(Nick), SHost = ejabberd_odbc:escape(Host), F = fun () -> case Nick of <<"">> -> ejabberd_odbc:sql_query_t([<<"delete from muc_registered where ">>, <<"jid='">>, SJID, <<"' and host='">>, Host, <<"';">>]), ok; _ -> Allow = case ejabberd_odbc:sql_query_t([<<"select jid from muc_registered ">>, <<"where nick='">>, SNick, <<"' and host='">>, SHost, <<"';">>]) of {selected, [<<"jid">>], [[J]]} -> J == JID; _ -> true end, if Allow -> odbc_queries:update_t(<<"muc_registered">>, [<<"jid">>, <<"host">>, <<"nick">>], [SJID, SHost, SNick], [<<"jid='">>, SJID, <<"' and host='">>, SHost, <<"'">>]), ok; true -> false end end end, ejabberd_odbc:sql_transaction(LServer, F). iq_set_register_info(ServerHost, Host, From, Nick, Lang) -> case set_nick(ServerHost, Host, From, Nick) of {atomic, ok} -> {result, []}; {atomic, false} -> ErrText = <<"That nickname is registered by another " "person">>, {error, ?ERRT_CONFLICT(Lang, ErrText)}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end. process_iq_register_set(ServerHost, Host, From, SubEl, Lang) -> #xmlel{children = Els} = SubEl, case xml:get_subtag(SubEl, <<"remove">>) of false -> 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">>} -> XData = jlib:parse_xdata_submit(XEl), case XData of invalid -> {error, ?ERR_BAD_REQUEST}; _ -> case lists:keysearch(<<"nick">>, 1, XData) of {value, {_, [Nick]}} when Nick /= <<"">> -> iq_set_register_info(ServerHost, Host, From, Nick, Lang); _ -> ErrText = <<"You must fill in field \"Nickname\" " "in the form">>, {error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)} end end; _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end; _ -> iq_set_register_info(ServerHost, Host, From, <<"">>, Lang) end. iq_get_vcard(Lang) -> [#xmlel{name = <<"FN">>, attrs = [], children = [{xmlcdata, <<"ejabberd/mod_muc">>}]}, #xmlel{name = <<"URL">>, attrs = [], children = [{xmlcdata, ?EJABBERD_URI}]}, #xmlel{name = <<"DESC">>, attrs = [], children = [{xmlcdata, <<(translate:translate(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)). get_vh_rooms(Host) -> mnesia:dirty_select(muc_online_room, [{#muc_online_room{name_host = '$1', _ = '_'}, [{'==', {element, 2, '$1'}, Host}], ['$_']}]). clean_table_from_bad_node(Node) -> F = fun() -> Es = mnesia:select( muc_online_room, [{#muc_online_room{pid = '$1', _ = '_'}, [{'==', {node, '$1'}, Node}], ['$_']}]), lists:foreach(fun(E) -> mnesia:delete_object(E) end, Es) end, mnesia:async_dirty(F). clean_table_from_bad_node(Node, Host) -> F = fun() -> Es = mnesia:select( muc_online_room, [{#muc_online_room{pid = '$1', name_host = {'_', Host}, _ = '_'}, [{'==', {node, '$1'}, Node}], ['$_']}]), lists:foreach(fun(E) -> mnesia:delete_object(E) end, Es) end, mnesia:async_dirty(F). opts_to_binary(Opts) -> lists:map( fun({title, Title}) -> {title, iolist_to_binary(Title)}; ({description, Desc}) -> {description, iolist_to_binary(Desc)}; ({password, Pass}) -> {password, iolist_to_binary(Pass)}; ({subject, Subj}) -> {subject, iolist_to_binary(Subj)}; ({subject_author, Author}) -> {subject_author, iolist_to_binary(Author)}; ({affiliations, Affs}) -> {affiliations, lists:map( fun({{U, S, R}, Aff}) -> NewAff = case Aff of {A, Reason} -> {A, iolist_to_binary(Reason)}; _ -> Aff end, {{iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(R)}, NewAff} end, Affs)}; ({captcha_whitelist, CWList}) -> {captcha_whitelist, lists:map( fun({U, S, R}) -> {iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(R)} end, CWList)}; (Opt) -> Opt end, Opts). update_tables(Host) -> update_muc_room_table(Host), update_muc_registered_table(Host). muc_room_schema() -> {record_info(fields, muc_room), #muc_room{}}. muc_registered_schema() -> {record_info(fields, muc_registered), #muc_registered{}}. update_muc_room_table(_Host) -> Fields = record_info(fields, muc_room), case mnesia:table_info(muc_room, attributes) of Fields -> ejabberd_config:convert_table_to_binary( muc_room, Fields, set, fun(#muc_room{name_host = {N, _}}) -> N end, fun(#muc_room{name_host = {N, H}, opts = Opts} = R) -> R#muc_room{name_host = {iolist_to_binary(N), iolist_to_binary(H)}, opts = opts_to_binary(Opts)} end); _ -> ?INFO_MSG("Recreating muc_room table", []), mnesia:transform_table(muc_room, ignore, Fields) end. update_muc_registered_table(_Host) -> Fields = record_info(fields, muc_registered), case mnesia:table_info(muc_registered, attributes) of Fields -> ejabberd_config:convert_table_to_binary( muc_registered, Fields, set, fun(#muc_registered{us_host = {_, H}}) -> H end, fun(#muc_registered{us_host = {{U, S}, H}, nick = Nick} = R) -> R#muc_registered{us_host = {{iolist_to_binary(U), iolist_to_binary(S)}, iolist_to_binary(H)}, nick = iolist_to_binary(Nick)} end); _ -> ?INFO_MSG("Recreating muc_registered table", []), mnesia:transform_table(muc_registered, ignore, Fields) end. export(_Server) -> [{muc_room, fun(Host, #muc_room{name_host = {Name, RoomHost}, opts = Opts}) -> case str:suffix(Host, RoomHost) of true -> SName = ejabberd_odbc:escape(Name), SRoomHost = ejabberd_odbc:escape(RoomHost), SOpts = ejabberd_odbc:encode_term(Opts), [[<<"delete from muc_room where name='">>, SName, <<"' and host='">>, SRoomHost, <<"';">>], [<<"insert into muc_room(name, host, opts) ", "values (">>, <<"'">>, SName, <<"', '">>, SRoomHost, <<"', '">>, SOpts, <<"');">>]]; false -> [] end end}, {muc_registered, fun(Host, #muc_registered{us_host = {{U, S}, RoomHost}, nick = Nick}) -> case str:suffix(Host, RoomHost) of true -> SJID = ejabberd_odbc:escape( jid:to_string( jid:make(U, S, <<"">>))), SNick = ejabberd_odbc:escape(Nick), SRoomHost = ejabberd_odbc:escape(RoomHost), [[<<"delete from muc_registered where jid='">>, SJID, <<"' and host='">>, SRoomHost, <<"';">>], [<<"insert into muc_registered(jid, host, " "nick) values ('">>, SJID, <<"', '">>, SRoomHost, <<"', '">>, SNick, <<"');">>]]; false -> [] end end}]. 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} end}, {<<"select jid, host, nick from muc_registered;">>, fun([J, RoomHost, Nick]) -> #jid{user = U, server = S} = jid:from_string(J), #muc_registered{us_host = {{U, S}, RoomHost}, nick = Nick} end}]. import(_LServer, mnesia, #muc_room{} = R) -> mnesia:dirty_write(R); import(_LServer, mnesia, #muc_registered{} = R) -> mnesia:dirty_write(R); import(_LServer, riak, #muc_room{} = R) -> ejabberd_riak:put(R, muc_room_schema()); import(_LServer, riak, #muc_registered{us_host = {_, Host}, nick = Nick} = R) -> ejabberd_riak:put(R, muc_registered_schema(), [{'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_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(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_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]. ejabberd-16.01/src/ejabberd_oauth.erl0000644000232200023220000005601612645157216020077 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% 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 jid:make(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. 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 = jid:nodeprep(User), LServer = jid: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 = jid:nodeprep(User), LServer = jid: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,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=">>. opt_type(oauth_expire) -> fun(I) when is_integer(I), I >= 0 -> I end; opt_type(oauth_access) -> fun(A) when is_atom(A) -> A end; opt_type(_) -> [oauth_expire, oauth_access]. ejabberd-16.01/src/mod_proxy65_stream.erl0000644000232200023220000002262112645157216020702 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_proxy65_stream.erl %%% Author : Evgeniy Khramtsov %%% Purpose : Bytestream process. %%% Created : 12 Oct 2006 by Evgeniy 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(mod_proxy65_stream). -author('xram@jabber.ru'). -behaviour(gen_fsm). %% gen_fsm callbacks. -export([init/1, handle_event/3, handle_sync_event/4, code_change/4, handle_info/3, terminate/3]). %% gen_fsm states. -export([wait_for_init/2, wait_for_auth/2, wait_for_request/2, wait_for_activation/2, stream_established/2]). -export([start/2, stop/1, start_link/3, activate/2, relay/3, socket_type/0]). -include("mod_proxy65.hrl"). -include("ejabberd.hrl"). -include("logger.hrl"). -define(WAIT_TIMEOUT, 60000). -record(state, {socket :: inet:socket(), timer = make_ref() :: reference(), sha1 = <<"">> :: binary(), host = <<"">> :: binary(), auth_type = anonymous :: plain | anonymous, shaper = none :: shaper:shaper()}). %% Unused callbacks handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. %%------------------------------- start({gen_tcp, Socket}, Opts1) -> {[Host], Opts} = lists:partition(fun (O) -> is_binary(O) end, Opts1), Supervisor = gen_mod:get_module_proc(Host, ejabberd_mod_proxy65_sup), supervisor:start_child(Supervisor, [Socket, Host, Opts]). start_link(Socket, Host, Opts) -> gen_fsm:start_link(?MODULE, [Socket, Host, Opts], []). init([Socket, Host, Opts]) -> process_flag(trap_exit, true), AuthType = gen_mod:get_opt(auth_type, Opts, fun(plain) -> plain; (anonymous) -> anonymous end, anonymous), Shaper = gen_mod:get_opt(shaper, Opts, fun(A) when is_atom(A) -> A end, none), RecvBuf = gen_mod:get_opt(recbuf, Opts, fun(I) when is_integer(I), I>0 -> I end, 8192), SendBuf = gen_mod:get_opt(sndbuf, Opts, fun(I) when is_integer(I), I>0 -> I end, 8192), TRef = erlang:send_after(?WAIT_TIMEOUT, self(), stop), inet:setopts(Socket, [{active, true}, {recbuf, RecvBuf}, {sndbuf, SendBuf}]), {ok, wait_for_init, #state{host = Host, auth_type = AuthType, socket = Socket, shaper = Shaper, timer = TRef}}. terminate(_Reason, StateName, #state{sha1 = SHA1}) -> catch mod_proxy65_sm:unregister_stream(SHA1), if StateName == stream_established -> ?INFO_MSG("Bytestream terminated", []); true -> ok end. %%%------------------------------ %%% API. %%%------------------------------ socket_type() -> raw. stop(StreamPid) -> StreamPid ! stop. activate({P1, J1}, {P2, J2}) -> case catch {gen_fsm:sync_send_all_state_event(P1, get_socket), gen_fsm:sync_send_all_state_event(P2, get_socket)} of {S1, S2} when is_port(S1), is_port(S2) -> P1 ! {activate, P2, S2, J1, J2}, P2 ! {activate, P1, S1, J1, J2}, JID1 = jid:to_string(J1), JID2 = jid:to_string(J2), ?INFO_MSG("(~w:~w) Activated bytestream for ~s " "-> ~s", [P1, P2, JID1, JID2]), ok; _ -> error end. %%%----------------------- %%% States %%%----------------------- wait_for_init(Packet, #state{socket = Socket, auth_type = AuthType} = StateData) -> case mod_proxy65_lib:unpack_init_message(Packet) of {ok, AuthMethods} -> Method = select_auth_method(AuthType, AuthMethods), gen_tcp:send(Socket, mod_proxy65_lib:make_init_reply(Method)), case Method of ?AUTH_ANONYMOUS -> {next_state, wait_for_request, StateData}; ?AUTH_PLAIN -> {next_state, wait_for_auth, StateData}; ?AUTH_NO_METHODS -> {stop, normal, StateData} end; error -> {stop, normal, StateData} end. 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), gen_tcp:send(Socket, mod_proxy65_lib:make_auth_reply(Result)), case Result of true -> {next_state, wait_for_request, StateData}; false -> {stop, normal, StateData} end; _ -> {stop, normal, StateData} end. wait_for_request(Packet, #state{socket = Socket} = StateData) -> Request = mod_proxy65_lib:unpack_request(Packet), case Request of #s5_request{sha1 = SHA1, cmd = connect} -> case catch mod_proxy65_sm:register_stream(SHA1) of {atomic, ok} -> inet:setopts(Socket, [{active, false}]), gen_tcp:send(Socket, mod_proxy65_lib:make_reply(Request)), {next_state, wait_for_activation, StateData#state{sha1 = SHA1}}; _ -> Err = mod_proxy65_lib:make_error_reply(Request), gen_tcp:send(Socket, Err), {stop, normal, StateData} end; #s5_request{cmd = udp} -> Err = mod_proxy65_lib:make_error_reply(Request, ?ERR_COMMAND_NOT_SUPPORTED), gen_tcp:send(Socket, Err), {stop, normal, StateData}; _ -> {stop, normal, StateData} end. wait_for_activation(_Data, StateData) -> {next_state, wait_for_activation, StateData}. stream_established(_Data, StateData) -> {next_state, stream_established, StateData}. %%%----------------------- %%% Callbacks processing %%%----------------------- %% SOCKS5 packets. handle_info({tcp, _S, Data}, StateName, StateData) when StateName /= wait_for_activation -> erlang:cancel_timer(StateData#state.timer), TRef = erlang:send_after(?WAIT_TIMEOUT, self(), stop), gen_fsm:send_event(self(), Data), {next_state, StateName, StateData#state{timer = TRef}}; %% Activation message. handle_info({activate, PeerPid, PeerSocket, IJid, TJid}, wait_for_activation, StateData) -> erlang:monitor(process, PeerPid), erlang:cancel_timer(StateData#state.timer), MySocket = StateData#state.socket, Shaper = StateData#state.shaper, Host = StateData#state.host, MaxRate = find_maxrate(Shaper, IJid, TJid, Host), spawn_link(?MODULE, relay, [MySocket, PeerSocket, MaxRate]), {next_state, stream_established, StateData}; %% Socket closed handle_info({tcp_closed, _Socket}, _StateName, StateData) -> {stop, normal, StateData}; handle_info({tcp_error, _Socket, _Reason}, _StateName, StateData) -> {stop, normal, StateData}; %% Got stop message. handle_info(stop, _StateName, StateData) -> {stop, normal, StateData}; %% Either linked process or peer process died. handle_info({'EXIT', _, _}, _StateName, StateData) -> {stop, normal, StateData}; handle_info({'DOWN', _, _, _, _}, _StateName, StateData) -> {stop, normal, StateData}; %% Packets of no interest handle_info(_Info, StateName, StateData) -> {next_state, StateName, StateData}. %% Socket request. handle_sync_event(get_socket, _From, wait_for_activation, StateData) -> Socket = StateData#state.socket, {reply, Socket, wait_for_activation, StateData}; handle_sync_event(_Event, _From, StateName, StateData) -> {reply, error, StateName, StateData}. %%%------------------------------------------------- %%% Relay Process. %%%------------------------------------------------- relay(MySocket, PeerSocket, Shaper) -> case gen_tcp:recv(MySocket, 0) of {ok, Data} -> gen_tcp:send(PeerSocket, Data), {NewShaper, Pause} = shaper:update(Shaper, byte_size(Data)), if Pause > 0 -> timer:sleep(Pause); true -> pass end, relay(MySocket, PeerSocket, NewShaper); _ -> stopped end. %%%------------------------ %%% Auxiliary functions %%%------------------------ select_auth_method(plain, AuthMethods) -> case lists:member(?AUTH_PLAIN, AuthMethods) of true -> ?AUTH_PLAIN; false -> ?AUTH_NO_METHODS end; select_auth_method(anonymous, AuthMethods) -> case lists:member(?AUTH_ANONYMOUS, AuthMethods) of true -> ?AUTH_ANONYMOUS; false -> ?AUTH_NO_METHODS end. %% Obviously, we must use shaper with maximum rate. find_maxrate(Shaper, JID1, JID2, Host) -> MaxRate1 = case acl:match_rule(Host, Shaper, JID1) of deny -> none; R1 -> shaper:new(R1) end, MaxRate2 = case acl:match_rule(Host, Shaper, JID2) of deny -> none; R2 -> shaper:new(R2) end, if MaxRate1 == none; MaxRate2 == none -> none; true -> lists:max([MaxRate1, MaxRate2]) end. ejabberd-16.01/src/mod_http_bind.erl0000644000232200023220000003553112645157216017752 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_http_bind.erl %%% Author : Stefan Strigler %%% Purpose : Implementation of XMPP over BOSH (XEP-0206) %%% Created : Tue Feb 20 13:15:52 CET 2007 %%% %%% %%% 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. %%% %%%---------------------------------------------------------------------- %%%---------------------------------------------------------------------- %%% This module acts as a bridge to ejabberd_http_bind which implements %%% the real stuff, this is to handle the new pluggable architecture for %%% extending ejabberd's http service. %%%---------------------------------------------------------------------- -module(mod_http_bind). -author('steve@zeank.in-berlin.de'). %%-define(ejabberd_debug, true). -behaviour(gen_mod). -export([start/2, stop/1, process/2, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_http.hrl"). -include("http_bind.hrl"). -define(PROCNAME_MHB, ejabberd_mod_http_bind). %% Duplicated from ejabberd_http_bind. %% TODO: move to hrl file. -record(http_bind, {id, pid, to, hold, wait, process_delay, version}). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- process([], #request{method = 'POST', data = <<>>}) -> ?DEBUG("Bad Request: no data", []), {400, ?HEADER, #xmlel{name = <<"h1">>, children = [{xmlcdata, <<"400 Bad Request">>}]}}; process([], #request{method = 'POST', data = Data, ip = IP, opts = Opts}) -> ?DEBUG("Incoming data: ~s", [Data]), ejabberd_http_bind:process_request(Data, IP, Opts); process([], #request{method = 'GET', data = <<>>}) -> {200, ?HEADER, get_human_html_xmlel()}; process([], #request{method = 'OPTIONS', data = <<>>}) -> {200, ?OPTIONS_HEADER, <<>>}; process([], #request{method = 'HEAD'}) -> {200, ?HEADER, <<>>}; process(_Path, _Request) -> ?DEBUG("Bad Request: ~p", [_Request]), {400, ?HEADER, #xmlel{name = <<"h1">>, children = [{xmlcdata, <<"400 Bad Request">>}]}}. %%%---------------------------------------------------------------------- %%% BEHAVIOUR CALLBACKS %%%---------------------------------------------------------------------- start(_Host, _Opts) -> setup_database(). stop(_Host) -> ok. setup_database() -> migrate_database(), mnesia:create_table(http_bind, [{ram_copies, [node()]}, {attributes, record_info(fields, http_bind)}]). migrate_database() -> case catch mnesia:table_info(http_bind, attributes) of [id, pid, to, hold, wait, process_delay, version] -> ok; _ -> %% Since the stored information is not important, instead %% 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]. %%%---------------------------------------------------------------------- %%% 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=">>. ejabberd-16.01/src/ejabberd_sm_redis.erl0000644000232200023220000001506312645157216020561 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov %%% @copyright (C) 2015, Evgeny Khramtsov %%% @doc %%% %%% @end %%% Created : 11 Mar 2015 by Evgeny Khramtsov %%%------------------------------------------------------------------- -module(ejabberd_sm_redis). -behaviour(ejabberd_config). -behaviour(ejabberd_sm). -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"). -include("logger.hrl"). -include("jlib.hrl"). -define(PROCNAME, 'ejabberd_redis_client'). %%%=================================================================== %%% API %%%=================================================================== -spec init() -> ok | {error, any()}. init() -> Server = ejabberd_config:get_option(redis_server, fun iolist_to_list/1, "localhost"), Port = ejabberd_config:get_option(redis_port, fun(P) when is_integer(P), P>0, P<65536 -> P end, 6379), DB = ejabberd_config:get_option(redis_db, fun(I) when is_integer(I), I >= 0 -> I end, 0), Pass = ejabberd_config:get_option(redis_password, fun iolist_to_list/1, ""), ReconnTimeout = timer:seconds( ejabberd_config:get_option( redis_reconnect_timeout, fun(I) when is_integer(I), I>0 -> I end, 1)), ConnTimeout = timer:seconds( ejabberd_config:get_option( redis_connect_timeout, fun(I) when is_integer(I), I>0 -> I end, 1)), case eredis:start_link(Server, Port, DB, Pass, ReconnTimeout, ConnTimeout) of {ok, Client} -> register(?PROCNAME, Client), clean_table(), ok; {error, _} = Err -> ?ERROR_MSG("failed to start redis client: ~p", [Err]), Err end. -spec set_session(#session{}) -> ok. set_session(Session) -> T = term_to_binary(Session), USKey = us_to_key(Session#session.us), SIDKey = sid_to_key(Session#session.sid), ServKey = server_to_key(element(2, Session#session.us)), USSIDKey = us_sid_to_key(Session#session.us, Session#session.sid), case eredis:qp(?PROCNAME, [["HSET", USKey, SIDKey, T], ["HSET", ServKey, USSIDKey, T]]) of [{ok, _}, {ok, _}] -> ok; Err -> ?ERROR_MSG("failed to set session for redis: ~p", [Err]) end. -spec delete_session(binary(), binary(), binary(), sid()) -> {ok, #session{}} | {error, notfound}. delete_session(LUser, LServer, _LResource, SID) -> USKey = us_to_key({LUser, LServer}), case eredis:q(?PROCNAME, ["HGETALL", USKey]) of {ok, Vals} -> Ss = decode_session_list(Vals), case lists:keyfind(SID, #session.sid, Ss) of false -> {error, notfound}; Session -> SIDKey = sid_to_key(SID), ServKey = server_to_key(element(2, Session#session.us)), USSIDKey = us_sid_to_key(Session#session.us, SID), eredis:qp(?PROCNAME, [["HDEL", USKey, SIDKey], ["HDEL", ServKey, USSIDKey]]), {ok, Session} end; Err -> ?ERROR_MSG("failed to delete session from redis: ~p", [Err]), {error, notfound} end. -spec get_sessions() -> [#session{}]. get_sessions() -> lists:flatmap( fun(LServer) -> get_sessions(LServer) end, ?MYHOSTS). -spec get_sessions(binary()) -> [#session{}]. get_sessions(LServer) -> ServKey = server_to_key(LServer), case eredis:q(?PROCNAME, ["HGETALL", ServKey]) of {ok, Vals} -> decode_session_list(Vals); Err -> ?ERROR_MSG("failed to get sessions from redis: ~p", [Err]), [] end. -spec get_sessions(binary(), binary()) -> [#session{}]. get_sessions(LUser, LServer) -> USKey = us_to_key({LUser, LServer}), case eredis:q(?PROCNAME, ["HGETALL", USKey]) of {ok, Vals} when is_list(Vals) -> decode_session_list(Vals); Err -> ?ERROR_MSG("failed to get sessions from redis: ~p", [Err]), [] end. -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 {ok, Vals} when is_list(Vals) -> [S || S <- decode_session_list(Vals), element(3, S#session.usr) == LResource]; Err -> ?ERROR_MSG("failed to get sessions from redis: ~p", [Err]), [] end. %%%=================================================================== %%% Internal functions %%%=================================================================== iolist_to_list(IOList) -> binary_to_list(iolist_to_binary(IOList)). us_to_key({LUser, LServer}) -> <<"ejabberd:sm:", LUser/binary, "@", LServer/binary>>. server_to_key(LServer) -> <<"ejabberd:sm:", LServer/binary>>. us_sid_to_key(US, SID) -> term_to_binary({US, SID}). sid_to_key(SID) -> term_to_binary(SID). decode_session_list([_, Val|T]) -> [binary_to_term(Val)|decode_session_list(T)]; decode_session_list([]) -> []. clean_table() -> ?INFO_MSG("Cleaning Redis SM table...", []), lists:foreach( fun(LServer) -> ServKey = server_to_key(LServer), case eredis:q(?PROCNAME, ["HKEYS", ServKey]) of {ok, []} -> ok; {ok, Vals} -> Vals1 = lists:filter( fun(USSIDKey) -> {_, SID} = binary_to_term(USSIDKey), node(element(2, SID)) == node() end, Vals), Q1 = ["HDEL", ServKey | Vals1], Q2 = lists:map( fun(USSIDKey) -> {US, SID} = binary_to_term(USSIDKey), USKey = us_to_key(US), SIDKey = sid_to_key(SID), ["HDEL", USKey, SIDKey] end, Vals1), Res = eredis:qp(?PROCNAME, [Q1|Q2]), case lists:filter( fun({ok, _}) -> false; (_) -> true end, Res) of [] -> ok; Errs -> ?ERROR_MSG("failed to clean redis table for " "server ~s: ~p", [LServer, Errs]) end; Err -> ?ERROR_MSG("failed to clean redis table for " "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]. ejabberd-16.01/src/mod_offline.erl0000644000232200023220000011035012645157216017412 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_offline.erl %%% Author : Alexey Shchepin %%% Purpose : Store and manage offline messages. %%% Created : 5 Jan 2003 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(mod_offline). -author('alexey@process-one.net'). -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). -behaviour(gen_mod). -export([count_offline_messages/2]). -export([start/2, start_link/2, stop/1, store_packet/3, resend_offline_messages/2, pop_offline_messages/3, get_sm_features/5, remove_expired_messages/1, remove_old_messages/2, remove_user/2, import/1, import/3, export/1, get_queue_length/2, get_offline_els/2, webadmin_page/3, webadmin_user/4, webadmin_user_parse_query/5]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_http.hrl"). -include("ejabberd_web_admin.hrl"). -include("mod_offline.hrl"). -define(PROCNAME, ejabberd_offline). -define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000). %% default value for the maximum number of user messages -define(MAX_USER_MESSAGES, infinity). 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), catch ?GEN_SERVER:call(Proc, stop), supervisor:terminate_child(ejabberd_sup, Proc), supervisor:delete_child(ejabberd_sup, Proc), ok. %%==================================================================== %% gen_server callbacks %%==================================================================== init([Host, Opts]) -> case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(offline_msg, [{disc_only_copies, [node()]}, {type, bag}, {attributes, record_info(fields, offline_msg)}]), update_table(); _ -> ok end, ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, store_packet, 50), ejabberd_hooks:add(resend_offline_messages_hook, Host, ?MODULE, pop_offline_messages, 50), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_sm_features, 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), 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}}. handle_call(stop, _From, State) -> {stop, normal, ok, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info(#offline_msg{us = UserServer} = Msg, State) -> #state{host = Host, access_max_offline_messages = AccessMaxOfflineMsgs} = State, DBType = gen_mod:db_type(Host, ?MODULE), Msgs = receive_all(UserServer, [Msg], DBType), Len = length(Msgs), MaxOfflineMsgs = get_max_user_messages(AccessMaxOfflineMsgs, UserServer, Host), store_offline_msg(Host, UserServer, Msgs, Len, MaxOfflineMsgs, DBType), {noreply, State}; handle_info(_Info, State) -> ?ERROR_MSG("got unexpected info: ~p", [_Info]), {noreply, State}. terminate(_Reason, State) -> Host = State#state.host, ejabberd_hooks:delete(offline_message_hook, Host, ?MODULE, store_packet, 50), ejabberd_hooks:delete(resend_offline_messages_hook, Host, ?MODULE, pop_offline_messages, 50), ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, Host, ?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(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), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. store_offline_msg(_Host, US, Msgs, Len, MaxOfflineMsgs, mnesia) -> F = fun () -> Count = if MaxOfflineMsgs =/= infinity -> Len + count_mnesia_records(US); true -> 0 end, if Count > MaxOfflineMsgs -> discard_warn_sender(Msgs); true -> if Len >= (?OFFLINE_TABLE_LOCK_THRESHOLD) -> mnesia:write_lock_table(offline_msg); true -> ok end, lists:foreach(fun (M) -> mnesia:write(M) end, Msgs) end end, mnesia:transaction(F); store_offline_msg(Host, {User, _Server}, Msgs, Len, MaxOfflineMsgs, odbc) -> Count = if MaxOfflineMsgs =/= infinity -> Len + count_offline_messages(User, Host); true -> 0 end, if Count > MaxOfflineMsgs -> discard_warn_sender(Msgs); true -> Query = lists:map(fun (M) -> Username = ejabberd_odbc:escape((M#offline_msg.to)#jid.luser), From = M#offline_msg.from, To = M#offline_msg.to, Packet = jlib:replace_from_to(From, To, M#offline_msg.packet), NewPacket = jlib:add_delay_info(Packet, Host, M#offline_msg.timestamp, <<"Offline Storage">>), XML = ejabberd_odbc:escape(xml:element_to_binary(NewPacket)), odbc_queries:add_spool_sql(Username, XML) end, Msgs), odbc_queries:add_spool(Host, Query) end; store_offline_msg(Host, {User, _}, Msgs, Len, MaxOfflineMsgs, riak) -> Count = if MaxOfflineMsgs =/= infinity -> Len + count_offline_messages(User, Host); true -> 0 end, if Count > MaxOfflineMsgs -> discard_warn_sender(Msgs); true -> lists:foreach( fun(#offline_msg{us = US, timestamp = TS} = M) -> ejabberd_riak:put(M, offline_msg_schema(), [{i, TS}, {'2i', [{<<"us">>, US}]}]) end, Msgs) end. get_max_user_messages(AccessRule, {User, Server}, Host) -> case acl:match_rule( Host, AccessRule, jid:make(User, Server, <<"">>)) of Max when is_integer(Max) -> Max; infinity -> infinity; _ -> ?MAX_USER_MESSAGES end. receive_all(US, Msgs, DBType) -> receive #offline_msg{us = US} = Msg -> receive_all(US, [Msg | Msgs], DBType) after 0 -> case DBType of mnesia -> Msgs; odbc -> lists:reverse(Msgs); riak -> Msgs end end. get_sm_features(Acc, _From, _To, <<"">>, _Lang) -> Feats = case Acc of {result, I} -> I; _ -> [] end, {result, Feats ++ [?NS_FEATURE_MSGOFFLINE]}; get_sm_features(_Acc, _From, _To, ?NS_FEATURE_MSGOFFLINE, _Lang) -> %% override all lesser features... {result, []}; get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. need_to_store(LServer, Packet) -> Type = xml: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 -> xml:get_subtag(Packet, <<"body">>) /= false; unless_chat_state -> not jlib:is_standalone_chat_state(Packet); true -> true end end; true -> false end. store_packet(From, To, Packet) -> case need_to_store(To#jid.lserver, Packet) of true -> 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 xml: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) -> #xmlel{name = Name, attrs = Attrs, children = Els} = Packet, case find_x_event(Els) of false -> true; El -> case xml:get_subtag(El, <<"id">>) of false -> case xml:get_subtag(El, <<"offline">>) of false -> true; _ -> ID = case xml:get_tag_attr_s(<<"id">>, Packet) of <<"">> -> #xmlel{name = <<"id">>, attrs = [], children = []}; S -> #xmlel{name = <<"id">>, attrs = [], children = [{xmlcdata, S}]} end, ejabberd_router:route(To, From, #xmlel{name = Name, attrs = Attrs, children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_EVENT}], children = [ID, #xmlel{name = <<"offline">>, attrs = [], children = []}]}]}), true end; _ -> false end end. %% Check if the packet has subelements about XEP-0022 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 ?NS_EVENT -> El; _ -> find_x_event(Els) end. 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 ?NS_EXPIRE -> Val = xml:get_tag_attr_s(<<"seconds">>, El), case catch jlib:binary_to_integer(Val) of {'EXIT', _} -> never; Int when Int > 0 -> {MegaSecs, Secs, MicroSecs} = TimeStamp, S = MegaSecs * 1000000 + Secs + Int, MegaSecs1 = S div 1000000, Secs1 = S rem 1000000, {MegaSecs1, Secs1, MicroSecs}; _ -> never end; _ -> find_x_expire(TimeStamp, Els) end. resend_offline_messages(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), US = {LUser, LServer}, F = fun () -> Rs = mnesia:wread({offline_msg, US}), mnesia:delete({offline_msg, US}), Rs end, case mnesia:transaction(F) of {atomic, Rs} -> lists:foreach(fun (R) -> ejabberd_sm ! {route, R#offline_msg.from, R#offline_msg.to, jlib:add_delay_info(R#offline_msg.packet, LServer, R#offline_msg.timestamp, <<"Offline Storage">>)} end, lists:keysort(#offline_msg.timestamp, Rs)); _ -> ok end. pop_offline_messages(Ls, User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), pop_offline_messages(Ls, LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). pop_offline_messages(Ls, LUser, LServer, mnesia) -> US = {LUser, LServer}, F = fun () -> Rs = mnesia:wread({offline_msg, US}), mnesia:delete({offline_msg, US}), Rs end, case mnesia:transaction(F) of {atomic, Rs} -> TS = p1_time_compat:timestamp(), Ls ++ lists:map(fun (R) -> offline_msg_to_route(LServer, R) end, lists:filter(fun (R) -> case R#offline_msg.expire of never -> true; TimeStamp -> TS < TimeStamp end end, lists:keysort(#offline_msg.timestamp, Rs))); _ -> 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}} -> Ls ++ lists:flatmap(fun ([_, XML]) -> case xml_stream:parse_element(XML) of {error, _Reason} -> []; El -> case offline_msg_to_route(LServer, El) of error -> []; RouteMsg -> [RouteMsg] end end end, Rs); _ -> Ls end; pop_offline_messages(Ls, LUser, LServer, riak) -> case ejabberd_riak:get_by_index(offline_msg, offline_msg_schema(), <<"us">>, {LUser, LServer}) of {ok, Rs} -> try lists:foreach( fun(#offline_msg{timestamp = T}) -> ok = ejabberd_riak:delete(offline_msg, T) end, Rs), TS = p1_time_compat:timestamp(), Ls ++ lists:map( fun (R) -> offline_msg_to_route(LServer, R) end, lists:filter( fun(R) -> case R#offline_msg.expire of never -> true; TimeStamp -> TS < TimeStamp end end, lists:keysort(#offline_msg.timestamp, Rs))) catch _:{badmatch, _} -> Ls end; _ -> Ls end. remove_expired_messages(Server) -> LServer = jid:nameprep(Server), remove_expired_messages(LServer, gen_mod:db_type(LServer, ?MODULE)). remove_expired_messages(_LServer, mnesia) -> TimeStamp = p1_time_compat:timestamp(), F = fun () -> mnesia:write_lock_table(offline_msg), mnesia:foldl(fun (Rec, _Acc) -> case Rec#offline_msg.expire of never -> ok; TS -> if TS < TimeStamp -> mnesia:delete_object(Rec); true -> ok end end end, ok, offline_msg) end, mnesia:transaction(F); remove_expired_messages(_LServer, odbc) -> {atomic, ok}; remove_expired_messages(_LServer, riak) -> {atomic, ok}. remove_old_messages(Days, Server) -> LServer = jid:nameprep(Server), remove_old_messages(Days, LServer, gen_mod:db_type(LServer, ?MODULE)). remove_old_messages(Days, _LServer, mnesia) -> S = p1_time_compat:system_time(seconds) - 60 * 60 * 24 * Days, MegaSecs1 = S div 1000000, Secs1 = S rem 1000000, TimeStamp = {MegaSecs1, Secs1, 0}, F = fun () -> mnesia:write_lock_table(offline_msg), mnesia:foldl(fun (#offline_msg{timestamp = TS} = Rec, _Acc) when TS < TimeStamp -> mnesia:delete_object(Rec); (_Rec, _Acc) -> ok end, ok, offline_msg) end, mnesia:transaction(F); remove_old_messages(Days, LServer, odbc) -> case catch ejabberd_odbc:sql_query( LServer, [<<"DELETE FROM spool" " WHERE created_at < " "DATE_SUB(CURDATE(), INTERVAL ">>, integer_to_list(Days), <<" DAY);">>]) of {updated, N} -> ?INFO_MSG("~p message(s) deleted from offline spool", [N]); _Error -> ?ERROR_MSG("Cannot delete message in offline spool: ~p", [_Error]) end, {atomic, ok}; remove_old_messages(_Days, _LServer, riak) -> {atomic, ok}. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). remove_user(LUser, LServer, mnesia) -> US = {LUser, LServer}, 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); remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete_by_index(offline_msg, <<"us">>, {LUser, LServer})}. jid_to_binary(#jid{user = U, server = S, resource = R, luser = LU, lserver = LS, lresource = LR}) -> #jid{user = iolist_to_binary(U), server = iolist_to_binary(S), resource = iolist_to_binary(R), luser = iolist_to_binary(LU), lserver = iolist_to_binary(LS), lresource = iolist_to_binary(LR)}. update_table() -> Fields = record_info(fields, offline_msg), case mnesia:table_info(offline_msg, attributes) of Fields -> ejabberd_config:convert_table_to_binary( offline_msg, Fields, bag, fun(#offline_msg{us = {U, _}}) -> U end, fun(#offline_msg{us = {U, S}, from = From, to = To, packet = El} = R) -> R#offline_msg{us = {iolist_to_binary(U), iolist_to_binary(S)}, from = jid_to_binary(From), to = jid_to_binary(To), packet = xml:to_xmlel(El)} end); _ -> ?INFO_MSG("Recreating offline_msg table", []), mnesia:transform_table(offline_msg, ignore, Fields) end. %% Helper functions: %% Warn senders that their messages have been discarded: discard_warn_sender(Msgs) -> lists:foreach(fun (#offline_msg{from = From, to = To, packet = Packet}) -> ErrText = <<"Your contact offline message queue is " "full. The message has been discarded.">>, Lang = xml:get_tag_attr_s(<<"xml:lang">>, Packet), Err = jlib:make_error_reply(Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)), ejabberd_router:route(To, From, Err) end, Msgs). webadmin_page(_, Host, #request{us = _US, path = [<<"user">>, U, <<"queue">>], q = Query, lang = Lang} = _Request) -> Res = user_queue(U, Host, Query, Lang), {stop, Res}; webadmin_page(Acc, _, _) -> Acc. get_offline_els(LUser, LServer) -> get_offline_els(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). get_offline_els(LUser, LServer, DBType) when DBType == mnesia; DBType == riak -> Msgs = read_all_msgs(LUser, LServer, DBType), lists:map( fun(Msg) -> {route, From, To, Packet} = offline_msg_to_route(LServer, Msg), 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} -> lists:flatmap( fun([XML]) -> case xml_stream:parse_element(XML) of #xmlel{} = El -> case offline_msg_to_route(LServer, El) of {route, _, _, NewEl} -> [NewEl]; error -> [] end; _ -> [] end end, Rs); _ -> [] end. offline_msg_to_route(LServer, #offline_msg{} = R) -> {route, R#offline_msg.from, R#offline_msg.to, 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)), if (To /= error) and (From /= error) -> {route, From, To, El}; true -> error end. read_all_msgs(LUser, LServer, mnesia) -> US = {LUser, LServer}, lists:keysort(#offline_msg.timestamp, mnesia:dirty_read({offline_msg, US})); read_all_msgs(LUser, LServer, riak) -> case ejabberd_riak:get_by_index( offline_msg, offline_msg_schema(), <<"us">>, {LUser, LServer}) of {ok, Rs} -> lists:keysort(#offline_msg.timestamp, Rs); _Err -> [] 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 xml_stream:parse_element(XML) of {error, _Reason} -> []; El -> [El] end end, Rs); _ -> [] end. format_user_queue(Msgs, DBType) when DBType == mnesia; DBType == riak -> lists:map(fun (#offline_msg{timestamp = TimeStamp, from = From, to = To, packet = #xmlel{name = Name, attrs = Attrs, children = Els}} = Msg) -> ID = jlib:encode_base64((term_to_binary(Msg))), {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:now_to_local_time(TimeStamp), Time = iolist_to_binary(io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w", [Year, Month, Day, Hour, Minute, Second])), 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}, FPacket = ejabberd_web_admin:pretty_print_xml(Packet), ?XE(<<"tr">>, [?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], [?INPUT(<<"checkbox">>, <<"selected">>, ID)]), ?XAC(<<"td">>, [{<<"class">>, <<"valign">>}], Time), ?XAC(<<"td">>, [{<<"class">>, <<"valign">>}], SFrom), ?XAC(<<"td">>, [{<<"class">>, <<"valign">>}], STo), ?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], [?XC(<<"pre">>, FPacket)])]) end, Msgs); format_user_queue(Msgs, odbc) -> lists:map(fun (#xmlel{} = Msg) -> ID = jlib:encode_base64((term_to_binary(Msg))), Packet = Msg, FPacket = ejabberd_web_admin:pretty_print_xml(Packet), ?XE(<<"tr">>, [?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], [?INPUT(<<"checkbox">>, <<"selected">>, ID)]), ?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], [?XC(<<"pre">>, FPacket)])]) end, Msgs). user_queue(User, Server, Query, Lang) -> 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, DBType), MsgsAll = read_all_msgs(LUser, LServer, DBType), Msgs = get_messages_subset(US, Server, MsgsAll, DBType), FMsgs = format_user_queue(Msgs, DBType), [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"~s's Offline Messages Queue">>), [us_to_list(US)])))] ++ case Res of ok -> [?XREST(<<"Submitted">>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?XE(<<"table">>, [?XE(<<"thead">>, [?XE(<<"tr">>, [?X(<<"td">>), ?XCT(<<"td">>, <<"Time">>), ?XCT(<<"td">>, <<"From">>), ?XCT(<<"td">>, <<"To">>), ?XCT(<<"td">>, <<"Packet">>)])]), ?XE(<<"tbody">>, if FMsgs == [] -> [?XE(<<"tr">>, [?XAC(<<"td">>, [{<<"colspan">>, <<"4">>}], <<" ">>)])]; true -> FMsgs end)]), ?BR, ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>)])]. user_queue_parse_query(LUser, LServer, Query, mnesia) -> US = {LUser, LServer}, case lists:keysearch(<<"delete">>, 1, Query) of {value, _} -> Msgs = lists:keysort(#offline_msg.timestamp, mnesia:dirty_read({offline_msg, US})), F = fun () -> lists:foreach(fun (Msg) -> ID = jlib:encode_base64((term_to_binary(Msg))), case lists:member({<<"selected">>, ID}, Query) of true -> mnesia:delete_object(Msg); false -> ok end end, Msgs) end, mnesia:transaction(F), ok; false -> nothing end; user_queue_parse_query(LUser, LServer, Query, riak) -> case lists:keysearch(<<"delete">>, 1, Query) of {value, _} -> Msgs = read_all_msgs(LUser, LServer, riak), lists:foreach( fun (Msg) -> ID = jlib:encode_base64((term_to_binary(Msg))), case lists:member({<<"selected">>, ID}, Query) of true -> ejabberd_riak:delete(offline_msg, Msg#offline_msg.timestamp); false -> ok end end, Msgs), ok; false -> nothing end; user_queue_parse_query(LUser, LServer, Query, odbc) -> Username = ejabberd_odbc:escape(LUser), case lists:keysearch(<<"delete">>, 1, Query) of {value, _} -> Msgs = case catch ejabberd_odbc:sql_query(LServer, [<<"select xml, seq from spool where username='">>, Username, <<"' order by seq;">>]) of {selected, [<<"xml">>, <<"seq">>], Rs} -> lists:flatmap(fun ([XML, Seq]) -> case xml_stream:parse_element(XML) of {error, _Reason} -> []; El -> [{El, Seq}] end end, Rs); _ -> [] end, F = fun () -> lists:foreach(fun ({Msg, Seq}) -> ID = jlib:encode_base64((term_to_binary(Msg))), case lists:member({<<"selected">>, ID}, Query) of true -> SSeq = ejabberd_odbc:escape(Seq), catch ejabberd_odbc:sql_query(LServer, [<<"delete from spool where username='">>, Username, <<"' and seq='">>, SSeq, <<"';">>]); false -> ok end end, Msgs) end, mnesia:transaction(F), ok; false -> nothing end. 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. get_messages_subset(User, Host, MsgsAll, DBType) -> Access = gen_mod:get_module_opt(Host, ?MODULE, access_max_user_messages, fun(A) when is_atom(A) -> A end, max_user_offline_messages), MaxOfflineMsgs = case get_max_user_messages(Access, User, Host) of Number when is_integer(Number) -> Number; _ -> 100 end, Length = length(MsgsAll), get_messages_subset2(MaxOfflineMsgs, Length, MsgsAll, DBType). get_messages_subset2(Max, Length, MsgsAll, _DBType) when Length =< Max * 2 -> MsgsAll; get_messages_subset2(Max, Length, MsgsAll, DBType) when DBType == mnesia; DBType == riak -> FirstN = Max, {MsgsFirstN, Msgs2} = lists:split(FirstN, MsgsAll), MsgsLastN = lists:nthtail(Length - FirstN - FirstN, Msgs2), NoJID = jid:make(<<"...">>, <<"...">>, <<"">>), IntermediateMsg = #offline_msg{timestamp = p1_time_compat:timestamp(), from = NoJID, to = NoJID, packet = #xmlel{name = <<"...">>, attrs = [], children = []}}, MsgsFirstN ++ [IntermediateMsg] ++ MsgsLastN; get_messages_subset2(Max, Length, MsgsAll, odbc) -> FirstN = Max, {MsgsFirstN, Msgs2} = lists:split(FirstN, MsgsAll), MsgsLastN = lists:nthtail(Length - FirstN - FirstN, Msgs2), IntermediateMsg = #xmlel{name = <<"...">>, attrs = [], children = []}, MsgsFirstN ++ [IntermediateMsg] ++ MsgsLastN. webadmin_user(Acc, User, Server, Lang) -> QueueLen = get_queue_length(jid:nodeprep(User), jid:nameprep(Server)), FQueueLen = [?AC(<<"queue/">>, (iolist_to_binary(integer_to_list(QueueLen))))], Acc ++ [?XCT(<<"h3">>, <<"Offline Messages:">>)] ++ FQueueLen ++ [?C(<<" ">>), ?INPUTT(<<"submit">>, <<"removealloffline">>, <<"Remove All Offline Messages">>)]. delete_all_msgs(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), delete_all_msgs(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). delete_all_msgs(LUser, LServer, mnesia) -> US = {LUser, LServer}, F = fun () -> mnesia:write_lock_table(offline_msg), lists:foreach(fun (Msg) -> mnesia:delete_object(Msg) end, mnesia:dirty_read({offline_msg, US})) end, mnesia:transaction(F); delete_all_msgs(LUser, LServer, riak) -> Res = ejabberd_riak:delete_by_index(offline_msg, <<"us">>, {LUser, LServer}), {atomic, Res}; delete_all_msgs(LUser, LServer, odbc) -> Username = ejabberd_odbc:escape(LUser), odbc_queries:del_spool_msg(LServer, Username), {atomic, ok}. webadmin_user_parse_query(_, <<"removealloffline">>, User, Server, _Query) -> case delete_all_msgs(User, Server) of {aborted, Reason} -> ?ERROR_MSG("Failed to remove offline messages: ~p", [Reason]), {stop, error}; {atomic, ok} -> ?INFO_MSG("Removed all offline messages for ~s@~s", [User, Server]), {stop, ok} end; webadmin_user_parse_query(Acc, _Action, _User, _Server, _Query) -> Acc. %% Returns as integer the number of offline messages for a given user count_offline_messages(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), DBType = gen_mod:db_type(LServer, ?MODULE), count_offline_messages(LUser, LServer, DBType). count_offline_messages(LUser, LServer, mnesia) -> US = {LUser, LServer}, F = fun () -> count_mnesia_records(US) end, case catch mnesia:async_dirty(F) of I when is_integer(I) -> I; _ -> 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 end; count_offline_messages(LUser, LServer, riak) -> case ejabberd_riak:count_by_index( offline_msg, <<"us">>, {LUser, LServer}) of {ok, Res} -> Res; _ -> 0 end. %% Return the number of records matching a given match expression. %% This function is intended to be used inside a Mnesia transaction. %% The count has been written to use the fewest possible memory by %% getting the record by small increment and by using continuation. -define(BATCHSIZE, 100). count_mnesia_records(US) -> MatchExpression = #offline_msg{us = US, _ = '_'}, case mnesia:select(offline_msg, [{MatchExpression, [], [[]]}], ?BATCHSIZE, read) of {Result, Cont} -> Count = length(Result), count_records_cont(Cont, Count); '$end_of_table' -> 0 end. count_records_cont(Cont, Count) -> case mnesia:select(Cont) of {Result, Cont} -> NewCount = Count + length(Result), count_records_cont(Cont, NewCount); '$end_of_table' -> Count end. offline_msg_schema() -> {record_info(fields, offline_msg), #offline_msg{}}. export(_Server) -> [{offline_msg, fun(Host, #offline_msg{us = {LUser, LServer}, timestamp = TimeStamp, from = From, to = To, packet = Packet}) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), 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)), [[<<"delete from spool where username='">>, Username, <<"';">>], [<<"insert into spool(username, xml) values ('">>, Username, <<"', '">>, XML, <<"');">>]]; (_Host, _R) -> [] end}]. import(LServer) -> [{<<"select username, xml from spool;">>, fun([LUser, XML]) -> El = #xmlel{} = xml_stream:parse_element(XML), From = #jid{} = jid:from_string( xml: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">>}, {attr, <<"stamp">>}]), TS = case jlib:datetime_string_to_timestamp(Stamp) of {_, _, _} = Now -> Now; undefined -> p1_time_compat:timestamp() end, Expire = find_x_expire(TS, El#xmlel.children), #offline_msg{us = {LUser, LServer}, from = From, to = To, timestamp = TS, expire = Expire} end}]. import(_LServer, mnesia, #offline_msg{} = Msg) -> mnesia:dirty_write(Msg); import(_LServer, riak, #offline_msg{us = US, timestamp = TS} = M) -> ejabberd_riak:put(M, offline_msg_schema(), [{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; (unless_chat_state) -> unless_chat_state end; mod_opt_type(_) -> [access_max_user_messages, db_type, store_empty_body]. ejabberd-16.01/src/node_online.erl0000644000232200023220000001327112645157216017426 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% 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). ejabberd-16.01/src/ejabberd_captcha.erl0000644000232200023220000005042712645157216020362 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% File : ejabberd_captcha.erl %%% Author : Evgeniy Khramtsov %%% Purpose : CAPTCHA processing. %%% Created : 26 Apr 2008 by Evgeniy 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(ejabberd_captcha). -behaviour(ejabberd_config). -protocol({xep, 158, '1.0'}). -behaviour(gen_server). %% API -export([start_link/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -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, opt_type/1]). -include("jlib.hrl"). -include("ejabberd.hrl"). -include("logger.hrl"). -include("ejabberd_http.hrl"). -define(VFIELD(Type, Var, Value), #xmlel{name = <<"field">>, attrs = [{<<"type">>, Type}, {<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], children = [Value]}]}). -define(CAPTCHA_TEXT(Lang), translate:translate(Lang, <<"Enter the text you see">>)). -define(CAPTCHA_LIFETIME, 120000). -define(LIMIT_PERIOD, 60*1000*1000). -type error() :: efbig | enodata | limit | malformed_image | timeout. -record(state, {limits = treap:empty() :: treap:treap()}). -record(captcha, {id :: binary(), pid :: pid(), key :: binary(), tref :: reference(), args :: any()}). start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). -spec create_captcha(binary(), jid(), jid(), binary(), any(), any()) -> {error, error()} | {ok, binary(), [xmlel()]}. create_captcha(SID, From, To, Lang, Limiter, Args) -> case create_image(Limiter) of {ok, Type, Key, Image} -> Id = <<(randoms:get_string())/binary>>, B64Image = jlib:encode_base64((Image)), JID = jid:to_string(From), CID = <<"sha1+", (p1_sha:sha(Image))/binary, "@bob.xmpp.org">>, Data = #xmlel{name = <<"data">>, attrs = [{<<"xmlns">>, ?NS_BOB}, {<<"cid">>, CID}, {<<"max-age">>, <<"0">>}, {<<"type">>, Type}], children = [{xmlcdata, B64Image}]}, Captcha = #xmlel{name = <<"captcha">>, attrs = [{<<"xmlns">>, ?NS_CAPTCHA}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = [?VFIELD(<<"hidden">>, <<"FORM_TYPE">>, {xmlcdata, ?NS_CAPTCHA}), ?VFIELD(<<"hidden">>, <<"from">>, {xmlcdata, jid:to_string(To)}), ?VFIELD(<<"hidden">>, <<"challenge">>, {xmlcdata, Id}), ?VFIELD(<<"hidden">>, <<"sid">>, {xmlcdata, SID}), #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"ocr">>}, {<<"label">>, ?CAPTCHA_TEXT(Lang)}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}, #xmlel{name = <<"media">>, attrs = [{<<"xmlns">>, ?NS_MEDIA}], children = [#xmlel{name = <<"uri">>, attrs = [{<<"type">>, Type}], children = [{xmlcdata, <<"cid:", CID/binary>>}]}]}]}]}]}, BodyString1 = translate:translate(Lang, <<"Your messages to ~s are being blocked. " "To unblock them, visit ~s">>), BodyString = iolist_to_binary(io_lib:format(BodyString1, [JID, get_url(Id)])), Body = #xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, BodyString}]}, OOB = #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_OOB}], children = [#xmlel{name = <<"url">>, attrs = [], children = [{xmlcdata, get_url(Id)}]}]}, Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}), ets:insert(captcha, #captcha{id = Id, pid = self(), key = Key, tref = Tref, args = Args}), {ok, Id, [Body, OOB, Captcha, Data]}; Err -> Err end. -spec create_captcha_x(binary(), jid(), binary(), any(), [xmlel()]) -> {ok, [xmlel()]} | {error, error()}. create_captcha_x(SID, To, Lang, Limiter, HeadEls) -> create_captcha_x(SID, To, Lang, Limiter, HeadEls, []). -spec create_captcha_x(binary(), jid(), binary(), any(), [xmlel()], [xmlel()]) -> {ok, [xmlel()]} | {error, error()}. create_captcha_x(SID, To, Lang, Limiter, HeadEls, TailEls) -> case create_image(Limiter) of {ok, Type, Key, Image} -> Id = <<(randoms:get_string())/binary>>, B64Image = jlib:encode_base64((Image)), CID = <<"sha1+", (p1_sha:sha(Image))/binary, "@bob.xmpp.org">>, Data = #xmlel{name = <<"data">>, attrs = [{<<"xmlns">>, ?NS_BOB}, {<<"cid">>, CID}, {<<"max-age">>, <<"0">>}, {<<"type">>, Type}], children = [{xmlcdata, B64Image}]}, HelpTxt = translate:translate(Lang, <<"If you don't see the CAPTCHA image here, " "visit the web page.">>), Imageurl = get_url(<>), Captcha = #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], children = [?VFIELD(<<"hidden">>, <<"FORM_TYPE">>, {xmlcdata, ?NS_CAPTCHA}) | HeadEls] ++ [#xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"fixed">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, HelpTxt}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"hidden">>}, {<<"var">>, <<"captchahidden">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"workaround-for-psi">>}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-single">>}, {<<"label">>, translate:translate(Lang, <<"CAPTCHA web page">>)}, {<<"var">>, <<"url">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Imageurl}]}]}, ?VFIELD(<<"hidden">>, <<"from">>, {xmlcdata, jid:to_string(To)}), ?VFIELD(<<"hidden">>, <<"challenge">>, {xmlcdata, Id}), ?VFIELD(<<"hidden">>, <<"sid">>, {xmlcdata, SID}), #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"ocr">>}, {<<"label">>, ?CAPTCHA_TEXT(Lang)}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}, #xmlel{name = <<"media">>, attrs = [{<<"xmlns">>, ?NS_MEDIA}], children = [#xmlel{name = <<"uri">>, attrs = [{<<"type">>, Type}], children = [{xmlcdata, <<"cid:", CID/binary>>}]}]}]}] ++ TailEls}, Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}), ets:insert(captcha, #captcha{id = Id, key = Key, tref = Tref}), {ok, [Captcha, Data]}; Err -> Err end. -spec build_captcha_html(binary(), binary()) -> captcha_not_found | {xmlel(), {xmlel(), xmlel(), xmlel(), xmlel()}}. build_captcha_html(Id, Lang) -> case lookup_captcha(Id) of {ok, _} -> ImgEl = #xmlel{name = <<"img">>, attrs = [{<<"src">>, get_url(<>)}], children = []}, TextEl = {xmlcdata, ?CAPTCHA_TEXT(Lang)}, IdEl = #xmlel{name = <<"input">>, attrs = [{<<"type">>, <<"hidden">>}, {<<"name">>, <<"id">>}, {<<"value">>, Id}], children = []}, KeyEl = #xmlel{name = <<"input">>, attrs = [{<<"type">>, <<"text">>}, {<<"name">>, <<"key">>}, {<<"size">>, <<"10">>}], children = []}, FormEl = #xmlel{name = <<"form">>, attrs = [{<<"action">>, get_url(Id)}, {<<"name">>, <<"captcha">>}, {<<"method">>, <<"POST">>}], children = [ImgEl, #xmlel{name = <<"br">>, attrs = [], children = []}, TextEl, #xmlel{name = <<"br">>, attrs = [], children = []}, IdEl, KeyEl, #xmlel{name = <<"br">>, attrs = [], children = []}, #xmlel{name = <<"input">>, attrs = [{<<"type">>, <<"submit">>}, {<<"name">>, <<"enter">>}, {<<"value">>, <<"OK">>}], children = []}]}, {FormEl, {ImgEl, TextEl, IdEl, KeyEl}}; _ -> captcha_not_found end. -spec process_reply(xmlel()) -> ok | {error, bad_match | not_found | malformed}. process_reply(#xmlel{} = El) -> case xml:get_subtag(El, <<"x">>) of false -> {error, malformed}; Xdata -> Fields = jlib:parse_xdata_submit(Xdata), case catch {proplists:get_value(<<"challenge">>, Fields), proplists:get_value(<<"ocr">>, Fields)} of {[Id | _], [OCR | _]} -> case check_captcha(Id, OCR) of captcha_valid -> ok; captcha_non_valid -> {error, bad_match}; captcha_not_found -> {error, not_found} end; _ -> {error, malformed} end end; process_reply(_) -> {error, malformed}. process(_Handlers, #request{method = 'GET', lang = Lang, path = [_, Id]}) -> case build_captcha_html(Id, Lang) of {FormEl, _} when is_tuple(FormEl) -> Form = #xmlel{name = <<"div">>, attrs = [{<<"align">>, <<"center">>}], children = [FormEl]}, ejabberd_web:make_xhtml([Form]); captcha_not_found -> ejabberd_web:error(not_found) end; process(_Handlers, #request{method = 'GET', path = [_, Id, <<"image">>], ip = IP}) -> {Addr, _Port} = IP, case lookup_captcha(Id) of {ok, #captcha{key = Key}} -> case create_image(Addr, Key) of {ok, Type, _, Img} -> {200, [{<<"Content-Type">>, Type}, {<<"Cache-Control">>, <<"no-cache">>}, {<<"Last-Modified">>, list_to_binary(httpd_util:rfc1123_date())}], Img}; {error, limit} -> ejabberd_web:error(not_allowed); _ -> ejabberd_web:error(not_found) end; _ -> ejabberd_web:error(not_found) end; process(_Handlers, #request{method = 'POST', q = Q, lang = Lang, path = [_, Id]}) -> ProvidedKey = proplists:get_value(<<"key">>, Q, none), case check_captcha(Id, ProvidedKey) of captcha_valid -> Form = #xmlel{name = <<"p">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"The CAPTCHA is valid.">>)}]}, ejabberd_web:make_xhtml([Form]); captcha_non_valid -> ejabberd_web:error(not_allowed); captcha_not_found -> ejabberd_web:error(not_found) end; process(_Handlers, _Request) -> ejabberd_web:error(not_found). init([]) -> mnesia:delete_table(captcha), ets:new(captcha, [named_table, public, {keypos, #captcha.id}]), check_captcha_setup(), {ok, #state{}}. handle_call({is_limited, Limiter, RateLimit}, _From, State) -> NowPriority = now_priority(), CleanPriority = NowPriority + (?LIMIT_PERIOD), Limits = clean_treap(State#state.limits, CleanPriority), case treap:lookup(Limiter, Limits) of {ok, _, Rate} when Rate >= RateLimit -> {reply, true, State#state{limits = Limits}}; {ok, Priority, Rate} -> NewLimits = treap:insert(Limiter, Priority, Rate + 1, Limits), {reply, false, State#state{limits = NewLimits}}; _ -> NewLimits = treap:insert(Limiter, NowPriority, 1, Limits), {reply, false, State#state{limits = NewLimits}} end; handle_call(_Request, _From, State) -> {reply, bad_request, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({remove_id, Id}, State) -> ?DEBUG("captcha ~p timed out", [Id]), case ets:lookup(captcha, Id) of [#captcha{args = Args, pid = Pid}] -> if is_pid(Pid) -> Pid ! {captcha_failed, Args}; true -> ok end, ets:delete(captcha, Id); _ -> ok end, {noreply, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. create_image() -> create_image(undefined). create_image(Limiter) -> Key = str:substr(randoms:get_string(), 1, 6), create_image(Limiter, Key). create_image(Limiter, Key) -> case is_limited(Limiter) of true -> {error, limit}; false -> do_create_image(Key) end. do_create_image(Key) -> FileName = get_prog_name(), Cmd = lists:flatten(io_lib:format("~s ~s", [FileName, Key])), case cmd(Cmd) of {ok, <<137, $P, $N, $G, $\r, $\n, 26, $\n, _/binary>> = Img} -> {ok, <<"image/png">>, Key, Img}; {ok, <<255, 216, _/binary>> = Img} -> {ok, <<"image/jpeg">>, Key, Img}; {ok, <<$G, $I, $F, $8, X, $a, _/binary>> = Img} when X == $7; X == $9 -> {ok, <<"image/gif">>, Key, Img}; {error, enodata = Reason} -> ?ERROR_MSG("Failed to process output from \"~s\". " "Maybe ImageMagick's Convert program " "is not installed.", [Cmd]), {error, Reason}; {error, Reason} -> ?ERROR_MSG("Failed to process an output from \"~s\": ~p", [Cmd, Reason]), {error, Reason}; _ -> Reason = malformed_image, ?ERROR_MSG("Failed to process an output from \"~s\": ~p", [Cmd, Reason]), {error, Reason} end. get_prog_name() -> case ejabberd_config:get_option( captcha_cmd, fun(FileName) -> F = iolist_to_binary(FileName), if F /= <<"">> -> F end end) of undefined -> ?DEBUG("The option captcha_cmd is not configured, " "but some module wants to use the CAPTCHA " "feature.", []), false; FileName -> FileName end. get_url(Str) -> CaptchaHost = ejabberd_config:get_option( captcha_host, fun iolist_to_binary/1, <<"">>), case str:tokens(CaptchaHost, <<":">>) of [Host] -> <<"http://", Host/binary, "/captcha/", Str/binary>>; [<<"http", _/binary>> = TransferProt, Host] -> <>; [Host, PortString] -> TransferProt = iolist_to_binary(atom_to_list(get_transfer_protocol(PortString))), <>; [TransferProt, Host, PortString] -> <>; _ -> <<"http://", (?MYNAME)/binary, "/captcha/", Str/binary>> end. get_transfer_protocol(PortString) -> PortNumber = jlib:binary_to_integer(PortString), PortListeners = get_port_listeners(PortNumber), get_captcha_transfer_protocol(PortListeners). get_port_listeners(PortNumber) -> AllListeners = ejabberd_config:get_option(listen, fun(V) -> V end), lists:filter(fun (Listener) when is_list(Listener) -> case proplists:get_value(port, Listener) of PortNumber -> true; _ -> false end; (_) -> false end, AllListeners). get_captcha_transfer_protocol([]) -> throw(<<"The port number mentioned in captcha_host " "is not a ejabberd_http listener with " "'captcha' option. Change the port number " "or specify http:// in that option.">>); get_captcha_transfer_protocol([Listener | Listeners]) when is_list(Listener) -> case proplists:get_value(module, Listener) == ejabberd_http andalso proplists:get_bool(captcha, Listener) of true -> case proplists:get_bool(tls, Listener) of true -> https; false -> http end; false -> get_captcha_transfer_protocol(Listeners) end; get_captcha_transfer_protocol([_ | Listeners]) -> get_captcha_transfer_protocol(Listeners). is_limited(undefined) -> false; is_limited(Limiter) -> case ejabberd_config:get_option( captcha_limit, fun(I) when is_integer(I), I > 0 -> I end) of undefined -> false; Int -> case catch gen_server:call(?MODULE, {is_limited, Limiter, Int}, 5000) of true -> true; false -> false; Err -> ?ERROR_MSG("Call failed: ~p", [Err]), false end end. -define(CMD_TIMEOUT, 5000). -define(MAX_FILE_SIZE, 64 * 1024). cmd(Cmd) -> Port = open_port({spawn, Cmd}, [stream, eof, binary]), TRef = erlang:start_timer(?CMD_TIMEOUT, self(), timeout), recv_data(Port, TRef, <<>>). recv_data(Port, TRef, Buf) -> receive {Port, {data, Bytes}} -> NewBuf = <>, if byte_size(NewBuf) > (?MAX_FILE_SIZE) -> return(Port, TRef, {error, efbig}); true -> recv_data(Port, TRef, NewBuf) end; {Port, {data, _}} -> return(Port, TRef, {error, efbig}); {Port, eof} when Buf /= <<>> -> return(Port, TRef, {ok, Buf}); {Port, eof} -> return(Port, TRef, {error, enodata}); {timeout, TRef, _} -> return(Port, TRef, {error, timeout}) end. return(Port, TRef, Result) -> case erlang:cancel_timer(TRef) of false -> receive {timeout, TRef, _} -> ok after 0 -> ok end; _ -> ok end, catch port_close(Port), Result. is_feature_available() -> case get_prog_name() of Prog when is_binary(Prog) -> true; false -> false end. check_captcha_setup() -> case is_feature_available() of true -> case create_image() of {ok, _, _, _} -> ok; _Err -> ?CRITICAL_MSG("Captcha is enabled in the option captcha_cmd, " "but it can't generate images.", []), throw({error, captcha_cmd_enabled_but_fails}) end; false -> ok end. lookup_captcha(Id) -> case ets:lookup(captcha, Id) of [C] -> {ok, C}; _ -> {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, tref = Tref}] -> ets:delete(captcha, Id), erlang:cancel_timer(Tref), if ValidKey == ProvidedKey -> if is_pid(Pid) -> Pid ! {captcha_succeed, Args}; true -> ok end, captcha_valid; true -> if is_pid(Pid) -> Pid ! {captcha_failed, Args}; true -> ok end, captcha_non_valid end; _ -> captcha_not_found end. clean_treap(Treap, CleanPriority) -> case treap:is_empty(Treap) of true -> Treap; false -> {_Key, Priority, _Value} = treap:get_root(Treap), if Priority > CleanPriority -> clean_treap(treap:delete_root(Treap), CleanPriority); true -> Treap end end. now_priority() -> -p1_time_compat:system_time(micro_seconds). 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]. ejabberd-16.01/src/eldap.erl0000644000232200023220000011506712645157216016230 0ustar debalancedebalance-module(eldap). %%% -------------------------------------------------------------------- %%% Created: 12 Oct 2000 by Tobbe %%% Function: Erlang client LDAP implementation according RFC 2251. %%% The interface is based on RFC 1823, and %%% draft-ietf-asid-ldap-c-api-00.txt %%% %%% Copyright (C) 2000 Torbjorn Tornkvist, tnt@home.se %%% %%% %%% 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. %%% Modified by Sean Hinde 7th Dec 2000 %%% Turned into gen_fsm, made non-blocking, added timers etc to support this. %%% Now has the concept of a name (string() or atom()) per instance which allows %%% multiple users to call by name if so desired. %%% %%% Can be configured with start_link parameters or use a config file to get %%% host to connect to, dn, password, log function etc. %%% Modified by Alexey Shchepin %%% Modified by Evgeniy Khramtsov %%% Implemented queue for bind() requests to prevent pending binds. %%% Implemented extensibleMatch/2 function. %%% Implemented LDAP Extended Operations (currently only Password Modify %%% is supported - RFC 3062). %%% Modified by Christophe Romain %%% Improve error case handling %%% Modified by Mickael Remond %%% Now use ejabberd log mechanism %%% Modified by: %%% Thomas Baden 2008 April 6th %%% Andy Harb 2008 April 28th %%% Anton Podavalov 2009 February 22th %%% Added LDAPS support, modeled off jungerl eldap.erl version. %%% NOTICE: STARTTLS is not supported. %%% -------------------------------------------------------------------- -vc('$Id$ '). %%%---------------------------------------------------------------------- %%% LDAP Client state machine. %%% Possible states are: %%% connecting - actually disconnected, but retrying periodically %%% wait_bind_response - connected and sent bind request %%% active - bound to LDAP Server and ready to handle commands %%% active_bind - sent bind() request and waiting for response %%%---------------------------------------------------------------------- -behaviour(gen_fsm). -include("ejabberd.hrl"). -include("logger.hrl"). %% External exports -export([start_link/1, start_link/6]). -export([baseObject/0, singleLevel/0, wholeSubtree/0, close/1, equalityMatch/2, greaterOrEqual/2, lessOrEqual/2, approxMatch/2, search/2, substrings/2, present/1, extensibleMatch/2, 'and'/1, 'or'/1, 'not'/1, modify/3, mod_add/2, mod_delete/2, mod_replace/2, add/3, delete/2, modify_dn/5, modify_passwd/3, bind/3]). -export([get_status/1]). -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]). -export_type([filter/0]). -include("ELDAPv3.hrl"). -include("eldap.hrl"). -define(LDAP_VERSION, 3). -define(RETRY_TIMEOUT, 500). -define(BIND_TIMEOUT, 10000). -define(CMD_TIMEOUT, 100000). %% Used in gen_fsm sync calls. %% Used as a timeout for gen_tcp:send/2 -define(CALL_TIMEOUT, (?CMD_TIMEOUT) + (?BIND_TIMEOUT) + (?RETRY_TIMEOUT)). -define(SEND_TIMEOUT, 30000). -define(MAX_TRANSACTION_ID, 65535). -define(MIN_TRANSACTION_ID, 0). %% Grace period after "soft" LDAP bind errors: -define(GRACEFUL_RETRY_TIMEOUT, 5000). -define(SUPPORTEDEXTENSION, <<"1.3.6.1.4.1.1466.101.120.7">>). -define(SUPPORTEDEXTENSIONSYNTAX, <<"1.3.6.1.4.1.1466.115.121.1.38">>). -define(STARTTLS, <<"1.3.6.1.4.1.1466.20037">>). -type handle() :: pid() | atom() | binary(). -record(eldap, {version = ?LDAP_VERSION :: non_neg_integer(), hosts = [] :: [binary()], host :: binary(), port = 389 :: inet:port_number(), sockmod = gen_tcp :: ssl | gen_tcp, tls = none :: none | tls, tls_options = [] :: [{cacertfile, string()} | {depth, non_neg_integer()} | {verify, non_neg_integer()}], fd, rootdn = <<"">> :: binary(), passwd = <<"">> :: binary(), id = 0 :: non_neg_integer(), bind_timer = make_ref() :: reference(), dict = dict:new() :: ?TDICT, req_q = queue:new() :: ?TQUEUE}). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link(Name) -> Reg_name = jlib:binary_to_atom(<<"eldap_", Name/binary>>), gen_fsm:start_link({local, Reg_name}, ?MODULE, [], []). -spec start_link(binary(), [binary()], inet:port_number(), binary(), binary(), tlsopts()) -> any(). start_link(Name, Hosts, Port, Rootdn, Passwd, Opts) -> Reg_name = jlib:binary_to_atom(<<"eldap_", Name/binary>>), gen_fsm:start_link({local, Reg_name}, ?MODULE, [Hosts, Port, Rootdn, Passwd, Opts], []). -spec get_status(handle()) -> any(). %%% -------------------------------------------------------------------- %%% Get status of connection. %%% -------------------------------------------------------------------- get_status(Handle) -> Handle1 = get_handle(Handle), gen_fsm:sync_send_all_state_event(Handle1, get_status). %%% -------------------------------------------------------------------- %%% Shutdown connection (and process) asynchronous. %%% -------------------------------------------------------------------- -spec close(handle()) -> any(). close(Handle) -> Handle1 = get_handle(Handle), gen_fsm:send_all_state_event(Handle1, close). %%% -------------------------------------------------------------------- %%% Add an entry. The entry field MUST NOT exist for the AddRequest %%% to succeed. The parent of the entry MUST exist. %%% Example: %%% %%% add(Handle, %%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", %%% [{"objectclass", ["person"]}, %%% {"cn", ["Bill Valentine"]}, %%% {"sn", ["Valentine"]}, %%% {"telephoneNumber", ["545 555 00"]}] %%% ) %%% -------------------------------------------------------------------- add(Handle, Entry, Attributes) -> Handle1 = get_handle(Handle), gen_fsm:sync_send_event(Handle1, {add, Entry, add_attrs(Attributes)}, ?CALL_TIMEOUT). %%% Do sanity check ! add_attrs(Attrs) -> F = fun ({Type, Vals}) -> {'AddRequest_attributes', Type, Vals} end, case catch lists:map(F, Attrs) of {'EXIT', _} -> throw({error, attribute_values}); Else -> Else end. %%% -------------------------------------------------------------------- %%% Delete an entry. The entry consists of the DN of %%% the entry to be deleted. %%% Example: %%% %%% delete(Handle, %%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com" %%% ) %%% -------------------------------------------------------------------- delete(Handle, Entry) -> Handle1 = get_handle(Handle), gen_fsm:sync_send_event(Handle1, {delete, Entry}, ?CALL_TIMEOUT). %%% -------------------------------------------------------------------- %%% Modify an entry. Given an entry a number of modification %%% operations can be performed as one atomic operation. %%% Example: %%% %%% modify(Handle, %%% "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", %%% [replace("telephoneNumber", ["555 555 00"]), %%% add("description", ["LDAP hacker"])] %%% ) %%% -------------------------------------------------------------------- -spec modify(handle(), any(), [add | delete | replace]) -> any(). modify(Handle, Object, Mods) -> Handle1 = get_handle(Handle), gen_fsm:sync_send_event(Handle1, {modify, Object, Mods}, ?CALL_TIMEOUT). %%% %%% Modification operations. %%% Example: %%% replace("telephoneNumber", ["555 555 00"]) %%% mod_add(Type, Values) -> m(add, Type, Values). mod_delete(Type, Values) -> m(delete, Type, Values). %%% -------------------------------------------------------------------- %%% Modify an entry. Given an entry a number of modification %%% operations can be performed as one atomic operation. %%% Example: %%% %%% modify_dn(Handle, %%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", %%% "cn=Ben Emerson", %%% true, %%% "" %%% ) %%% -------------------------------------------------------------------- mod_replace(Type, Values) -> m(replace, Type, Values). m(Operation, Type, Values) -> #'ModifyRequest_modification_SEQOF'{operation = Operation, modification = #'AttributeTypeAndValues'{type = Type, vals = Values}}. modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup) -> Handle1 = get_handle(Handle), gen_fsm:sync_send_event(Handle1, {modify_dn, Entry, NewRDN, bool_p(DelOldRDN), optional(NewSup)}, ?CALL_TIMEOUT). -spec modify_passwd(handle(), binary(), binary()) -> any(). modify_passwd(Handle, DN, Passwd) -> Handle1 = get_handle(Handle), gen_fsm:sync_send_event(Handle1, {modify_passwd, DN, Passwd}, ?CALL_TIMEOUT). %%% -------------------------------------------------------------------- %%% Bind. %%% Example: %%% %%% bind(Handle, %%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", %%% "secret") %%% -------------------------------------------------------------------- -spec bind(handle(), binary(), binary()) -> any(). bind(Handle, RootDN, Passwd) -> Handle1 = get_handle(Handle), gen_fsm:sync_send_event(Handle1, {bind, RootDN, Passwd}, ?CALL_TIMEOUT). %%% Sanity checks ! bool_p(Bool) when Bool == true; Bool == false -> Bool. optional([]) -> asn1_NOVALUE; optional(Value) -> Value. %%% -------------------------------------------------------------------- %%% Synchronous search of the Directory returning a %%% requested set of attributes. %%% %%% Example: %%% %%% Filter = eldap:substrings("sn", [{any,"o"}]), %%% eldap:search(S, [{base, "dc=bluetail, dc=com"}, %%% {filter, Filter}, %%% {attributes,["cn"]}])), %%% %%% Returned result: {ok, #eldap_search_result{}} %%% %%% Example: %%% %%% {ok,{eldap_search_result, %%% [{eldap_entry, %%% "cn=Magnus Froberg, dc=bluetail, dc=com", %%% [{"cn",["Magnus Froberg"]}]}, %%% {eldap_entry, %%% "cn=Torbjorn Tornkvist, dc=bluetail, dc=com", %%% [{"cn",["Torbjorn Tornkvist"]}]}], %%% []}} %%% %%% -------------------------------------------------------------------- -type search_args() :: [{base, binary()} | {filter, filter()} | {scope, scope()} | {attributes, [binary()]} | {types_only, boolean()} | {timeout, non_neg_integer()} | {limit, non_neg_integer()} | {deref_aliases, never | searching | finding | always}]. -spec search(handle(), eldap_search() | search_args()) -> any(). search(Handle, A) when is_record(A, eldap_search) -> call_search(Handle, A); search(Handle, L) when is_list(L) -> case catch parse_search_args(L) of {error, Emsg} -> {error, Emsg}; {'EXIT', Emsg} -> {error, Emsg}; A when is_record(A, eldap_search) -> call_search(Handle, A) end. call_search(Handle, A) -> Handle1 = get_handle(Handle), gen_fsm:sync_send_event(Handle1, {search, A}, ?CALL_TIMEOUT). -spec parse_search_args(search_args()) -> eldap_search(). parse_search_args(Args) -> parse_search_args(Args, #eldap_search{scope = wholeSubtree}). parse_search_args([{base, Base} | T], A) -> parse_search_args(T, A#eldap_search{base = Base}); parse_search_args([{filter, Filter} | T], A) -> parse_search_args(T, A#eldap_search{filter = Filter}); parse_search_args([{scope, Scope} | T], A) -> parse_search_args(T, A#eldap_search{scope = Scope}); parse_search_args([{attributes, Attrs} | T], A) -> parse_search_args(T, A#eldap_search{attributes = Attrs}); parse_search_args([{types_only, TypesOnly} | T], A) -> parse_search_args(T, A#eldap_search{types_only = TypesOnly}); parse_search_args([{timeout, Timeout} | T], A) when is_integer(Timeout) -> parse_search_args(T, A#eldap_search{timeout = Timeout}); parse_search_args([{limit, Limit} | T], A) when is_integer(Limit) -> parse_search_args(T, A#eldap_search{limit = Limit}); parse_search_args([{deref_aliases, never} | T], A) -> parse_search_args(T, A#eldap_search{deref_aliases = neverDerefAliases}); parse_search_args([{deref_aliases, searching} | T], A) -> parse_search_args(T, A#eldap_search{deref_aliases = derefInSearching}); parse_search_args([{deref_aliases, finding} | T], A) -> parse_search_args(T, A#eldap_search{deref_aliases = derefFindingBaseObj}); parse_search_args([{deref_aliases, always} | T], A) -> parse_search_args(T, A#eldap_search{deref_aliases = derefAlways}); parse_search_args([H | _], _) -> throw({error, {unknown_arg, H}}); parse_search_args([], A) -> A. baseObject() -> baseObject. singleLevel() -> singleLevel. %%% %%% The Scope parameter %%% wholeSubtree() -> wholeSubtree. %%% %%% Boolean filter operations %%% -type filter() :: 'and'() | 'or'() | 'not'() | equalityMatch() | greaterOrEqual() | lessOrEqual() | approxMatch() | present() | substrings() | extensibleMatch(). %%% %%% The following Filter parameters consist of an attribute %%% and an attribute value. Example: F("uid","tobbe") %%% -type 'and'() :: {'and', [filter()]}. -spec 'and'([filter()]) -> 'and'(). 'and'(ListOfFilters) when is_list(ListOfFilters) -> {'and', ListOfFilters}. -type 'or'() :: {'or', [filter()]}. -spec 'or'([filter()]) -> 'or'(). 'or'(ListOfFilters) when is_list(ListOfFilters) -> {'or', ListOfFilters}. -type 'not'() :: {'not', filter()}. -spec 'not'(filter()) -> 'not'(). 'not'(Filter) when is_tuple(Filter) -> {'not', Filter}. -type equalityMatch() :: {equalityMatch, 'AttributeValueAssertion'()}. -spec equalityMatch(binary(), binary()) -> equalityMatch(). equalityMatch(Desc, Value) -> {equalityMatch, av_assert(Desc, Value)}. -type greaterOrEqual() :: {greaterOrEqual, 'AttributeValueAssertion'()}. -spec greaterOrEqual(binary(), binary()) -> greaterOrEqual(). greaterOrEqual(Desc, Value) -> {greaterOrEqual, av_assert(Desc, Value)}. -type lessOrEqual() :: {lessOrEqual, 'AttributeValueAssertion'()}. -spec lessOrEqual(binary(), binary()) -> lessOrEqual(). lessOrEqual(Desc, Value) -> {lessOrEqual, av_assert(Desc, Value)}. -type approxMatch() :: {approxMatch, 'AttributeValueAssertion'()}. -spec approxMatch(binary(), binary()) -> approxMatch(). approxMatch(Desc, Value) -> {approxMatch, av_assert(Desc, Value)}. -type 'AttributeValueAssertion'() :: #'AttributeValueAssertion'{attributeDesc :: binary(), assertionValue :: binary()}. -spec av_assert(binary(), binary()) -> 'AttributeValueAssertion'(). av_assert(Desc, Value) -> #'AttributeValueAssertion'{attributeDesc = Desc, assertionValue = Value}. %%% %%% Filter to check for the presence of an attribute %%% -type present() :: {present, binary()}. -spec present(binary()) -> present(). %%% %%% A substring filter seem to be based on a pattern: %%% %%% InitValue*AnyValue*FinalValue %%% %%% where all three parts seem to be optional (at least when %%% talking with an OpenLDAP server). Thus, the arguments %%% to substrings/2 looks like this: %%% %%% Type ::= string( ) %%% SubStr ::= listof( {initial,Value} | {any,Value}, {final,Value}) %%% %%% Example: substrings("sn",[{initial,"To"},{any,"kv"},{final,"st"}]) %%% will match entries containing: 'sn: Tornkvist' %%% present(Attribute) -> {present, Attribute}. %%% %%% extensibleMatch filter. %%% FIXME: Describe the purpose of this filter. %%% %%% Value ::= string( ) %%% Opts ::= listof( {matchingRule, Str} | {type, Str} | {dnAttributes, true} ) %%% %%% Example: extensibleMatch("Fred", [{matchingRule, "1.2.3.4.5"}, {type, "cn"}]). %%% -type substr() :: [{initial | any | final, binary()}]. -type 'SubstringFilter'() :: #'SubstringFilter'{type :: binary(), substrings :: substr()}. -type substrings() :: {substrings, 'SubstringFilter'()}. -spec substrings(binary(), substr()) -> substrings(). substrings(Type, SubStr) -> {substrings, #'SubstringFilter'{type = Type, substrings = SubStr}}. -type match_opts() :: [{matchingRule | type, binary()} | {dnAttributes, boolean()}]. -type 'MatchingRuleAssertion'() :: #'MatchingRuleAssertion'{matchValue :: binary(), type :: asn1_NOVALUE | binary(), matchingRule :: asn1_NOVALUE | binary(), dnAttributes :: asn1_DEFAULT | true}. -type extensibleMatch() :: {extensibleMatch, 'MatchingRuleAssertion'()}. -spec extensibleMatch(binary(), match_opts()) -> extensibleMatch(). extensibleMatch(Value, Opts) -> MRA = #'MatchingRuleAssertion'{matchValue = Value}, {extensibleMatch, extensibleMatch_opts(Opts, MRA)}. extensibleMatch_opts([{matchingRule, Rule} | Opts], MRA) -> extensibleMatch_opts(Opts, MRA#'MatchingRuleAssertion'{matchingRule = Rule}); extensibleMatch_opts([{type, Desc} | Opts], MRA) -> extensibleMatch_opts(Opts, MRA#'MatchingRuleAssertion'{type = Desc}); extensibleMatch_opts([{dnAttributes, true} | Opts], MRA) -> extensibleMatch_opts(Opts, MRA#'MatchingRuleAssertion'{dnAttributes = true}); extensibleMatch_opts([_ | Opts], MRA) -> extensibleMatch_opts(Opts, MRA); extensibleMatch_opts([], MRA) -> MRA. get_handle(Pid) when is_pid(Pid) -> Pid; get_handle(Atom) when is_atom(Atom) -> Atom; get_handle(Name) when is_binary(Name) -> jlib:binary_to_atom(<<"eldap_", Name/binary>>). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, StateName, StateData} | %% {ok, StateName, StateData, Timeout} | %% ignore | %% {stop, StopReason} %% I use the trick of setting a timeout of 0 to pass control into the %% process. %%---------------------------------------------------------------------- init([Hosts, Port, Rootdn, Passwd, Opts]) -> Encrypt = case gen_mod:get_opt(encrypt, Opts, fun(tls) -> tls; (starttls) -> starttls; (none) -> none end) of tls -> tls; _ -> none end, PortTemp = case Port of undefined -> case Encrypt of tls -> ?LDAPS_PORT; _ -> ?LDAP_PORT end; PT -> PT end, CacertOpts = case gen_mod:get_opt( tls_cacertfile, Opts, fun(S) when is_binary(S) -> binary_to_list(S); (undefined) -> undefined end) of undefined -> []; Path -> [{cacertfile, Path}] end, DepthOpts = case gen_mod:get_opt( tls_depth, Opts, fun(I) when is_integer(I), I>=0 -> I; (undefined) -> undefined end) of undefined -> []; Depth -> [{depth, Depth}] end, Verify = gen_mod:get_opt(tls_verify, Opts, fun(hard) -> hard; (soft) -> soft; (false) -> false end, false), TLSOpts = if (Verify == hard orelse Verify == soft) andalso CacertOpts == [] -> ?WARNING_MSG("TLS verification is enabled but no CA " "certfiles configured, so verification " "is disabled.", []), []; Verify == soft -> [{verify, 1}] ++ CacertOpts ++ DepthOpts; Verify == hard -> [{verify, 2}] ++ CacertOpts ++ DepthOpts; true -> [] end, {ok, connecting, #eldap{hosts = Hosts, port = PortTemp, rootdn = Rootdn, passwd = Passwd, tls = Encrypt, tls_options = TLSOpts, id = 0, dict = dict:new(), req_q = queue:new()}, 0}. connecting(timeout, S) -> {ok, NextState, NewS} = connect_bind(S), {next_state, NextState, NewS}. connecting(Event, From, S) -> Q = queue:in({Event, From}, S#eldap.req_q), {next_state, connecting, S#eldap{req_q = Q}}. wait_bind_response(Event, From, S) -> Q = queue:in({Event, From}, S#eldap.req_q), {next_state, wait_bind_response, S#eldap{req_q = Q}}. active_bind(Event, From, S) -> Q = queue:in({Event, From}, S#eldap.req_q), {next_state, active_bind, S#eldap{req_q = Q}}. active(Event, From, S) -> process_command(S, Event, From). %%---------------------------------------------------------------------- %% Func: handle_event/3 %% Called when gen_fsm:send_all_state_event/2 is invoked. %% Returns: {next_state, NextStateName, NextStateData} | %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- handle_event(close, _StateName, S) -> catch (S#eldap.sockmod):close(S#eldap.fd), {stop, normal, S}; handle_event(_Event, StateName, S) -> {next_state, StateName, S}. handle_sync_event(_Event, _From, StateName, S) -> {reply, {StateName, S}, StateName, S}. %% %% 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]), {next_state, connecting, S}; handle_info({Tag, _Socket, Data}, wait_bind_response, S) when Tag == tcp; Tag == ssl -> cancel_timer(S#eldap.bind_timer), case catch recvd_wait_bind_response(Data, S) of bound -> dequeue_commands(S); {fail_bind, Reason} -> report_bind_failure(S#eldap.host, S#eldap.port, Reason), {next_state, connecting, close_and_retry(S, ?GRACEFUL_RETRY_TIMEOUT)}; {'EXIT', Reason} -> report_bind_failure(S#eldap.host, S#eldap.port, Reason), {next_state, connecting, close_and_retry(S)}; {error, Reason} -> report_bind_failure(S#eldap.host, S#eldap.port, Reason), {next_state, connecting, close_and_retry(S)} end; handle_info({Tag, _Socket, Data}, StateName, S) when (StateName == active orelse StateName == active_bind) andalso (Tag == tcp orelse Tag == ssl) -> case catch recvd_packet(Data, S) of {response, Response, RequestType} -> NewS = case Response of {reply, Reply, To, S1} -> gen_fsm:reply(To, Reply), S1; {ok, S1} -> S1 end, if StateName == active_bind andalso RequestType == bindRequest orelse StateName == active -> dequeue_commands(NewS); true -> {next_state, StateName, NewS} end; _ -> {next_state, StateName, S} end; handle_info({Tag, _Socket}, Fsm_state, S) when Tag == tcp_closed; Tag == ssl_closed -> ?WARNING_MSG("LDAP server closed the connection: ~s:~p~nIn " "State: ~p", [S#eldap.host, S#eldap.port, Fsm_state]), {next_state, connecting, close_and_retry(S)}; handle_info({Tag, _Socket, Reason}, Fsm_state, S) when Tag == tcp_error; Tag == ssl_error -> ?DEBUG("eldap received tcp_error: ~p~nIn State: ~p", [Reason, Fsm_state]), {next_state, connecting, close_and_retry(S)}; %% %% Timers %% handle_info({timeout, Timer, {cmd_timeout, Id}}, StateName, S) -> case cmd_timeout(Timer, Id, S) of {reply, To, Reason, NewS} -> gen_fsm:reply(To, Reason), {next_state, StateName, NewS}; {error, _Reason} -> {next_state, StateName, S} end; 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) -> {next_state, connecting, close_and_retry(S)}; %% %% Make sure we don't fill the message queue with rubbish %% handle_info(Info, StateName, S) -> ?DEBUG("eldap. Unexpected Info: ~p~nIn state: " "~p~n when StateData is: ~p", [Info, StateName, S]), {next_state, StateName, S}. %%---------------------------------------------------------------------- %% Func: terminate/3 %% Purpose: Shutdown the fsm %% Returns: any %%---------------------------------------------------------------------- terminate(_Reason, _StateName, _StatData) -> ok. %%---------------------------------------------------------------------- %% Func: code_change/4 %% Purpose: Convert process state when code is changed %% Returns: {ok, NewState, NewStateData} %%---------------------------------------------------------------------- code_change(_OldVsn, StateName, S, _Extra) -> {ok, StateName, S}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- dequeue_commands(S) -> case queue:out(S#eldap.req_q) of {{value, {Event, From}}, Q} -> case process_command(S#eldap{req_q = Q}, Event, From) of {_, active, NewS} -> dequeue_commands(NewS); Res -> Res end; {empty, _} -> {next_state, active, S} end. process_command(S, Event, From) -> case send_command(Event, From, S) of {ok, NewS} -> case Event of {bind, _, _} -> {next_state, active_bind, NewS}; _ -> {next_state, active, NewS} end; {error, _Reason} -> Q = queue:in_r({Event, From}, S#eldap.req_q), NewS = close_and_retry(S#eldap{req_q = Q}), {next_state, connecting, NewS} end. send_command(Command, From, S) -> Id = bump_id(S), {Name, Request} = gen_req(Command), Message = #'LDAPMessage'{messageID = Id, protocolOp = {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 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 end. gen_req({search, A}) -> {searchRequest, #'SearchRequest'{baseObject = A#eldap_search.base, scope = A#eldap_search.scope, derefAliases = A#eldap_search.deref_aliases, sizeLimit = A#eldap_search.limit, timeLimit = A#eldap_search.timeout, typesOnly = A#eldap_search.types_only, filter = A#eldap_search.filter, attributes = A#eldap_search.attributes}}; gen_req({add, Entry, Attrs}) -> {addRequest, #'AddRequest'{entry = Entry, attributes = Attrs}}; gen_req({delete, Entry}) -> {delRequest, Entry}; gen_req({modify, Obj, Mod}) -> {modifyRequest, #'ModifyRequest'{object = Obj, modification = Mod}}; gen_req({modify_dn, Entry, NewRDN, DelOldRDN, NewSup}) -> {modDNRequest, #'ModifyDNRequest'{entry = Entry, newrdn = NewRDN, deleteoldrdn = DelOldRDN, newSuperior = NewSup}}; gen_req({modify_passwd, DN, Passwd}) -> {ok, ReqVal} = 'ELDAPv3':encode('PasswdModifyRequestValue', #'PasswdModifyRequestValue'{userIdentity = DN, newPasswd = Passwd}), {extendedReq, #'ExtendedRequest'{requestName = ?passwdModifyOID, requestValue = iolist_to_binary(ReqVal)}}; gen_req({bind, RootDN, Passwd}) -> {bindRequest, #'BindRequest'{version = ?LDAP_VERSION, name = RootDN, authentication = {simple, Passwd}}}. %%----------------------------------------------------------------------- %% recvd_packet %% Deals with incoming packets in the active state %% Will return one of: %% {ok, NewS} - Don't reply to client yet as this is part of a search %% result and we haven't got all the answers yet. %% {reply, Result, From, NewS} - Reply with result to client From %% {error, Reason} %% {'EXIT', Reason} - Broke %%----------------------------------------------------------------------- recvd_packet(Pkt, S) -> case 'ELDAPv3':decode('LDAPMessage', Pkt) of {ok, Msg} -> Op = Msg#'LDAPMessage'.protocolOp, ?DEBUG("~p", [Op]), Dict = S#eldap.dict, Id = Msg#'LDAPMessage'.messageID, {Timer, From, Name, Result_so_far} = get_op_rec(Id, Dict), Answer = case {Name, Op} of {searchRequest, {searchResEntry, R}} when is_record(R, 'SearchResultEntry') -> New_dict = dict:append(Id, R, Dict), {ok, S#eldap{dict = New_dict}}; {searchRequest, {searchResDone, Result}} -> Reason = Result#'LDAPResult'.resultCode, if Reason == success; Reason == sizeLimitExceeded -> {Res, Ref} = polish(Result_so_far), New_dict = dict:erase(Id, Dict), cancel_timer(Timer), {reply, #eldap_search_result{entries = Res, referrals = Ref}, From, S#eldap{dict = New_dict}}; true -> New_dict = dict:erase(Id, Dict), cancel_timer(Timer), {reply, {error, Reason}, From, S#eldap{dict = New_dict}} end; {searchRequest, {searchResRef, R}} -> New_dict = dict:append(Id, R, Dict), {ok, S#eldap{dict = New_dict}}; {addRequest, {addResponse, Result}} -> New_dict = dict:erase(Id, Dict), cancel_timer(Timer), Reply = check_reply(Result, From), {reply, Reply, From, S#eldap{dict = New_dict}}; {delRequest, {delResponse, Result}} -> New_dict = dict:erase(Id, Dict), cancel_timer(Timer), Reply = check_reply(Result, From), {reply, Reply, From, S#eldap{dict = New_dict}}; {modifyRequest, {modifyResponse, Result}} -> New_dict = dict:erase(Id, Dict), cancel_timer(Timer), Reply = check_reply(Result, From), {reply, Reply, From, S#eldap{dict = New_dict}}; {modDNRequest, {modDNResponse, Result}} -> New_dict = dict:erase(Id, Dict), cancel_timer(Timer), Reply = check_reply(Result, From), {reply, Reply, From, S#eldap{dict = New_dict}}; {bindRequest, {bindResponse, Result}} -> New_dict = dict:erase(Id, Dict), cancel_timer(Timer), Reply = check_bind_reply(Result, From), {reply, Reply, From, S#eldap{dict = New_dict}}; {extendedReq, {extendedResp, Result}} -> New_dict = dict:erase(Id, Dict), cancel_timer(Timer), Reply = check_extended_reply(Result, From), {reply, Reply, From, S#eldap{dict = New_dict}}; {OtherName, OtherResult} -> New_dict = dict:erase(Id, Dict), cancel_timer(Timer), {reply, {error, {invalid_result, OtherName, OtherResult}}, From, S#eldap{dict = New_dict}} end, {response, Answer, Name}; Error -> Error end. check_reply(#'LDAPResult'{resultCode = success}, _From) -> ok; check_reply(#'LDAPResult'{resultCode = Reason}, _From) -> {error, Reason}; check_reply(Other, _From) -> {error, Other}. check_bind_reply(#'BindResponse'{resultCode = success}, _From) -> ok; check_bind_reply(#'BindResponse'{resultCode = Reason}, _From) -> {error, Reason}; check_bind_reply(Other, _From) -> {error, Other}. %% TODO: process reply depending on requestName: %% this requires BER-decoding of #'ExtendedResponse'.response check_extended_reply(#'ExtendedResponse'{resultCode = success}, _From) -> ok; check_extended_reply(#'ExtendedResponse'{resultCode = Reason}, _From) -> {error, Reason}; check_extended_reply(Other, _From) -> {error, Other}. get_op_rec(Id, Dict) -> case dict:find(Id, Dict) of {ok, [{Timer, _Command, From, Name} | Res]} -> {Timer, From, Name, Res}; error -> throw({error, unkown_id}) end. %%----------------------------------------------------------------------- %% recvd_wait_bind_response packet %% Deals with incoming packets in the wait_bind_response state %% Will return one of: %% bound - Success - move to active state %% {fail_bind, Reason} - Failed %% {error, Reason} %% {'EXIT', Reason} - Broken packet %%----------------------------------------------------------------------- recvd_wait_bind_response(Pkt, S) -> case 'ELDAPv3':decode('LDAPMessage', Pkt) of {ok, Msg} -> ?DEBUG("~p", [Msg]), check_id(S#eldap.id, Msg#'LDAPMessage'.messageID), case Msg#'LDAPMessage'.protocolOp of {bindResponse, Result} -> case Result#'BindResponse'.resultCode of success -> bound; Error -> {fail_bind, Error} end end; Else -> {fail_bind, Else} end. check_id(Id, Id) -> ok; check_id(_, _) -> throw({error, wrong_bind_id}). %%----------------------------------------------------------------------- %% General Helpers %%----------------------------------------------------------------------- cancel_timer(Timer) -> erlang:cancel_timer(Timer), receive {timeout, Timer, _} -> ok after 0 -> ok end. close_and_retry(S, Timeout) -> catch (S#eldap.sockmod):close(S#eldap.fd), Queue = dict:fold(fun (_Id, [{Timer, Command, From, _Name} | _], Q) -> cancel_timer(Timer), queue:in_r({Command, From}, Q); (_, _, Q) -> Q end, S#eldap.req_q, S#eldap.dict), erlang:send_after(Timeout, self(), {timeout, retry_connect}), S#eldap{fd = undefined, req_q = Queue, dict = dict:new()}. close_and_retry(S) -> close_and_retry(S, ?RETRY_TIMEOUT). report_bind_failure(Host, Port, Reason) -> ?WARNING_MSG("LDAP bind failed on ~s:~p~nReason: ~p", [Host, Port, Reason]). %%----------------------------------------------------------------------- %% Sort out timed out commands %%----------------------------------------------------------------------- cmd_timeout(Timer, Id, S) -> Dict = S#eldap.dict, case dict:find(Id, Dict) of {ok, [{Timer, _Command, From, Name} | Res]} -> case Name of searchRequest -> {Res1, Ref1} = polish(Res), New_dict = dict:erase(Id, Dict), {reply, From, {timeout, #eldap_search_result{entries = Res1, referrals = Ref1}}, S#eldap{dict = New_dict}}; _ -> New_dict = dict:erase(Id, Dict), {reply, From, {error, timeout}, S#eldap{dict = New_dict}} end; error -> {error, timed_out_cmd_not_in_dict} end. %%----------------------------------------------------------------------- %% Common stuff for results %%----------------------------------------------------------------------- %%% %%% Polish the returned search result %%% polish(Entries) -> polish(Entries, [], []). polish([H | T], Res, Ref) when is_record(H, 'SearchResultEntry') -> ObjectName = H#'SearchResultEntry'.objectName, F = fun ({_, A, V}) -> {A, V} end, Attrs = lists:map(F, H#'SearchResultEntry'.attributes), polish(T, [#eldap_entry{object_name = ObjectName, attributes = Attrs} | Res], Ref); polish([H | T], Res, Ref) -> % No special treatment of referrals at the moment. polish(T, Res, [H | Ref]); polish([], Res, Ref) -> {Res, Ref}. %%----------------------------------------------------------------------- %% Connect to next server in list and attempt to bind to it. %%----------------------------------------------------------------------- connect_bind(S) -> Host = next_host(S#eldap.host, S#eldap.hosts), ?INFO_MSG("LDAP connection on ~s:~p", [Host, S#eldap.port]), Opts = if S#eldap.tls == tls -> [{packet, asn1}, {active, true}, {keepalive, true}, binary | S#eldap.tls_options]; true -> [{packet, asn1}, {active, true}, {keepalive, true}, {send_timeout, ?SEND_TIMEOUT}, binary] end, HostS = binary_to_list(Host), SocketData = case S#eldap.tls of tls -> SockMod = ssl, ssl:connect(HostS, S#eldap.port, Opts); %% starttls -> %% TODO: Implement STARTTLS; _ -> SockMod = gen_tcp, gen_tcp:connect(HostS, S#eldap.port, Opts) end, case SocketData of {ok, Socket} -> case bind_request(Socket, S#eldap{sockmod = SockMod}) of {ok, NewS} -> Timer = erlang:start_timer(?BIND_TIMEOUT, self(), {timeout, bind_timeout}), {ok, wait_bind_response, NewS#eldap{fd = Socket, sockmod = SockMod, host = Host, bind_timer = Timer}}; {error, Reason} -> report_bind_failure(Host, S#eldap.port, Reason), NewS = close_and_retry(S), {ok, connecting, NewS#eldap{host = Host}} end; {error, Reason} -> ?ERROR_MSG("LDAP connection failed:~n** Server: " "~s:~p~n** Reason: ~p~n** Socket options: ~p", [Host, S#eldap.port, Reason, Opts]), NewS = close_and_retry(S), {ok, connecting, NewS#eldap{host = Host}} end. bind_request(Socket, S) -> Id = bump_id(S), Req = #'BindRequest'{version = S#eldap.version, name = S#eldap.rootdn, authentication = {simple, S#eldap.passwd}}, 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), case (S#eldap.sockmod):send(Socket, Bytes) of ok -> {ok, S#eldap{id = Id}}; Error -> Error end. %% Given last tried Server, find next one to try next_host(undefined, [H | _]) -> H; % First time, take first next_host(Host, Hosts) -> % Find next in turn next_host(Host, Hosts, Hosts). next_host(Host, [Host], Hosts) -> hd(Hosts); % Wrap back to first next_host(Host, [Host | Tail], _Hosts) -> hd(Tail); % Take next next_host(_Host, [], Hosts) -> hd(Hosts); % Never connected before? (shouldn't happen) next_host(Host, [_ | T], Hosts) -> next_host(Host, T, Hosts). bump_id(#eldap{id = Id}) when Id > (?MAX_TRANSACTION_ID) -> ?MIN_TRANSACTION_ID; bump_id(#eldap{id = Id}) -> Id + 1. ejabberd-16.01/src/mod_sip.erl0000644000232200023220000002543412645157216016573 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author 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 %%% 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_sip). -protocol({rfc, 3261}). -behaviour(gen_mod). -behaviour(esip). %% API -export([start/2, stop/1, make_response/2, is_my_host/1, at_my_host/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"). -include_lib("esip/include/esip.hrl"). %%%=================================================================== %%% API %%%=================================================================== start(_Host, _Opts) -> ejabberd:start_app(esip), esip:set_config_value(max_server_transactions, 10000), esip:set_config_value(max_client_transactions, 10000), esip:set_config_value(software, <<"ejabberd ", (?VERSION)/binary>>), esip:set_config_value(module, ?MODULE), Spec = {mod_sip_registrar, {mod_sip_registrar, start_link, []}, transient, 2000, worker, [mod_sip_registrar]}, TmpSupSpec = {mod_sip_proxy_sup, {ejabberd_tmp_sup, start_link, [mod_sip_proxy_sup, mod_sip_proxy]}, permanent, infinity, supervisor, [ejabberd_tmp_sup]}, supervisor:start_child(ejabberd_sup, Spec), supervisor:start_child(ejabberd_sup, TmpSupSpec), ok. stop(_Host) -> ok. data_in(Data, #sip_socket{type = Transport, addr = {MyIP, MyPort}, peer = {PeerIP, PeerPort}}) -> ?DEBUG( "SIP [~p/in] ~s:~p -> ~s:~p:~n~s", [Transport, inet_parse:ntoa(PeerIP), PeerPort, inet_parse:ntoa(MyIP), MyPort, Data]). data_out(Data, #sip_socket{type = Transport, addr = {MyIP, MyPort}, peer = {PeerIP, PeerPort}}) -> ?DEBUG( "SIP [~p/out] ~s:~p -> ~s:~p:~n~s", [Transport, inet_parse:ntoa(MyIP), MyPort, inet_parse:ntoa(PeerIP), PeerPort, Data]). message_in(#sip{type = request, method = M} = Req, SIPSock) when M /= <<"ACK">>, M /= <<"CANCEL">> -> case action(Req, SIPSock) of {relay, _LServer} -> ok; Action -> request(Req, SIPSock, undefined, Action) end; message_in(ping, SIPSock) -> mod_sip_registrar:ping(SIPSock); message_in(_, _) -> ok. message_out(_, _) -> ok. response(_Resp, _SIPSock) -> ok. request(#sip{method = <<"ACK">>} = Req, SIPSock) -> case action(Req, SIPSock) of {relay, LServer} -> mod_sip_proxy:route(Req, LServer, [{authenticated, true}]); {proxy_auth, LServer} -> mod_sip_proxy:route(Req, LServer, [{authenticated, false}]); _ -> ok end; request(_Req, _SIPSock) -> ok. request(Req, SIPSock, TrID) -> request(Req, SIPSock, TrID, action(Req, SIPSock)). request(Req, SIPSock, TrID, Action) -> case Action of to_me -> process(Req, SIPSock); register -> mod_sip_registrar:request(Req, SIPSock); loop -> make_response(Req, #sip{status = 483, type = response}); {unsupported, Require} -> make_response(Req, #sip{status = 420, type = response, hdrs = [{'unsupported', Require}]}); {relay, LServer} -> case mod_sip_proxy:start(LServer, []) of {ok, Pid} -> mod_sip_proxy:route(Req, SIPSock, TrID, Pid), {mod_sip_proxy, route, [Pid]}; Err -> ?INFO_MSG("failed to proxy request ~p: ~p", [Req, Err]), Err end; {proxy_auth, LServer} -> make_response( Req, #sip{status = 407, type = response, hdrs = [{'proxy-authenticate', make_auth_hdr(LServer)}]}); {auth, LServer} -> make_response( Req, #sip{status = 401, type = response, hdrs = [{'www-authenticate', make_auth_hdr(LServer)}]}); deny -> make_response(Req, #sip{status = 403, type = response}); not_found -> make_response(Req, #sip{status = 480, type = response}) end. locate(_SIPMsg) -> ok. find(#uri{user = User, host = Host}) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Host), if LUser == <<"">> -> to_me; true -> case mod_sip_registrar:find_sockets(LUser, LServer) of [] -> not_found; [_|_] -> {relay, LServer} end end. %%%=================================================================== %%% Internal functions %%%=================================================================== action(#sip{method = <<"REGISTER">>, type = request, hdrs = Hdrs, uri = #uri{user = <<"">>} = URI} = Req, SIPSock) -> case at_my_host(URI) of true -> Require = esip:get_hdrs('require', Hdrs) -- supported(), case Require of [_|_] -> {unsupported, Require}; _ -> {_, ToURI, _} = esip:get_hdr('to', Hdrs), case at_my_host(ToURI) of true -> case check_auth(Req, 'authorization', SIPSock) of true -> register; false -> {auth, jid:nameprep(ToURI#uri.host)} end; false -> deny end end; false -> deny end; action(#sip{method = Method, hdrs = Hdrs, type = request} = Req, SIPSock) -> case esip:get_hdr('max-forwards', Hdrs) of 0 when Method == <<"OPTIONS">> -> to_me; 0 -> loop; _ -> Require = esip:get_hdrs('proxy-require', Hdrs) -- supported(), case Require of [_|_] -> {unsupported, Require}; _ -> {_, ToURI, _} = esip:get_hdr('to', Hdrs), {_, FromURI, _} = esip:get_hdr('from', Hdrs), case at_my_host(FromURI) of true -> case check_auth(Req, 'proxy-authorization', SIPSock) of true -> case at_my_host(ToURI) of true -> find(ToURI); false -> LServer = jid:nameprep(FromURI#uri.host), {relay, LServer} end; false -> {proxy_auth, FromURI#uri.host} end; false -> case at_my_host(ToURI) of true -> find(ToURI); false -> deny end end end end. check_auth(#sip{method = <<"CANCEL">>}, _, _SIPSock) -> true; check_auth(#sip{method = Method, hdrs = Hdrs, body = Body}, AuthHdr, _SIPSock) -> Issuer = case AuthHdr of 'authorization' -> to; 'proxy-authorization' -> from end, {_, #uri{user = User, host = Host}, _} = esip:get_hdr(Issuer, Hdrs), LUser = jid:nodeprep(User), LServer = jid:nameprep(Host), case lists:filter( fun({_, Params}) -> Username = esip:get_param(<<"username">>, Params), Realm = esip:get_param(<<"realm">>, Params), (LUser == esip:unquote(Username)) and (LServer == esip:unquote(Realm)) end, esip:get_hdrs(AuthHdr, Hdrs)) of [Auth|_] -> case ejabberd_auth:get_password_s(LUser, LServer) of <<"">> -> false; 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 end. allow() -> [<<"OPTIONS">>, <<"REGISTER">>]. supported() -> [<<"path">>, <<"outbound">>]. process(#sip{method = <<"OPTIONS">>} = Req, _) -> make_response(Req, #sip{type = response, status = 200, hdrs = [{'allow', allow()}, {'supported', supported()}]}); process(#sip{method = <<"REGISTER">>} = Req, _) -> make_response(Req, #sip{type = response, status = 400}); process(Req, _) -> make_response(Req, #sip{type = response, status = 405, hdrs = [{'allow', allow()}]}). make_auth_hdr(LServer) -> {<<"Digest">>, [{<<"realm">>, esip:quote(LServer)}, {<<"qop">>, esip:quote(<<"auth">>)}, {<<"nonce">>, esip:quote(esip:make_hexstr(20))}]}. make_response(Req, Resp) -> esip:make_response(Req, Resp, esip:make_tag()). at_my_host(#uri{host = Host}) -> is_my_host(jid:nameprep(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]. ejabberd-16.01/src/mod_register_web.erl0000644000232200023220000004723612645157216020465 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% File : mod_register_web.erl %%% Author : Badlop %%% Purpose : Web page to register account and related tasks %%% Created : 4 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. %%% %%%---------------------------------------------------------------------- %%% IDEAS: %%% %%% * Implement those options, already present in mod_register: %%% + access %%% + captcha_protected %%% + password_strength %%% + welcome_message %%% + registration_timeout %%% %%% * Improve this module to allow each virtual host to have different %%% options. See http://support.process-one.net/browse/EJAB-561 %%% %%% * Check that all the text is translatable. %%% %%% * Add option to use a custom CSS file, or custom CSS lines. %%% %%% * Don't hardcode the "register" path in URL. %%% %%% * Allow private email during register, and store in custom table. %%% * Optionally require private email to register. %%% * Optionally require email confirmation to register. %%% * Allow to set a private email address anytime. %%% * Allow to recover password using private email to confirm (mod_passrecover) %%% * Optionally require invitation %%% * Optionally register request is forwarded to admin, no account created. -module(mod_register_web). -author('badlop@process-one.net'). -behaviour(gen_mod). -export([start/2, stop/1, process/2, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_http.hrl"). -include("ejabberd_web_admin.hrl"). %%%---------------------------------------------------------------------- %%% gen_mod callbacks %%%---------------------------------------------------------------------- start(_Host, _Opts) -> %% case gen_mod:get_opt(docroot, Opts, fun(A) -> A end, undefined) of ok. stop(_Host) -> ok. %%%---------------------------------------------------------------------- %%% HTTP handlers %%%---------------------------------------------------------------------- process([], #request{method = 'GET', lang = Lang}) -> index_page(Lang); process([<<"register.css">>], #request{method = 'GET'}) -> serve_css(); process([<<"new">>], #request{method = 'GET', lang = Lang, host = Host, ip = IP}) -> {Addr, _Port} = IP, form_new_get(Host, Lang, Addr); process([<<"delete">>], #request{method = 'GET', lang = Lang, host = Host}) -> form_del_get(Host, Lang); process([<<"change_password">>], #request{method = 'GET', lang = Lang, host = Host}) -> form_changepass_get(Host, Lang); process([<<"new">>], #request{method = 'POST', q = Q, ip = {Ip, _Port}, lang = Lang, host = _HTTPHost}) -> case form_new_post(Q) of {success, ok, {Username, Host, _Password}} -> Jid = jid:make(Username, Host, <<"">>), mod_register:send_registration_notifications(?MODULE, Jid, Ip), Text = (?T(<<"Your Jabber account was successfully " "created.">>)), {200, [], Text}; Error -> ErrorText = list_to_binary([?T(<<"There was an error creating the account: ">>), ?T(get_error_text(Error))]), {404, [], ErrorText} end; process([<<"delete">>], #request{method = 'POST', q = Q, lang = Lang, host = Host}) -> case form_del_post(Q, Host) of {atomic, ok} -> Text = (?T(<<"Your Jabber account was successfully " "deleted.">>)), {200, [], Text}; Error -> ErrorText = list_to_binary([?T(<<"There was an error deleting the account: ">>), ?T(get_error_text(Error))]), {404, [], ErrorText} end; %% TODO: Currently only the first vhost is usable. The web request record %% 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 {atomic, ok} -> Text = (?T(<<"The password of your Jabber account " "was successfully changed.">>)), {200, [], Text}; Error -> ErrorText = list_to_binary([?T(<<"There was an error changing the password: ">>), ?T(get_error_text(Error))]), {404, [], ErrorText} end; process(_Path, _Request) -> {404, [], "Not Found"}. %%%---------------------------------------------------------------------- %%% CSS %%%---------------------------------------------------------------------- serve_css() -> {200, [{<<"Content-Type">>, <<"text/css">>}, last_modified(), cache_control_public()], css()}. last_modified() -> {<<"Last-Modified">>, <<"Mon, 25 Feb 2008 13:23:30 GMT">>}. cache_control_public() -> {<<"Cache-Control">>, <<"public">>}. css() -> <<"html,body {\nbackground: white;\nmargin: " "0;\npadding: 0;\nheight: 100%;\n}">>. %%%---------------------------------------------------------------------- %%% Index page %%%---------------------------------------------------------------------- index_page(Lang) -> HeadEls = [?XCT(<<"title">>, <<"Jabber Account Registration">>), ?XA(<<"link">>, [{<<"href">>, <<"/register/register.css">>}, {<<"type">>, <<"text/css">>}, {<<"rel">>, <<"stylesheet">>}])], Els = [?XACT(<<"h1">>, [{<<"class">>, <<"title">>}, {<<"style">>, <<"text-align:center;">>}], <<"Jabber Account Registration">>), ?XE(<<"ul">>, [?XE(<<"li">>, [?ACT(<<"new">>, <<"Register a Jabber account">>)]), ?XE(<<"li">>, [?ACT(<<"change_password">>, <<"Change Password">>)]), ?XE(<<"li">>, [?ACT(<<"delete">>, <<"Unregister a Jabber account">>)])])], {200, [{<<"Server">>, <<"ejabberd">>}, {<<"Content-Type">>, <<"text/html">>}], ejabberd_web:make_xhtml(HeadEls, Els)}. %%%---------------------------------------------------------------------- %%% Formulary new account GET %%%---------------------------------------------------------------------- form_new_get(Host, Lang, IP) -> CaptchaEls = build_captcha_li_list(Lang, IP), HeadEls = [?XCT(<<"title">>, <<"Register a Jabber account">>), ?XA(<<"link">>, [{<<"href">>, <<"/register/register.css">>}, {<<"type">>, <<"text/css">>}, {<<"rel">>, <<"stylesheet">>}])], Els = [?XACT(<<"h1">>, [{<<"class">>, <<"title">>}, {<<"style">>, <<"text-align:center;">>}], <<"Register a Jabber account">>), ?XCT(<<"p">>, <<"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.">>), ?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?XE(<<"ol">>, ([?XE(<<"li">>, [?CT(<<"Username:">>), ?C(<<" ">>), ?INPUTS(<<"text">>, <<"username">>, <<"">>, <<"20">>), ?BR, ?XE(<<"ul">>, [?XCT(<<"li">>, <<"This is case insensitive: macbeth is " "the same that MacBeth and Macbeth.">>), ?XC(<<"li">>, <<(?T(<<"Characters not allowed:">>))/binary, " \" & ' / : < > @ ">>)])]), ?XE(<<"li">>, [?CT(<<"Server:">>), ?C(<<" ">>), ?INPUTS(<<"text">>, <<"host">>, Host, <<"20">>)]), ?XE(<<"li">>, [?CT(<<"Password:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"password">>, <<"">>, <<"20">>), ?BR, ?XE(<<"ul">>, [?XCT(<<"li">>, <<"Don't tell your password to anybody, " "not even the administrators of the Jabber " "server.">>), ?XCT(<<"li">>, <<"You can later change your password using " "a Jabber client.">>), ?XCT(<<"li">>, <<"Some Jabber clients can store your password " "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 " "Jabber there isn't an automated way " "to recover your password if you forget " "it.">>)])]), ?XE(<<"li">>, [?CT(<<"Password Verification:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"password2">>, <<"">>, <<"20">>)])] ++ CaptchaEls ++ [?XE(<<"li">>, [?INPUTT(<<"submit">>, <<"register">>, <<"Register">>)])]))])], {200, [{<<"Server">>, <<"ejabberd">>}, {<<"Content-Type">>, <<"text/html">>}], ejabberd_web:make_xhtml(HeadEls, Els)}. %% Copied from mod_register.erl %% Function copied from ejabberd_logger_h.erl and customized %%%---------------------------------------------------------------------- %%% Formulary new POST %%%---------------------------------------------------------------------- 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] -> {error, passwords_not_identical}; [_Username, _Password, _Password2, Id, Key] -> ejabberd_captcha:check_captcha(Id, Key), {error, passwords_not_identical}; _ -> {error, wrong_parameters} end. get_register_parameters(Q) -> lists:map(fun (Key) -> case lists:keysearch(Key, 1, Q) of {value, {_Key, Value}} -> Value; false -> false end end, [<<"username">>, <<"host">>, <<"password">>, <<"password2">>, <<"id">>, <<"key">>]). form_new_post(Username, Host, Password, {false, false}) -> register_account(Username, Host, Password); form_new_post(Username, Host, Password, {Id, Key}) -> case ejabberd_captcha:check_captcha(Id, Key) of captcha_valid -> register_account(Username, Host, Password); captcha_non_valid -> {error, captcha_non_valid}; captcha_not_found -> {error, captcha_non_valid} end. %%%---------------------------------------------------------------------- %%% Formulary Captcha support for new GET/POST %%%---------------------------------------------------------------------- build_captcha_li_list(Lang, IP) -> case ejabberd_captcha:is_feature_available() of true -> build_captcha_li_list2(Lang, IP); false -> [] end. build_captcha_li_list2(Lang, IP) -> SID = <<"">>, From = #jid{user = <<"">>, server = <<"test">>, resource = <<"">>}, To = #jid{user = <<"">>, server = <<"test">>, resource = <<"">>}, Args = [], case ejabberd_captcha:create_captcha(SID, From, To, Lang, IP, Args) of {ok, Id, _} -> {_, {CImg, CText, CId, CKey}} = ejabberd_captcha:build_captcha_html(Id, Lang), [?XE(<<"li">>, [CText, ?C(<<" ">>), CId, CKey, ?BR, CImg])]; _ -> [] end. %%%---------------------------------------------------------------------- %%% Formulary change password GET %%%---------------------------------------------------------------------- form_changepass_get(Host, Lang) -> HeadEls = [?XCT(<<"title">>, <<"Change Password">>), ?XA(<<"link">>, [{<<"href">>, <<"/register/register.css">>}, {<<"type">>, <<"text/css">>}, {<<"rel">>, <<"stylesheet">>}])], Els = [?XACT(<<"h1">>, [{<<"class">>, <<"title">>}, {<<"style">>, <<"text-align:center;">>}], <<"Change Password">>), ?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?XE(<<"ol">>, [?XE(<<"li">>, [?CT(<<"Username:">>), ?C(<<" ">>), ?INPUTS(<<"text">>, <<"username">>, <<"">>, <<"20">>)]), ?XE(<<"li">>, [?CT(<<"Server:">>), ?C(<<" ">>), ?C(Host)]), ?XE(<<"li">>, [?CT(<<"Old Password:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"passwordold">>, <<"">>, <<"20">>)]), ?XE(<<"li">>, [?CT(<<"New Password:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"password">>, <<"">>, <<"20">>)]), ?XE(<<"li">>, [?CT(<<"Password Verification:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"password2">>, <<"">>, <<"20">>)]), ?XE(<<"li">>, [?INPUTT(<<"submit">>, <<"changepass">>, <<"Change Password">>)])])])], {200, [{<<"Server">>, <<"ejabberd">>}, {<<"Content-Type">>, <<"text/html">>}], ejabberd_web:make_xhtml(HeadEls, Els)}. %%%---------------------------------------------------------------------- %%% Formulary change password POST %%%---------------------------------------------------------------------- form_changepass_post(Q, Host) -> case catch get_changepass_parameters(Q) of [Username, PasswordOld, Password, Password] -> try_change_password(Username, Host, PasswordOld, Password); [_Username, _PasswordOld, _Password, _Password2] -> {error, passwords_not_identical}; _ -> {error, wrong_parameters} end. get_changepass_parameters(Q) -> %% @spec(Username,Host,PasswordOld,Password) -> {atomic, ok} | %% {error, account_doesnt_exist} | %% {error, password_not_changed} | %% {error, password_incorrect} lists:map(fun (Key) -> {value, {_Key, Value}} = lists:keysearch(Key, 1, Q), Value end, [<<"username">>, <<"passwordold">>, <<"password">>, <<"password2">>]). try_change_password(Username, Host, PasswordOld, Password) -> try change_password(Username, Host, PasswordOld, Password) of {atomic, ok} -> {atomic, ok} catch error:{badmatch, Error} -> {error, Error} end. change_password(Username, Host, PasswordOld, Password) -> account_exists = check_account_exists(Username, Host), password_correct = check_password(Username, Host, PasswordOld), ok = ejabberd_auth:set_password(Username, Host, Password), case check_password(Username, Host, Password) of password_correct -> {atomic, ok}; password_incorrect -> {error, password_not_changed} end. check_account_exists(Username, Host) -> case ejabberd_auth:is_user_exists(Username, Host) of true -> account_exists; false -> account_doesnt_exist end. check_password(Username, Host, Password) -> case ejabberd_auth:check_password(Username, Host, Password) of true -> password_correct; false -> password_incorrect end. %%%---------------------------------------------------------------------- %%% Formulary delete account GET %%%---------------------------------------------------------------------- form_del_get(Host, Lang) -> HeadEls = [?XCT(<<"title">>, <<"Unregister a Jabber account">>), ?XA(<<"link">>, [{<<"href">>, <<"/register/register.css">>}, {<<"type">>, <<"text/css">>}, {<<"rel">>, <<"stylesheet">>}])], Els = [?XACT(<<"h1">>, [{<<"class">>, <<"title">>}, {<<"style">>, <<"text-align:center;">>}], <<"Unregister a Jabber account">>), ?XCT(<<"p">>, <<"This page allows to unregister a Jabber " "account in this Jabber server.">>), ?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?XE(<<"ol">>, [?XE(<<"li">>, [?CT(<<"Username:">>), ?C(<<" ">>), ?INPUTS(<<"text">>, <<"username">>, <<"">>, <<"20">>)]), ?XE(<<"li">>, [?CT(<<"Server:">>), ?C(<<" ">>), ?C(Host)]), ?XE(<<"li">>, [?CT(<<"Password:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"password">>, <<"">>, <<"20">>)]), ?XE(<<"li">>, [?INPUTT(<<"submit">>, <<"unregister">>, <<"Unregister">>)])])])], {200, [{<<"Server">>, <<"ejabberd">>}, {<<"Content-Type">>, <<"text/html">>}], ejabberd_web:make_xhtml(HeadEls, Els)}. %% @spec(Username, Host, Password) -> {success, ok, {Username, Host, Password} | %% {success, exists, {Username, Host, Password}} | %% {error, not_allowed} | %% {error, invalid_jid} 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 jid:make(Username, Host, <<"">>) of error -> {error, invalid_jid}; JID -> case acl:match_rule(Host, Access, JID) of deny -> {error, not_allowed}; allow -> register_account2(Username, Host, Password) end end. register_account2(Username, Host, Password) -> case ejabberd_auth:try_register(Username, Host, Password) of {atomic, Res} -> {success, Res, {Username, Host, Password}}; Other -> Other end. %%%---------------------------------------------------------------------- %%% Formulary delete POST %%%---------------------------------------------------------------------- form_del_post(Q, Host) -> case catch get_unregister_parameters(Q) of [Username, Password] -> try_unregister_account(Username, Host, Password); _ -> {error, wrong_parameters} end. get_unregister_parameters(Q) -> %% @spec(Username, Host, Password) -> {atomic, ok} | %% {error, account_doesnt_exist} | %% {error, account_exists} | %% {error, password_incorrect} lists:map(fun (Key) -> {value, {_Key, Value}} = lists:keysearch(Key, 1, Q), Value end, [<<"username">>, <<"password">>]). try_unregister_account(Username, Host, Password) -> try unregister_account(Username, Host, Password) of {atomic, ok} -> {atomic, ok} catch error:{badmatch, Error} -> {error, Error} end. unregister_account(Username, Host, Password) -> account_exists = check_account_exists(Username, Host), password_correct = check_password(Username, Host, Password), ok = ejabberd_auth:remove_user(Username, Host, Password), account_doesnt_exist = check_account_exists(Username, Host), {atomic, ok}. %%%---------------------------------------------------------------------- %%% Error texts %%%---------------------------------------------------------------------- get_error_text({error, captcha_non_valid}) -> <<"The captcha you entered is wrong">>; get_error_text({success, exists, _}) -> get_error_text({atomic, exists}); get_error_text({atomic, exists}) -> <<"The account already exists">>; get_error_text({error, password_incorrect}) -> <<"Incorrect password">>; get_error_text({error, invalid_jid}) -> <<"The username is not valid">>; get_error_text({error, not_allowed}) -> <<"Not allowed">>; get_error_text({error, account_doesnt_exist}) -> <<"Account doesn't exist">>; get_error_text({error, account_exists}) -> <<"The account was not deleted">>; get_error_text({error, password_not_changed}) -> <<"The password was not changed">>; 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(_) -> []. ejabberd-16.01/src/ejabberd_web.erl0000644000232200023220000000616512645157216017534 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_web.erl %%% Author : Alexey Shchepin %%% Purpose : %%% Purpose : %%% Created : 28 Feb 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_web). -author('alexey@process-one.net'). %% External exports -export([make_xhtml/1, make_xhtml/2, error/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_http.hrl"). %% XXX bard: there are variants of make_xhtml in ejabberd_http and %% ejabberd_web_admin. It might be a good idea to centralize it here %% and also create an ejabberd_web.hrl file holding the macros, so %% that third parties can use ejabberd_web as an "utility" library. make_xhtml(Els) -> make_xhtml([], Els). make_xhtml(HeadEls, Els) -> #xmlel{name = <<"html">>, attrs = [{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>}, {<<"xml:lang">>, <<"en">>}, {<<"lang">>, <<"en">>}], children = [#xmlel{name = <<"head">>, attrs = [], children = [#xmlel{name = <<"meta">>, attrs = [{<<"http-equiv">>, <<"Content-Type">>}, {<<"content">>, <<"text/html; charset=utf-8">>}], children = []} | HeadEls]}, #xmlel{name = <<"body">>, attrs = [], children = Els}]}. -define(X(Name), #xmlel{name = Name, attrs = [], children = []}). -define(XA(Name, Attrs), #xmlel{name = Name, attrs = Attrs, children = []}). -define(XE(Name, Els), #xmlel{name = Name, attrs = [], children = Els}). -define(XAE(Name, Attrs, Els), #xmlel{name = Name, attrs = Attrs, children = Els}). -define(C(Text), {xmlcdata, Text}). -define(XC(Name, Text), ?XE(Name, [?C(Text)])). -define(XAC(Name, Attrs, Text), ?XAE(Name, Attrs, [?C(Text)])). -define(LI(Els), ?XE(<<"li">>, Els)). -define(A(URL, Els), ?XAE(<<"a">>, [{<<"href">>, URL}], Els)). -define(AC(URL, Text), ?A(URL, [?C(Text)])). -define(P, ?X(<<"p">>)). -define(BR, ?X(<<"br">>)). -define(INPUT(Type, Name, Value), ?XA(<<"input">>, [{<<"type">>, Type}, {<<"name">>, Name}, {<<"value">>, Value}])). error(not_found) -> {404, [], make_xhtml([?XC(<<"h1">>, <<"404 Not Found">>)])}; error(not_allowed) -> {401, [], make_xhtml([?XC(<<"h1">>, <<"401 Unauthorized">>)])}. ejabberd-16.01/src/cyrsasl_plain.erl0000644000232200023220000000562212645157216020001 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : cyrsasl_plain.erl %%% Author : Alexey Shchepin %%% Purpose : PLAIN SASL mechanism %%% Created : 8 Mar 2003 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_plain). -author('alexey@process-one.net'). -export([start/1, stop/0, mech_new/4, mech_step/2, parse/1]). -behaviour(cyrsasl). -record(state, {check_password}). start(_Opts) -> cyrsasl:register_mechanism(<<"PLAIN">>, ?MODULE, plain), ok. stop() -> ok. mech_new(_Host, _GetPassword, CheckPassword, _CheckPasswordDigest) -> {ok, #state{check_password = CheckPassword}}. mech_step(State, ClientIn) -> case prepare(ClientIn) of [AuthzId, User, Password] -> case (State#state.check_password)(User, Password) of {true, AuthModule} -> {ok, [{username, User}, {authzid, AuthzId}, {auth_module, AuthModule}]}; _ -> {error, <<"not-authorized">>, User} end; _ -> {error, <<"bad-protocol">>} end. prepare(ClientIn) -> case parse(ClientIn) of [<<"">>, UserMaybeDomain, Password] -> case parse_domain(UserMaybeDomain) of %% login@domainpwd [User, _Domain] -> [UserMaybeDomain, User, Password]; %% loginpwd [User] -> [<<"">>, User, Password] end; %% login@domainloginpwd [AuthzId, User, Password] -> [AuthzId, User, Password]; _ -> 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]). ejabberd-16.01/src/ejabberd_logger.erl0000644000232200023220000002010012645157216020217 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov %%% @doc %%% %%% @end %%% Created : 12 May 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., %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%%------------------------------------------------------------------- -module(ejabberd_logger). -behaviour(ejabberd_config). %% API -export([start/0, reopen_log/0, rotate_log/0, get/0, set/1, get_log_path/0, opt_type/1]). -include("ejabberd.hrl"). -type loglevel() :: 0 | 1 | 2 | 3 | 4 | 5. -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()}. %%%=================================================================== %%% API %%%=================================================================== %% @doc Returns the full path to the ejabberd log file. %% It first checks for application configuration parameter 'log_path'. %% If not defined it checks the environment variable EJABBERD_LOG_PATH. %% And if that one is neither defined, returns the default value: %% "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. get_log_path() -> case ejabberd_config:env_binary_to_list(ejabberd, log_path) of {ok, Path} -> Path; undefined -> case os:getenv("EJABBERD_LOG_PATH") of false -> ?LOG_PATH; Path -> 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) -> case application:get_env(ejabberd, Name) of {ok, I} when is_integer(I), I>=0 -> I; undefined -> Default; {ok, Junk} -> error_logger:error_msg("wrong value for ~s: ~p; " "using ~p as a fallback~n", [Name, Junk, Default]), Default end. get_string_env(Name, Default) -> case application:get_env(ejabberd, Name) of {ok, L} when is_list(L) -> L; undefined -> Default; {ok, Junk} -> error_logger:error_msg("wrong value for ~s: ~p; " "using ~p as a fallback~n", [Name, Junk, Default]), Default end. start() -> application:load(sasl), application:set_env(sasl, sasl_error_logger, false), application:load(lager), ConsoleLog = get_log_path(), Dir = filename:dirname(ConsoleLog), ErrorLog = filename:join([Dir, "error.log"]), CrashLog = filename:join([Dir, "crash.log"]), LogRotateDate = get_string_env(log_rotate_date, ""), LogRotateSize = get_integer_env(log_rotate_size, 10*1024*1024), LogRotateCount = get_integer_env(log_rotate_count, 1), LogRateLimit = get_integer_env(log_rate_limit, 100), application:set_env(lager, error_logger_hwm, LogRateLimit), application:set_env( lager, handlers, [{lager_console_backend, info}, {lager_file_backend, [{file, ConsoleLog}, {level, info}, {date, LogRotateDate}, {count, LogRotateCount}, {size, LogRotateSize}]}, {lager_file_backend, [{file, ErrorLog}, {level, error}, {date, LogRotateDate}, {count, LogRotateCount}, {size, LogRotateSize}]}]), application:set_env(lager, crash_log, CrashLog), application:set_env(lager, crash_log_date, LogRotateDate), application:set_env(lager, crash_log_size, LogRotateSize), application:set_env(lager, crash_log_count, LogRotateCount), ejabberd:start_app(lager), ok. reopen_log() -> %% Lager detects external log rotation automatically. ok. rotate_log() -> lager_crash_log ! rotate, lists:foreach( fun({lager_file_backend, File}) -> whereis(lager_event) ! {rotate, File}; (_) -> ok end, gen_event:which_handlers(lager_event)). get() -> case lager:get_loglevel(lager_console_backend) of none -> {0, no_log, "No log"}; emergency -> {1, critical, "Critical"}; alert -> {1, critical, "Critical"}; critical -> {1, critical, "Critical"}; error -> {2, error, "Error"}; warning -> {3, warning, "Warning"}; notice -> {3, warning, "Warning"}; info -> {4, info, "Info"}; debug -> {5, debug, "Debug"} end. set(LogLevel) when is_integer(LogLevel) -> LagerLogLevel = case LogLevel of 0 -> none; 1 -> critical; 2 -> error; 3 -> warning; 4 -> info; 5 -> debug; E -> throw({wrong_loglevel, E}) end, case lager:get_loglevel(lager_console_backend) of LagerLogLevel -> ok; _ -> ConsoleLog = get_log_path(), lists:foreach( fun({lager_file_backend, File} = H) when File == ConsoleLog -> lager:set_loglevel(H, LagerLogLevel); (lager_console_backend = H) -> lager:set_loglevel(H, LagerLogLevel); (_) -> ok end, gen_event:which_handlers(lager_event)) end, {module, lager}; 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. ejabberd-16.01/src/mod_muc_admin.erl0000644000232200023220000007407512645157216017741 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_muc_admin.erl %%% Author : Badlop %%% Purpose : Tools for additional MUC administration %%% Created : 8 Sep 2007 by Badlop %%% Id : $Id: mod_muc_admin.erl 1133 2012-10-17 22:13:06Z badlop $ %%%---------------------------------------------------------------------- -module(mod_muc_admin). -author('badlop@ono.com'). -behaviour(gen_mod). -export([start/2, stop/1, muc_online_rooms/1, 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/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, web_page_host/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("mod_muc_room.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 %%---------------------------- start(Host, _Opts) -> ejabberd_commands:register_commands(commands()), 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_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), ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, web_page_host, 50). %%% %%% Register commands %%% 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}}}}, #ejabberd_commands{name = muc_unregister_nick, tags = [muc], desc = "Unregister the nick in the MUC service", module = ?MODULE, function = muc_unregister_nick, args = [{nick, binary}], result = {res, rescode}}, #ejabberd_commands{name = create_room, tags = [muc_room], desc = "Create a MUC room name@service in host", module = ?MODULE, function = create_room, args = [{name, binary}, {service, binary}, {host, binary}], result = {res, rescode}}, #ejabberd_commands{name = destroy_room, tags = [muc_room], desc = "Destroy a MUC room", module = ?MODULE, function = destroy_room, args = [{name, binary}, {service, binary}], 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}}, #ejabberd_commands{name = rooms_unused_list, tags = [muc], desc = "List the rooms that are unused for many days in host", module = ?MODULE, function = rooms_unused_list, args = [{host, binary}, {days, integer}], result = {rooms, {list, {room, string}}}}, #ejabberd_commands{name = rooms_unused_destroy, tags = [muc], desc = "Destroy the rooms that are unused for many days in host", module = ?MODULE, function = rooms_unused_destroy, 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, args = [{name, binary}, {service, binary}], result = {occupants, {list, {occupant, {tuple, [{jid, string}, {nick, string}, {role, string} ]}} }}}, #ejabberd_commands{name = get_room_occupants_number, tags = [muc_room], desc = "Get the number of occupants of a MUC room", module = ?MODULE, function = get_room_occupants_number, args = [{name, binary}, {service, binary}], result = {occupants, integer}}, #ejabberd_commands{name = send_direct_invitation, tags = [muc_room], 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 = [{name, binary}, {service, binary}, {password, binary}, {reason, binary}, {users, binary}], result = {res, rescode}}, #ejabberd_commands{name = change_room_option, tags = [muc_room], desc = "Change an option in a MUC room", module = ?MODULE, function = change_room_option, 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", module = ?MODULE, function = set_room_affiliation, args = [{name, binary}, {service, binary}, {jid, binary}, {affiliation, binary}], result = {res, rescode}}, #ejabberd_commands{name = get_room_affiliations, tags = [muc_room], desc = "Get the list of affiliations of a MUC room", module = ?MODULE, function = get_room_affiliations, args = [{name, binary}, {service, binary}], result = {affiliations, {list, {affiliation, {tuple, [{username, string}, {domain, string}, {affiliation, atom}, {reason, string} ]}} }}} ]. %%% %%% ejabberd commands %%% muc_online_rooms(ServerHost) -> MUCHost = find_host(ServerHost), Rooms = ets:tab2list(muc_online_room), lists:foldl( fun({_, {Roomname, Host}, _}, Results) -> case MUCHost of global -> [<> | Results]; Host -> [<> | Results]; _ -> Results end end, [], Rooms). muc_unregister_nick(Nick) -> F2 = fun(N) -> [{_,Key,_}] = mnesia:index_read(muc_registered, N, 3), mnesia:delete({muc_registered, Key}) end, case mnesia:transaction(F2, [Nick], 1) of {atomic, ok} -> ok; {aborted, _Error} -> 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 %%---------------------------- %%---------------------------- %% Web Admin %%---------------------------- %%--------------- %% Web Admin Menu web_menu_main(Acc, Lang) -> Acc ++ [{<<"muc">>, ?T(<<"Multi-User Chat">>)}]. web_menu_host(Acc, _Host, Lang) -> Acc ++ [{<<"muc">>, ?T(<<"Multi-User Chat">>)}]. %%--------------- %% Web Admin Page -define(TDTD(L, N), ?XE(<<"tr">>, [?XCT(<<"td">>, L), ?XC(<<"td">>, jlib:integer_to_binary(N)) ])). web_page_main(_, #request{path=[<<"muc">>], lang = Lang} = _Request) -> 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)), ?TDTD(<<"Registered nicknames">>, mnesia:table_info(muc_registered, size)) ]) ]), ?XE(<<"ul">>, [?LI([?ACT(<<"rooms">>, <<"List of rooms">>)])]) ], {stop, Res}; web_page_main(_, #request{path=[<<"muc">>, <<"rooms">>], q = Q, lang = Lang} = _Request) -> Sort_query = get_sort_query(Q), Res = make_rooms_page(global, Lang, Sort_query), {stop, Res}; web_page_main(Acc, _) -> Acc. web_page_host(_, Host, #request{path = [<<"muc">>], q = Q, lang = Lang} = _Request) -> Sort_query = get_sort_query(Q), Res = make_rooms_page(find_host(Host), Lang, Sort_query), {stop, Res}; web_page_host(Acc, _, _) -> Acc. %% Returns: {normal | reverse, Integer} get_sort_query(Q) -> case catch get_sort_query2(Q) of {ok, Res} -> Res; _ -> {normal, 1} end. get_sort_query2(Q) -> {value, {_, String}} = lists:keysearch(<<"sort">>, 1, Q), Integer = list_to_integer(binary_to_list(String)), case Integer >= 0 of true -> {ok, {normal, Integer}}; false -> {ok, {reverse, abs(Integer)}} end. make_rooms_page(Host, Lang, {Sort_direction, Sort_column}) -> Rooms_names = get_rooms(Host), Rooms_infos = build_info_rooms(Rooms_names), Rooms_sorted = sort_rooms(Sort_direction, Sort_column, Rooms_infos), Rooms_prepared = prepare_rooms_infos(Rooms_sorted), TList = lists:map( fun(Room) -> ?XE(<<"tr">>, [?XC(<<"td">>, E) || E <- Room]) end, Rooms_prepared), Titles = [<<"Jabber ID">>, <<"# participants">>, <<"Last message">>, <<"Public">>, <<"Persistent">>, <<"Logging">>, <<"Just created">>, <<"Room title">>], {Titles_TR, _} = lists:mapfoldl( fun(Title, Num_column) -> NCS = jlib:integer_to_binary(Num_column), TD = ?XE(<<"td">>, [?CT(Title), ?C(<<" ">>), ?AC(<<"?sort=", NCS/binary>>, <<"<">>), ?C(<<" ">>), ?AC(<<"?sort=-", NCS/binary>>, <<">">>)]), {TD, Num_column+1} end, 1, Titles), [?XCT(<<"h1">>, <<"Multi-User Chat">>), ?XCT(<<"h2">>, <<"Chatrooms">>), ?XE(<<"table">>, [?XE(<<"thead">>, [?XE(<<"tr">>, Titles_TR)] ), ?XE(<<"tbody">>, TList) ] ) ]. sort_rooms(Direction, Column, Rooms) -> Rooms2 = lists:keysort(Column, Rooms), case Direction of normal -> Rooms2; reverse -> lists:reverse(Rooms2) end. build_info_rooms(Rooms) -> [build_info_room(Room) || Room <- Rooms]. build_info_room({Name, Host, Pid}) -> C = get_room_config(Pid), Title = C#config.title, Public = C#config.public, Persistent = C#config.persistent, Logging = C#config.logging, S = get_room_state(Pid), Just_created = S#state.just_created, Num_participants = length(dict:fetch_keys(S#state.users)), History = (S#state.history)#lqueue.queue, Ts_last_message = case queue:is_empty(History) of true -> <<"A long time ago">>; false -> Last_message1 = queue:last(History), {_, _, _, Ts_last, _} = Last_message1, jlib:timestamp_to_iso(Ts_last) end, {<>, Num_participants, Ts_last_message, Public, Persistent, Logging, Just_created, Title}. prepare_rooms_infos(Rooms) -> [prepare_room_info(Room) || Room <- Rooms]. prepare_room_info(Room_info) -> {NameHost, Num_participants, Ts_last_message, Public, Persistent, Logging, Just_created, Title} = Room_info, [NameHost, jlib:integer_to_binary(Num_participants), Ts_last_message, jlib:atom_to_binary(Public), jlib:atom_to_binary(Persistent), jlib:atom_to_binary(Logging), jlib:atom_to_binary(Just_created), Title]. %%---------------------------- %% Create/Delete Room %%---------------------------- %% @spec (Name::binary(), Host::binary(), ServerHost::binary()) -> %% ok | error %% @doc Create a room immediately with the default options. create_room(Name, Host, ServerHost) -> %% Get the default room options from the muc configuration DefRoomOpts = gen_mod:get_module_opt(ServerHost, mod_muc, default_room_options, fun(X) -> X end, []), %% Store the room on the server, it is not started yet though at this point mod_muc:store_room(ServerHost, Host, Name, DefRoomOpts), %% Get all remaining mod_muc parameters that might be utilized Access = gen_mod:get_module_opt(ServerHost, mod_muc, access, fun(X) -> X end, all), 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), 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), %% If the room does not exist yet in the muc_online_room case mnesia:dirty_read(muc_online_room, {Name, Host}) of [] -> %% Start the room {ok, Pid} = mod_muc_room:start( Host, ServerHost, {Access, AcCreate, AcAdmin, AcPer}, Name, HistorySize, RoomShaper, DefRoomOpts), {atomic, ok} = register_room(Host, Name, Pid), ok; _ -> error end. register_room(Host, Name, Pid) -> F = fun() -> mnesia:write(#muc_online_room{name_host = {Name, Host}, pid = Pid}) end, mnesia:transaction(F). %% Create the room only in the database. %% It is required to restart the MUC service for the room to appear. 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()) -> %% 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) -> case mnesia:dirty_read(muc_online_room, {Name, Service}) of [R] -> Pid = R#muc_online_room.pid, gen_fsm:send_all_state_event(Pid, destroy), ok; [] -> error end. destroy_room({N, H, SH}) -> io:format("Destroying room: ~s@~s - vhost: ~s~n", [N, H, SH]), destroy_room(N, H). %%---------------------------- %% Destroy Rooms in File %%---------------------------- %% The format of the file is: one chatroom JID per line %% The file encoding must be UTF-8 destroy_rooms_file(Filename) -> {ok, F} = file:open(Filename, [read]), RJID = read_room(F), Rooms = read_rooms(F, RJID, []), file:close(F), [destroy_room(A) || A <- Rooms], ok. read_rooms(_F, eof, L) -> L; read_rooms(F, RJID, L) -> RJID2 = read_room(F), read_rooms(F, RJID2, [RJID | L]). read_room(F) -> case io:get_line(F, "") of eof -> eof; String -> case io_lib:fread("~s", String) of {ok, [RoomJID], _} -> split_roomjid(RoomJID); {error, What} -> io:format("Parse error: what: ~p~non the line: ~p~n~n", [What, String]) end end. %% 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]). %%---------------------------- %% Create Rooms in File %%---------------------------- create_rooms_file(Filename) -> {ok, F} = file:open(Filename, [read]), RJID = read_room(F), Rooms = read_rooms(F, RJID, []), file:close(F), %% Read the default room options defined for the first virtual host DefRoomOpts = gen_mod:get_module_opt(?MYNAME, mod_muc, default_room_options, fun(L) when is_list(L) -> L end, []), [muc_create_room(?MYNAME, A, DefRoomOpts) || A <- Rooms], ok. %%---------------------------- %% List/Delete Unused Rooms %%---------------------------- %%--------------- %% Control rooms_unused_list(Host, Days) -> rooms_unused_report(list, Host, Days). rooms_unused_destroy(Host, Days) -> rooms_unused_report(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, _P} <- RP]. muc_unused(Action, ServerHost, Days) -> Host = find_host(ServerHost), muc_unused2(Action, ServerHost, Host, Days). muc_unused2(Action, ServerHost, Host, Last_allowed) -> %% Get all required info about all existing rooms Rooms_all = get_rooms(Host), %% Decide which ones pass the requirements Rooms_pass = decide_rooms(Rooms_all, Last_allowed), Num_rooms_all = length(Rooms_all), Num_rooms_pass = length(Rooms_pass), %% Perform the desired action for matching rooms act_on_rooms(Action, Rooms_pass, ServerHost), {Num_rooms_all, Num_rooms_pass, Rooms_pass}. %%--------------- %% Get info get_rooms(Host) -> Get_room_names = fun(Room_reg, Names) -> Pid = Room_reg#muc_online_room.pid, case {Host, Room_reg#muc_online_room.name_host} of {Host, {Name1, Host}} -> [{Name1, Host, Pid} | Names]; {global, {Name1, Host1}} -> [{Name1, Host1, Pid} | Names]; _ -> Names end end, ets:foldr(Get_room_names, [], muc_online_room). get_room_config(Room_pid) -> {ok, R} = gen_fsm:sync_send_all_state_event(Room_pid, get_config), R. get_room_state(Room_pid) -> {ok, R} = gen_fsm:sync_send_all_state_event(Room_pid, get_state), R. %%--------------- %% Decide decide_rooms(Rooms, Last_allowed) -> Decide = fun(R) -> decide_room(R, Last_allowed) end, lists:filter(Decide, Rooms). decide_room({_Room_name, _Host, Room_pid}, Last_allowed) -> C = get_room_config(Room_pid), Persistent = C#config.persistent, S = get_room_state(Room_pid), Just_created = S#state.just_created, Room_users = S#state.users, Num_users = length(?DICT:to_list(Room_users)), History = (S#state.history)#lqueue.queue, Ts_now = calendar:universal_time(), Ts_uptime = uptime_seconds(), {Has_hist, Last} = case queue:is_empty(History) of true -> {false, Ts_uptime}; false -> Last_message = queue:last(History), {_, _, _, Ts_last, _} = Last_message, Ts_diff = calendar:datetime_to_gregorian_seconds(Ts_now) - calendar:datetime_to_gregorian_seconds(Ts_last), {true, Ts_diff} end, case {Persistent, Just_created, Num_users, Has_hist, seconds_to_days(Last)} of {_true, false, 0, _, Last_days} when Last_days >= Last_allowed -> true; _ -> false end. seconds_to_days(S) -> S div (60*60*24). %%--------------- %% Act act_on_rooms(Action, Rooms, ServerHost) -> ServerHosts = [ {A, find_host(A)} || A <- ?MYHOSTS ], Delete = fun({_N, H, _Pid} = Room) -> SH = case ServerHost of global -> find_serverhost(H, ServerHosts); O -> O end, act_on_room(Action, Room, SH) end, lists:foreach(Delete, Rooms). find_serverhost(Host, ServerHosts) -> {value, {ServerHost, Host}} = lists:keysearch(Host, 2, ServerHosts), ServerHost. act_on_room(destroy, {N, H, Pid}, SH) -> gen_fsm:send_all_state_event( Pid, {destroy, <<"Room destroyed by rooms_unused_destroy.">>}), mod_muc:room_destroyed(H, N, Pid, SH), mod_muc:forget_room(SH, H, N); act_on_room(list, _, _) -> ok. %%---------------------------- %% Change Room Option %%---------------------------- get_room_occupants(Room, Host) -> case get_room_pid(Room, Host) of room_not_found -> throw({error, room_not_found}); Pid -> get_room_occupants(Pid) end. get_room_occupants(Pid) -> S = get_room_state(Pid), lists:map( fun({_LJID, Info}) -> {jid:to_string(Info#user.jid), Info#user.nick, atom_to_list(Info#user.role)} end, dict:to_list(S#state.users)). get_room_occupants_number(Room, Host) -> length(get_room_occupants(Room, Host)). %%---------------------------- %% Send Direct Invitation %%---------------------------- %% http://xmpp.org/extensions/xep-0249.html 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) || UserStrings <- UsersStrings], timer:sleep(1000), ok. get_users_to_invite(RoomJid, UsersString) -> UsersStrings = string:tokens(UsersString, ":"), 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). build_invitation(Password, Reason, RoomString) -> PasswordAttrList = case Password of <<"none">> -> []; _ -> [{<<"password">>, Password}] end, ReasonAttrList = case Reason of <<"none">> -> []; _ -> [{<<"reason">>, Reason}] end, XAttrs = [{<<"xmlns">>, ?NS_XCONFERENCE}, {<<"jid">>, RoomString}] ++ PasswordAttrList ++ ReasonAttrList, XEl = {xmlel, <<"x">>, XAttrs, []}, {xmlel, <<"message">>, [], [XEl]}. send_direct_invitation(FromJid, UserJid, XmlEl) -> ejabberd_router:route(FromJid, UserJid, XmlEl). %%---------------------------- %% Change Room Option %%---------------------------- %% @spec(Name::string(), Service::string(), Option::string(), Value) -> ok %% Value = atom() | integer() | string() %% @doc Change an option in an existing room. %% Requires the name of the room, the MUC service where it exists, %% the option to change (for example title or max_users), %% and the value to assign to the new option. %% For example: %% change_room_option("testroom", "conference.localhost", "title", "Test Room") change_room_option(Name, Service, Option, Value) when is_atom(Option) -> Pid = get_room_pid(Name, Service), {ok, _} = change_room_option(Pid, Option, Value), ok; change_room_option(Name, Service, OptionString, ValueString) -> Option = jlib:binary_to_atom(OptionString), Value = case Option of title -> ValueString; description -> ValueString; password -> ValueString; subject ->ValueString; subject_author ->ValueString; max_users -> jlib:binary_to_integer(ValueString); _ -> jlib:binary_to_atom(ValueString) end, change_room_option(Name, Service, Option, Value). change_room_option(Pid, Option, Value) -> Config = get_room_config(Pid), Config2 = change_option(Option, Value, Config), gen_fsm:sync_send_all_state_event(Pid, {change_config, Config2}). %% @doc Get the Pid of an existing MUC room, or 'room_not_found'. get_room_pid(Name, Service) -> case mnesia:dirty_read(muc_online_room, {Name, Service}) of [] -> room_not_found; [Room] -> Room#muc_online_room.pid end. %% It is required to put explicitely all the options because %% the record elements are replaced at compile time. %% So, this can't be parametrized. 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}; 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}; moderated -> Config#config{moderated = Value}; password -> Config#config{password = Value}; password_protected -> Config#config{password_protected = Value}; persistent -> Config#config{persistent = Value}; public -> Config#config{public = Value}; public_list -> Config#config{public_list = Value}; title -> Config#config{title = Value}; vcard -> Config#config{vcard = Value}; voice_request_min_interval -> Config#config{voice_request_min_interval = Value} end. %%---------------------------- %% Get Room Options %%---------------------------- get_room_options(Name, Service) -> 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), get_options(Config). get_options(Config) -> Fields = record_info(fields, config), [config | Values] = tuple_to_list(Config), lists:zip(Fields, Values). %%---------------------------- %% Get Room Affiliations %%---------------------------- %% @spec(Name::binary(), Service::binary()) -> %% [{JID::string(), Domain::string(), Role::string(), Reason::string()}] %% @doc Get the affiliations of the room Name@Service. get_room_affiliations(Name, Service) -> case mnesia:dirty_read(muc_online_room, {Name, Service}) of [R] -> %% Get the PID of the online room, then request its state Pid = R#muc_online_room.pid, {ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, get_state), Affiliations = ?DICT:to_list(StateData#state.affiliations), lists:map( fun({{Uname, Domain, _Res}, {Aff, Reason}}) when is_atom(Aff)-> {Uname, Domain, Aff, Reason}; ({{Uname, Domain, _Res}, Aff}) when is_atom(Aff)-> {Uname, Domain, Aff, <<>>} end, Affiliations); [] -> throw({error, "The room does not exist."}) end. %%---------------------------- %% Change Room Affiliation %%---------------------------- %% @spec(Name, Service, JID, AffiliationString) -> ok | {error, Error} %% Name = binary() %% Service = binary() %% JID = binary() %% AffiliationString = "outcast" | "none" | "member" | "admin" | "owner" %% @doc Set the affiliation of JID in the room Name@Service. %% If the affiliation is 'none', the action is to remove, %% In any other case the action will be to create the affiliation. set_room_affiliation(Name, Service, JID, AffiliationString) -> Affiliation = jlib:binary_to_atom(AffiliationString), case mnesia:dirty_read(muc_online_room, {Name, Service}) of [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, {jid:from_string(JID), affiliation, Affiliation, <<"">>}, <<"">>}), mod_muc:store_room(StateData#state.server_host, StateData#state.host, StateData#state.room, make_opts(StateData)), ok; [] -> error end. make_opts(StateData) -> Config = StateData#state.config, [ {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} ]. %%---------------------------- %% Utils %%---------------------------- uptime_seconds() -> trunc(element(1, erlang:statistics(wall_clock))/1000). find_host(global) -> global; find_host("global") -> global; find_host(<<"global">>) -> global; 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(_) -> []. ejabberd-16.01/src/cyrsasl_scram.erl0000644000232200023220000001745512645157216020012 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : cyrsasl_scram.erl %%% Author : Stephen Röttger %%% Purpose : SASL SCRAM authentication %%% Created : 7 Aug 2011 by Stephen Röttger %%% %%% %%% 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_scram). -author('stephen.roettger@googlemail.com'). -protocol({rfc, 5802}). -export([start/1, stop/0, mech_new/4, mech_step/2]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -behaviour(cyrsasl). -record(state, {step = 2 :: 2 | 4, stored_key = <<"">> :: binary(), server_key = <<"">> :: binary(), username = <<"">> :: binary(), get_password :: fun(), check_password :: fun(), auth_message = <<"">> :: binary(), client_nonce = <<"">> :: binary(), server_nonce = <<"">> :: binary()}). -define(SALT_LENGTH, 16). -define(NONCE_LENGTH, 16). start(_Opts) -> cyrsasl:register_mechanism(<<"SCRAM-SHA-1">>, ?MODULE, scram). stop() -> ok. mech_new(_Host, GetPassword, _CheckPassword, _CheckPasswordDigest) -> {ok, #state{step = 2, get_password = GetPassword}}. mech_step(#state{step = 2} = State, ClientIn) -> case re:split(ClientIn, <<",">>, [{return, binary}]) of [_CBind, _AuthorizationIdentity, _UserNameAttribute, _ClientNonceAttribute, ExtensionAttribute | _] when ExtensionAttribute /= [] -> {error, <<"protocol-error-extension-not-supported">>}; [CBind, _AuthorizationIdentity, UserNameAttribute, ClientNonceAttribute | _] when (CBind == <<"y">>) or (CBind == <<"n">>) -> case parse_attribute(UserNameAttribute) of {error, Reason} -> {error, Reason}; {_, EscapedUserName} -> case unescape_username(EscapedUserName) of error -> {error, <<"protocol-error-bad-username">>}; UserName -> case parse_attribute(ClientNonceAttribute) of {$r, ClientNonce} -> {Ret, _AuthModule} = (State#state.get_password)(UserName), 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, _} -> {StoredKey, ServerKey, Salt, IterationCount} = if is_tuple(Ret) -> Ret; true -> TempSalt = crypto:rand_bytes(?SALT_LENGTH), SaltedPassword = scram:salted_password(Ret, TempSalt, ?SCRAM_DEFAULT_ITERATION_COUNT), {scram:stored_key(scram:client_key(SaltedPassword)), scram:server_key(SaltedPassword), TempSalt, ?SCRAM_DEFAULT_ITERATION_COUNT} end, ClientFirstMessageBare = str:substr(ClientIn, str:str(ClientIn, <<"n=">>)), ServerNonce = jlib:encode_base64(crypto:rand_bytes(?NONCE_LENGTH)), ServerFirstMessage = iolist_to_binary( ["r=", ClientNonce, ServerNonce, ",", "s=", jlib:encode_base64(Salt), ",", "i=", integer_to_list(IterationCount)]), {continue, ServerFirstMessage, State#state{step = 4, stored_key = StoredKey, server_key = ServerKey, auth_message = <>, client_nonce = ClientNonce, server_nonce = ServerNonce, username = UserName}} end; _Else -> {error, <<"not-supported">>} end end end; _Else -> {error, <<"bad-protocol">>} end; mech_step(#state{step = 4} = State, ClientIn) -> case str:tokens(ClientIn, <<",">>) of [GS2ChannelBindingAttribute, NonceAttribute, ClientProofAttribute] -> case parse_attribute(GS2ChannelBindingAttribute) of {$c, CVal} -> ChannelBindingSupport = binary:at(jlib:decode_base64(CVal), 0), if (ChannelBindingSupport == $n) or (ChannelBindingSupport == $y) -> Nonce = <<(State#state.client_nonce)/binary, (State#state.server_nonce)/binary>>, case parse_attribute(NonceAttribute) of {$r, CompareNonce} when CompareNonce == Nonce -> case parse_attribute(ClientProofAttribute) of {$p, ClientProofB64} -> ClientProof = jlib:decode_base64(ClientProofB64), AuthMessage = iolist_to_binary( [State#state.auth_message, ",", str:substr(ClientIn, 1, str:str(ClientIn, <<",p=">>) - 1)]), ClientSignature = scram:client_signature(State#state.stored_key, AuthMessage), ClientKey = scram:client_key(ClientProof, ClientSignature), CompareStoredKey = scram:stored_key(ClientKey), if CompareStoredKey == State#state.stored_key -> ServerSignature = scram:server_signature(State#state.server_key, AuthMessage), {ok, [{username, State#state.username}], <<"v=", (jlib:encode_base64(ServerSignature))/binary>>}; true -> {error, <<"bad-auth">>, State#state.username} end; _Else -> {error, <<"bad-protocol">>} end; {$r, _} -> {error, <<"bad-nonce">>}; _Else -> {error, <<"bad-protocol">>} end; true -> {error, <<"bad-channel-binding">>} end; _Else -> {error, <<"bad-protocol">>} end; _Else -> {error, <<"bad-protocol">>} end. parse_attribute(Attribute) -> AttributeLen = byte_size(Attribute), if AttributeLen >= 3 -> AttributeS = binary_to_list(Attribute), SecondChar = lists:nth(2, AttributeS), case is_alpha(lists:nth(1, AttributeS)) of true -> if SecondChar == $= -> String = str:substr(Attribute, 3), {lists:nth(1, AttributeS), String}; true -> {error, <<"bad-format second char not equal sign">>} end; _Else -> {error, <<"bad-format first char not a letter">>} end; true -> {error, <<"bad-format attribute too short">>} end. unescape_username(<<"">>) -> <<"">>; unescape_username(EscapedUsername) -> Pos = str:str(EscapedUsername, <<"=">>), if Pos == 0 -> EscapedUsername; true -> Start = str:substr(EscapedUsername, 1, Pos - 1), End = str:substr(EscapedUsername, Pos), EndLen = byte_size(End), if EndLen < 3 -> error; true -> case str:substr(End, 1, 3) of <<"=2C">> -> <>; <<"=3D">> -> < mnesia:create_table(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 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 end. ejabberd-16.01/src/mod_proxy65_lib.erl0000644000232200023220000000501112645157216020147 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_proxy65_lib.erl %%% Author : Evgeniy Khramtsov %%% Purpose : SOCKS5 parsing library. %%% Created : 12 Oct 2006 by Evgeniy 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(mod_proxy65_lib). -author('xram@jabber.ru'). -include("mod_proxy65.hrl"). -export([unpack_init_message/1, unpack_auth_request/1, unpack_request/1, make_init_reply/1, make_auth_reply/1, make_reply/1, make_error_reply/1, make_error_reply/2]). unpack_init_message(<<(?VERSION_5), N, AuthMethodList:N/binary>>) when N > 0, N < 256 -> {ok, binary_to_list(AuthMethodList)}; unpack_init_message(_) -> error. unpack_auth_request(<<1, ULen, User:ULen/binary, PLen, Pass:PLen/binary>>) when ULen < 256, PLen < 256 -> {(User), (Pass)}; unpack_auth_request(_) -> error. unpack_request(<<(?VERSION_5), CMD, RSV, (?ATYP_DOMAINNAME), 40, SHA1:40/binary, 0, 0>>) when CMD == (?CMD_CONNECT); CMD == (?CMD_UDP) -> Command = if CMD == (?CMD_CONNECT) -> connect; CMD == (?CMD_UDP) -> udp end, #s5_request{cmd = Command, rsv = RSV, sha1 = (SHA1)}; unpack_request(_) -> error. make_init_reply(Method) -> [?VERSION_5, Method]. make_auth_reply(true) -> [1, ?SUCCESS]; make_auth_reply(false) -> [1, ?ERR_NOT_ALLOWED]. make_reply(#s5_request{rsv = RSV, sha1 = SHA1}) -> [?VERSION_5, ?SUCCESS, RSV, ?ATYP_DOMAINNAME, byte_size(SHA1), SHA1, 0, 0]. make_error_reply(Request) -> make_error_reply(Request, ?ERR_NOT_ALLOWED). make_error_reply(#s5_request{rsv = RSV, sha1 = SHA1}, Reason) -> [?VERSION_5, Reason, RSV, ?ATYP_DOMAINNAME, byte_size(SHA1), SHA1, 0, 0]. ejabberd-16.01/src/mod_roster.erl0000644000232200023220000016326012645157216017316 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_roster.erl %%% Author : Alexey Shchepin %%% Purpose : Roster management %%% Created : 11 Dec 2002 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. %%% %%%---------------------------------------------------------------------- %%% @doc Roster management (Mnesia storage). %%% %%% Includes support for XEP-0237: Roster Versioning. %%% The roster versioning follows an all-or-nothing strategy: %%% - If the version supplied by the client is the latest, return an empty response. %%% - If not, return the entire new roster (with updated version string). %%% Roster version is a hash digest of the entire roster. %%% No additional data is stored in DB. -module(mod_roster). -protocol({xep, 237, '1.3'}). -protocol({xep, 321, '0.1'}). -author('alexey@process-one.net'). -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, 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, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("mod_roster.hrl"). -include("ejabberd_http.hrl"). -include("ejabberd_web_admin.hrl"). -export_type([subscription/0]). start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, one_queue), case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(roster, [{disc_copies, [node()]}, {attributes, record_info(fields, roster)}]), mnesia:create_table(roster_version, [{disc_copies, [node()]}, {attributes, record_info(fields, roster_version)}]), update_tables(), mnesia:add_table_index(roster, us), mnesia:add_table_index(roster_version, us); _ -> ok end, ejabberd_hooks:add(roster_get, Host, ?MODULE, get_user_roster, 50), ejabberd_hooks:add(roster_in_subscription, Host, ?MODULE, in_subscription, 50), ejabberd_hooks:add(roster_out_subscription, Host, ?MODULE, out_subscription, 50), ejabberd_hooks:add(roster_get_subscription_lists, Host, ?MODULE, get_subscription_lists, 50), ejabberd_hooks:add(roster_get_jid_info, Host, ?MODULE, get_jid_info, 50), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), ejabberd_hooks:add(resend_subscription_requests_hook, Host, ?MODULE, get_in_pending_subscriptions, 50), ejabberd_hooks:add(roster_get_versioning_feature, Host, ?MODULE, get_versioning_feature, 50), ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, webadmin_page, 50), ejabberd_hooks:add(webadmin_user, Host, ?MODULE, webadmin_user, 50), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER, ?MODULE, process_iq, IQDisc). stop(Host) -> ejabberd_hooks:delete(roster_get, Host, ?MODULE, get_user_roster, 50), ejabberd_hooks:delete(roster_in_subscription, Host, ?MODULE, in_subscription, 50), ejabberd_hooks:delete(roster_out_subscription, Host, ?MODULE, out_subscription, 50), ejabberd_hooks:delete(roster_get_subscription_lists, Host, ?MODULE, get_subscription_lists, 50), ejabberd_hooks:delete(roster_get_jid_info, Host, ?MODULE, get_jid_info, 50), ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), ejabberd_hooks:delete(resend_subscription_requests_hook, Host, ?MODULE, get_in_pending_subscriptions, 50), ejabberd_hooks:delete(roster_get_versioning_feature, Host, ?MODULE, get_versioning_feature, 50), ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, webadmin_page, 50), ejabberd_hooks:delete(webadmin_user, Host, ?MODULE, webadmin_user, 50), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER). process_iq(From, To, IQ) when ((From#jid.luser == <<"">>) andalso (From#jid.resource == <<"">>)) -> process_iq_manager(From, To, IQ); process_iq(From, To, IQ) -> #iq{sub_el = SubEl} = IQ, #jid{lserver = LServer} = From, case lists:member(LServer, ?MYHOSTS) of true -> process_local_iq(From, To, IQ); _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]} end. process_local_iq(From, To, #iq{type = Type} = IQ) -> case Type of set -> try_process_iq_set(From, To, IQ); get -> process_iq_get(From, To, IQ) end. roster_hash(Items) -> p1_sha:sha(term_to_binary(lists:sort([R#roster{groups = lists:sort(Grs)} || R = #roster{groups = Grs} <- Items]))). roster_versioning_enabled(Host) -> gen_mod:get_module_opt(Host, ?MODULE, versioning, fun(B) when is_boolean(B) -> B end, false). roster_version_on_db(Host) -> gen_mod:get_module_opt(Host, ?MODULE, store_current_id, fun(B) when is_boolean(B) -> B end, false). %% Returns a list that may contain an xmlelement with the XEP-237 feature if it's enabled. get_versioning_feature(Acc, Host) -> case roster_versioning_enabled(Host) of true -> Feature = #xmlel{name = <<"ver">>, attrs = [{<<"xmlns">>, ?NS_ROSTER_VER}], children = []}, [Feature | Acc]; false -> [] end. roster_version(LServer, LUser) -> US = {LUser, LServer}, case roster_version_on_db(LServer) of true -> case read_roster_version(LUser, LServer) of error -> not_found; V -> V end; false -> roster_hash(ejabberd_hooks:run_fold(roster_get, LServer, [], [US])) end. read_roster_version(LUser, LServer) -> read_roster_version(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). read_roster_version(LUser, LServer, mnesia) -> US = {LUser, LServer}, case mnesia:dirty_read(roster_version, US) of [#roster_version{version = V}] -> V; [] -> 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 end; read_roster_version(LServer, LUser, riak) -> case ejabberd_riak:get(roster_version, roster_version_schema(), {LUser, LServer}) of {ok, #roster_version{version = V}} -> V; _Err -> error end. write_roster_version(LUser, LServer) -> write_roster_version(LUser, LServer, false). 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(p1_time_compat:unique_integer())), write_roster_version(LUser, LServer, InTransaction, Ver, gen_mod:db_type(LServer, ?MODULE)), Ver. write_roster_version(LUser, LServer, InTransaction, Ver, mnesia) -> US = {LUser, LServer}, if InTransaction -> mnesia:write(#roster_version{us = US, version = Ver}); true -> mnesia:dirty_write(#roster_version{us = US, version = Ver}) end; write_roster_version(LUser, LServer, InTransaction, Ver, odbc) -> Username = ejabberd_odbc:escape(LUser), EVer = ejabberd_odbc:escape(Ver), if InTransaction -> odbc_queries:set_roster_version(Username, EVer); true -> odbc_queries:sql_transaction(LServer, fun () -> odbc_queries:set_roster_version(Username, EVer) end) end; write_roster_version(LUser, LServer, _InTransaction, Ver, riak) -> US = {LUser, LServer}, ejabberd_riak:put(#roster_version{us = US, version = Ver}, roster_version_schema()). %% 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 %% - roster versioning is used by server and client, BUT the server isn't storing versions on db OR %% - the roster version from client don't match current version. process_iq_get(From, To, #iq{sub_el = SubEl} = IQ) -> LUser = From#jid.luser, LServer = From#jid.lserver, US = {LUser, LServer}, try {ItemsToSend, VersionToSend} = case {xml:get_tag_attr(<<"ver">>, SubEl), roster_versioning_enabled(LServer), roster_version_on_db(LServer)} of {{value, RequestedVersion}, true, true} -> case read_roster_version(LUser, LServer) of error -> RosterVersion = write_roster_version(LUser, LServer), {lists:map(fun item_to_xml/1, ejabberd_hooks:run_fold(roster_get, To#jid.lserver, [], [US])), RosterVersion}; RequestedVersion -> {false, false}; NewVersion -> {lists:map(fun item_to_xml/1, ejabberd_hooks:run_fold(roster_get, To#jid.lserver, [], [US])), NewVersion} end; {{value, RequestedVersion}, true, false} -> RosterItems = ejabberd_hooks:run_fold(roster_get, To#jid.lserver, [], [US]), case roster_hash(RosterItems) of RequestedVersion -> {false, false}; New -> {lists:map(fun item_to_xml/1, RosterItems), New} end; _ -> {lists:map(fun item_to_xml/1, ejabberd_hooks:run_fold(roster_get, To#jid.lserver, [], [US])), false} end, IQ#iq{type = result, sub_el = case {ItemsToSend, VersionToSend} of {false, false} -> []; {Items, false} -> [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_ROSTER}], children = Items}]; {Items, Version} -> [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_ROSTER}, {<<"ver">>, Version}], children = Items}] end} catch _:_ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} end. get_user_roster(Acc, {LUser, LServer}) -> Items = get_roster(LUser, LServer), lists:filter(fun (#roster{subscription = none, ask = in}) -> false; (_) -> true end, Items) ++ Acc. get_roster(LUser, LServer) -> get_roster(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). get_roster(LUser, LServer, mnesia) -> US = {LUser, LServer}, case catch mnesia:dirty_index_read(roster, US, #roster.us) of Items when is_list(Items)-> Items; _ -> [] end; get_roster(LUser, LServer, riak) -> case ejabberd_riak:get_by_index(roster, roster_schema(), <<"us">>, {LUser, LServer}) of {ok, Items} -> Items; _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; _ -> [] end. item_to_xml(Item) -> Attrs1 = [{<<"jid">>, jid:to_string(Item#roster.jid)}], Attrs2 = case Item#roster.name of <<"">> -> Attrs1; Name -> [{<<"name">>, Name} | Attrs1] end, Attrs3 = case Item#roster.subscription of none -> [{<<"subscription">>, <<"none">>} | Attrs2]; from -> [{<<"subscription">>, <<"from">>} | Attrs2]; to -> [{<<"subscription">>, <<"to">>} | Attrs2]; both -> [{<<"subscription">>, <<"both">>} | Attrs2]; remove -> [{<<"subscription">>, <<"remove">>} | Attrs2] end, Attrs4 = case ask_to_pending(Item#roster.ask) of out -> [{<<"ask">>, <<"subscribe">>} | Attrs3]; both -> [{<<"ask">>, <<"subscribe">>} | Attrs3]; _ -> Attrs3 end, SubEls1 = lists:map(fun (G) -> #xmlel{name = <<"group">>, attrs = [], children = [{xmlcdata, G}]} end, Item#roster.groups), SubEls = SubEls1 ++ Item#roster.xs, #xmlel{name = <<"item">>, attrs = Attrs4, children = SubEls}. get_roster_by_jid_t(LUser, LServer, LJID) -> DBType = gen_mod:db_type(LServer, ?MODULE), get_roster_by_jid_t(LUser, LServer, LJID, DBType). get_roster_by_jid_t(LUser, LServer, LJID, mnesia) -> case mnesia:read({roster, {LUser, LServer, LJID}}) of [] -> #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID}; [I] -> I#roster{jid = LJID, name = <<"">>, groups = [], 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), case Res of [] -> #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID}; [I] -> R = raw_to_record(LServer, I), case R of %% Bad JID in database: error -> #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID}; _ -> R#roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID, name = <<"">>} end end; get_roster_by_jid_t(LUser, LServer, LJID, riak) -> case ejabberd_riak:get(roster, roster_schema(), {LUser, LServer, LJID}) of {ok, I} -> I#roster{jid = LJID, name = <<"">>, groups = [], xs = []}; {error, notfound} -> #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID}; Err -> exit(Err) end. try_process_iq_set(From, To, #iq{sub_el = SubEl} = IQ) -> #jid{server = Server} = From, Access = gen_mod:get_module_opt(Server, ?MODULE, access, fun(A) when is_atom(A) -> A end, all), case acl:match_rule(Server, Access, From) of deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; allow -> process_iq_set(From, To, IQ) end. process_iq_set(From, To, #iq{sub_el = SubEl, id = Id} = IQ) -> #xmlel{children = Els} = SubEl, Managed = is_managed_from_id(Id), lists:foreach(fun (El) -> process_item_set(From, To, El, Managed) end, Els), IQ#iq{type = result, sub_el = []}. process_item_set(From, To, #xmlel{attrs = Attrs, children = Els}, Managed) -> JID1 = jid:from_string(xml:get_attr_s(<<"jid">>, Attrs)), #jid{user = User, luser = LUser, lserver = LServer} = From, case JID1 of error -> ok; _ -> LJID = jid:tolower(JID1), F = fun () -> Item = get_roster_by_jid_t(LUser, LServer, LJID), Item1 = process_item_attrs_managed(Item, Attrs, Managed), Item2 = process_item_els(Item1, Els), case Item2#roster.subscription of remove -> del_roster_t(LUser, LServer, LJID); _ -> update_roster_t(LUser, LServer, LJID, Item2) end, send_itemset_to_managers(From, Item2, Managed), Item3 = ejabberd_hooks:run_fold(roster_process_item, LServer, Item2, [LServer]), case roster_version_on_db(LServer) of true -> write_roster_version_t(LUser, LServer); false -> ok end, {Item, Item3} end, case transaction(LServer, F) of {atomic, {OldItem, Item}} -> push_item(User, LServer, To, Item), case Item#roster.subscription of remove -> send_unsubscribing_presence(From, OldItem), ok; _ -> ok end; E -> ?DEBUG("ROSTER: roster item set error: ~p~n", [E]), ok end end; process_item_set(_From, _To, _, _Managed) -> ok. process_item_attrs(Item, [{Attr, Val} | Attrs]) -> case Attr of <<"jid">> -> case jid:from_string(Val) of error -> process_item_attrs(Item, Attrs); JID1 -> JID = {JID1#jid.luser, JID1#jid.lserver, JID1#jid.lresource}, process_item_attrs(Item#roster{jid = JID}, Attrs) end; <<"name">> -> process_item_attrs(Item#roster{name = Val}, Attrs); <<"subscription">> -> case Val of <<"remove">> -> process_item_attrs(Item#roster{subscription = remove}, Attrs); _ -> process_item_attrs(Item, Attrs) end; <<"ask">> -> process_item_attrs(Item, Attrs); _ -> process_item_attrs(Item, Attrs) end; process_item_attrs(Item, []) -> Item. process_item_els(Item, [#xmlel{name = Name, attrs = Attrs, children = SEls} | Els]) -> case Name of <<"group">> -> Groups = [xml:get_cdata(SEls) | Item#roster.groups], process_item_els(Item#roster{groups = Groups}, Els); _ -> case xml:get_attr_s(<<"xmlns">>, Attrs) of <<"">> -> process_item_els(Item, Els); _ -> XEls = [#xmlel{name = Name, attrs = Attrs, children = SEls} | Item#roster.xs], process_item_els(Item#roster{xs = XEls}, Els) end end; process_item_els(Item, [{xmlcdata, _} | Els]) -> process_item_els(Item, Els); process_item_els(Item, []) -> Item. push_item(User, Server, From, Item) -> ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>), jid:make(User, Server, <<"">>), {broadcast, {item, Item#roster.jid, Item#roster.subscription}}), case roster_versioning_enabled(Server) of true -> push_item_version(Server, User, From, Item, roster_version(Server, User)); false -> lists:foreach(fun (Resource) -> push_item(User, Server, Resource, From, Item) end, ejabberd_sm:get_user_resources(User, Server)) end. push_item(User, Server, Resource, From, Item) -> push_item(User, Server, Resource, From, Item, not_found). push_item(User, Server, Resource, From, Item, RosterVersion) -> ExtraAttrs = case RosterVersion of not_found -> []; _ -> [{<<"ver">>, RosterVersion}] end, ResIQ = #iq{type = set, xmlns = ?NS_ROSTER, %% @doc Roster push, calculate and include the version attribute. %% TODO: don't push to those who didn't load roster id = <<"push", (randoms:get_string())/binary>>, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_ROSTER} | ExtraAttrs], children = [item_to_xml(Item)]}]}, ejabberd_router:route(From, jid:make(User, Server, Resource), jlib:iq_to_xml(ResIQ)). push_item_version(Server, User, From, Item, RosterVersion) -> lists:foreach(fun (Resource) -> push_item(User, Server, Resource, From, Item, RosterVersion) end, ejabberd_sm:get_user_resources(User, Server)). get_subscription_lists(Acc, User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), DBType = gen_mod:db_type(LServer, ?MODULE), Items = get_subscription_lists(Acc, LUser, LServer, DBType), fill_subscription_lists(LServer, Items, [], []). get_subscription_lists(_, LUser, LServer, mnesia) -> US = {LUser, LServer}, case mnesia:dirty_index_read(roster, US, #roster.us) of Items when is_list(Items) -> Items; _ -> [] 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) -> lists:map(fun(I) -> raw_to_record(LServer, I) end, Items); _ -> [] end; get_subscription_lists(_, LUser, LServer, riak) -> case ejabberd_riak:get_by_index(roster, roster_schema(), <<"us">>, {LUser, LServer}) of {ok, Items} -> Items; _Err -> [] end. fill_subscription_lists(LServer, [#roster{} = I | Is], F, T) -> J = element(3, I#roster.usj), case I#roster.subscription of both -> fill_subscription_lists(LServer, Is, [J | F], [J | T]); from -> fill_subscription_lists(LServer, Is, [J | F], T); to -> fill_subscription_lists(LServer, Is, F, [J | T]); _ -> fill_subscription_lists(LServer, Is, F, T) end; fill_subscription_lists(LServer, [RawI | Is], F, T) -> I = raw_to_record(LServer, RawI), case I of %% Bad JID in database: error -> fill_subscription_lists(LServer, Is, F, T); _ -> fill_subscription_lists(LServer, [I | Is], F, T) end; fill_subscription_lists(_LServer, [], F, T) -> {F, T}. ask_to_pending(subscribe) -> out; ask_to_pending(unsubscribe) -> none; ask_to_pending(Ask) -> Ask. roster_subscribe_t(LUser, LServer, LJID, Item) -> DBType = gen_mod:db_type(LServer, ?MODULE), roster_subscribe_t(LUser, LServer, LJID, Item, DBType). 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, riak) -> ejabberd_riak:put(Item, roster_schema(), [{'2i', [{<<"us">>, {LUser, LServer}}]}]). transaction(LServer, F) -> case gen_mod:db_type(LServer, ?MODULE) of mnesia -> mnesia:transaction(F); odbc -> ejabberd_odbc:sql_transaction(LServer, F); riak -> {atomic, F()} end. in_subscription(_, User, Server, JID, Type, Reason) -> process_subscription(in, User, Server, JID, Type, Reason). out_subscription(User, Server, JID, Type) -> process_subscription(out, User, Server, JID, Type, <<"">>). get_roster_by_jid_with_groups_t(LUser, LServer, LJID) -> DBType = gen_mod:db_type(LServer, ?MODULE), get_roster_by_jid_with_groups_t(LUser, LServer, LJID, DBType). get_roster_by_jid_with_groups_t(LUser, LServer, LJID, mnesia) -> case mnesia:read({roster, {LUser, LServer, LJID}}) of [] -> #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID}; [I] -> I 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">>], []} -> #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID} end; get_roster_by_jid_with_groups_t(LUser, LServer, LJID, riak) -> case ejabberd_riak:get(roster, roster_schema(), {LUser, LServer, LJID}) of {ok, I} -> I; {error, notfound} -> #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID}; Err -> exit(Err) end. process_subscription(Direction, User, Server, JID1, Type, Reason) -> 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), NewState = case Direction of out -> out_state_change(Item#roster.subscription, Item#roster.ask, Type); in -> in_state_change(Item#roster.subscription, Item#roster.ask, Type) end, AutoReply = case Direction of out -> none; in -> in_auto_reply(Item#roster.subscription, Item#roster.ask, Type) end, AskMessage = case NewState of {_, both} -> Reason; {_, in} -> Reason; _ -> <<"">> end, case NewState of none -> {none, AutoReply}; {none, none} when Item#roster.subscription == none, Item#roster.ask == in -> del_roster_t(LUser, LServer, LJID), {none, AutoReply}; {Subscription, Pending} -> NewItem = Item#roster{subscription = Subscription, ask = Pending, askmessage = iolist_to_binary(AskMessage)}, roster_subscribe_t(LUser, LServer, LJID, NewItem), case roster_version_on_db(LServer) of true -> write_roster_version_t(LUser, LServer); false -> ok end, {{push, NewItem}, AutoReply} end end, case transaction(LServer, F) of {atomic, {Push, AutoReply}} -> case AutoReply of none -> ok; _ -> T = case AutoReply of subscribed -> <<"subscribed">>; unsubscribed -> <<"unsubscribed">> end, ejabberd_router:route(jid:make(User, Server, <<"">>), JID1, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, T}], children = []}) end, case Push of {push, Item} -> if Item#roster.subscription == none, Item#roster.ask == in -> ok; true -> push_item(User, Server, jid:make(User, Server, <<"">>), Item) end, true; none -> false end; _ -> false end. %% in_state_change(Subscription, Pending, Type) -> NewState %% NewState = none | {NewSubscription, NewPending} -ifdef(ROSTER_GATEWAY_WORKAROUND). -define(NNSD, {to, none}). -define(NISD, {to, in}). -else. -define(NNSD, none). -define(NISD, none). -endif. in_state_change(none, none, subscribe) -> {none, in}; in_state_change(none, none, subscribed) -> ?NNSD; in_state_change(none, none, unsubscribe) -> none; in_state_change(none, none, unsubscribed) -> none; in_state_change(none, out, subscribe) -> {none, both}; in_state_change(none, out, subscribed) -> {to, none}; in_state_change(none, out, unsubscribe) -> none; in_state_change(none, out, unsubscribed) -> {none, none}; in_state_change(none, in, subscribe) -> none; in_state_change(none, in, subscribed) -> ?NISD; in_state_change(none, in, unsubscribe) -> {none, none}; in_state_change(none, in, unsubscribed) -> none; in_state_change(none, both, subscribe) -> none; in_state_change(none, both, subscribed) -> {to, in}; in_state_change(none, both, unsubscribe) -> {none, out}; in_state_change(none, both, unsubscribed) -> {none, in}; in_state_change(to, none, subscribe) -> {to, in}; in_state_change(to, none, subscribed) -> none; in_state_change(to, none, unsubscribe) -> none; in_state_change(to, none, unsubscribed) -> {none, none}; in_state_change(to, in, subscribe) -> none; in_state_change(to, in, subscribed) -> none; in_state_change(to, in, unsubscribe) -> {to, none}; in_state_change(to, in, unsubscribed) -> {none, in}; in_state_change(from, none, subscribe) -> none; in_state_change(from, none, subscribed) -> {both, none}; in_state_change(from, none, unsubscribe) -> {none, none}; in_state_change(from, none, unsubscribed) -> none; in_state_change(from, out, subscribe) -> none; in_state_change(from, out, subscribed) -> {both, none}; in_state_change(from, out, unsubscribe) -> {none, out}; in_state_change(from, out, unsubscribed) -> {from, none}; in_state_change(both, none, subscribe) -> none; in_state_change(both, none, subscribed) -> none; in_state_change(both, none, unsubscribe) -> {to, none}; in_state_change(both, none, unsubscribed) -> {from, none}. out_state_change(none, none, subscribe) -> {none, out}; out_state_change(none, none, subscribed) -> none; out_state_change(none, none, unsubscribe) -> none; out_state_change(none, none, unsubscribed) -> none; out_state_change(none, out, subscribe) -> {none, out}; %% We need to resend query (RFC3921, section 9.2) out_state_change(none, out, subscribed) -> none; out_state_change(none, out, unsubscribe) -> {none, none}; out_state_change(none, out, unsubscribed) -> none; out_state_change(none, in, subscribe) -> {none, both}; out_state_change(none, in, subscribed) -> {from, none}; out_state_change(none, in, unsubscribe) -> none; out_state_change(none, in, unsubscribed) -> {none, none}; out_state_change(none, both, subscribe) -> none; out_state_change(none, both, subscribed) -> {from, out}; out_state_change(none, both, unsubscribe) -> {none, in}; out_state_change(none, both, unsubscribed) -> {none, out}; out_state_change(to, none, subscribe) -> none; out_state_change(to, none, subscribed) -> {both, none}; out_state_change(to, none, unsubscribe) -> {none, none}; out_state_change(to, none, unsubscribed) -> none; out_state_change(to, in, subscribe) -> none; out_state_change(to, in, subscribed) -> {both, none}; out_state_change(to, in, unsubscribe) -> {none, in}; out_state_change(to, in, unsubscribed) -> {to, none}; out_state_change(from, none, subscribe) -> {from, out}; out_state_change(from, none, subscribed) -> none; out_state_change(from, none, unsubscribe) -> none; out_state_change(from, none, unsubscribed) -> {none, none}; out_state_change(from, out, subscribe) -> none; out_state_change(from, out, subscribed) -> none; out_state_change(from, out, unsubscribe) -> {from, none}; out_state_change(from, out, unsubscribed) -> {none, out}; out_state_change(both, none, subscribe) -> none; out_state_change(both, none, subscribed) -> none; out_state_change(both, none, unsubscribe) -> {from, none}; out_state_change(both, none, unsubscribed) -> {to, none}. in_auto_reply(from, none, subscribe) -> subscribed; in_auto_reply(from, out, subscribe) -> subscribed; in_auto_reply(both, none, subscribe) -> subscribed; in_auto_reply(none, in, unsubscribe) -> unsubscribed; in_auto_reply(none, both, unsubscribe) -> unsubscribed; in_auto_reply(to, in, unsubscribe) -> unsubscribed; in_auto_reply(from, none, unsubscribe) -> unsubscribed; in_auto_reply(from, out, unsubscribe) -> unsubscribed; in_auto_reply(both, none, unsubscribe) -> unsubscribed; in_auto_reply(_, _, _) -> none. remove_user(User, 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)). remove_user(LUser, LServer, mnesia) -> US = {LUser, LServer}, F = fun () -> lists:foreach(fun (R) -> mnesia:delete_object(R) end, mnesia:index_read(roster, US, #roster.us)) end, mnesia:transaction(F); remove_user(LUser, LServer, odbc) -> Username = ejabberd_odbc:escape(LUser), odbc_queries:del_user_roster_t(LServer, Username), ok; remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete_by_index(roster, <<"us">>, {LUser, LServer})}. %% For each contact with Subscription: %% Both or From, send a "unsubscribed" presence stanza; %% Both or To, send a "unsubscribe" presence stanza. send_unsubscription_to_rosteritems(LUser, LServer) -> RosterItems = get_user_roster([], {LUser, LServer}), From = jid:make({LUser, LServer, <<"">>}), lists:foreach(fun (RosterItem) -> send_unsubscribing_presence(From, RosterItem) end, RosterItems). send_unsubscribing_presence(From, Item) -> IsTo = case Item#roster.subscription of both -> true; to -> true; _ -> false end, IsFrom = case Item#roster.subscription of both -> true; from -> true; _ -> false end, if IsTo -> send_presence_type(jid:remove_resource(From), jid:make(Item#roster.jid), <<"unsubscribe">>); true -> ok end, if IsFrom -> send_presence_type(jid:remove_resource(From), jid:make(Item#roster.jid), <<"unsubscribed">>); true -> ok end, ok. send_presence_type(From, To, Type) -> ejabberd_router:route(From, To, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, Type}], children = []}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_items(User, Server, SubEl) -> #xmlel{children = Els} = SubEl, LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), F = fun () -> lists:foreach(fun (El) -> process_item_set_t(LUser, LServer, El) end, Els) end, transaction(LServer, F). update_roster_t(LUser, LServer, LJID, Item) -> DBType = gen_mod:db_type(LServer, ?MODULE), update_roster_t(LUser, LServer, LJID, Item, DBType). 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, ItemGroups); update_roster_t(LUser, LServer, _LJID, Item, riak) -> ejabberd_riak:put(Item, roster_schema(), [{'2i', [{<<"us">>, {LUser, LServer}}]}]). del_roster_t(LUser, LServer, LJID) -> DBType = gen_mod:db_type(LServer, ?MODULE), del_roster_t(LUser, LServer, LJID, DBType). 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); 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 = jid:from_string(xml:get_attr_s(<<"jid">>, Attrs)), case JID1 of error -> ok; _ -> JID = {JID1#jid.user, JID1#jid.server, JID1#jid.resource}, LJID = {JID1#jid.luser, JID1#jid.lserver, JID1#jid.lresource}, Item = #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = JID}, Item1 = process_item_attrs_ws(Item, Attrs), Item2 = process_item_els(Item1, Els), case Item2#roster.subscription of remove -> del_roster_t(LUser, LServer, LJID); _ -> update_roster_t(LUser, LServer, LJID, Item2) end end; process_item_set_t(_LUser, _LServer, _) -> ok. process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) -> case Attr of <<"jid">> -> case jid:from_string(Val) of error -> process_item_attrs_ws(Item, Attrs); JID1 -> JID = {JID1#jid.luser, JID1#jid.lserver, JID1#jid.lresource}, process_item_attrs_ws(Item#roster{jid = JID}, Attrs) end; <<"name">> -> process_item_attrs_ws(Item#roster{name = Val}, Attrs); <<"subscription">> -> case Val of <<"remove">> -> process_item_attrs_ws(Item#roster{subscription = remove}, Attrs); <<"none">> -> process_item_attrs_ws(Item#roster{subscription = none}, Attrs); <<"both">> -> process_item_attrs_ws(Item#roster{subscription = both}, Attrs); <<"from">> -> process_item_attrs_ws(Item#roster{subscription = from}, Attrs); <<"to">> -> process_item_attrs_ws(Item#roster{subscription = to}, Attrs); _ -> process_item_attrs_ws(Item, Attrs) end; <<"ask">> -> process_item_attrs_ws(Item, Attrs); _ -> process_item_attrs_ws(Item, Attrs) end; process_item_attrs_ws(Item, []) -> Item. get_in_pending_subscriptions(Ls, User, 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 = jid:make(User, Server, <<"">>), Result = get_roster(JID#jid.luser, JID#jid.lserver, DBType), Ls ++ lists:map(fun (R) -> Message = R#roster.askmessage, Status = if is_binary(Message) -> (Message); true -> <<"">> end, #xmlel{name = <<"presence">>, attrs = [{<<"from">>, jid:to_string(R#roster.jid)}, {<<"to">>, jid:to_string(JID)}, {<<"type">>, <<"subscribe">>}], children = [#xmlel{name = <<"status">>, attrs = [], children = [{xmlcdata, Status}]}]} end, lists:filter(fun (R) -> case R#roster.ask of in -> true; both -> true; _ -> false end end, Result)); 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) -> Ls ++ lists:map(fun (R) -> Message = R#roster.askmessage, #xmlel{name = <<"presence">>, attrs = [{<<"from">>, jid:to_string(R#roster.jid)}, {<<"to">>, jid:to_string(JID)}, {<<"type">>, <<"subscribe">>}], children = [#xmlel{name = <<"status">>, attrs = [], children = [{xmlcdata, Message}]}]} end, lists:flatmap(fun (I) -> case raw_to_record(LServer, I) of %% Bad JID in database: error -> []; R -> case R#roster.ask of in -> [R]; both -> [R]; _ -> [] end end end, Items)); _ -> Ls end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% read_subscription_and_groups(User, Server, LJID) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), read_subscription_and_groups(LUser, LServer, LJID, gen_mod:db_type(LServer, ?MODULE)). read_subscription_and_groups(LUser, LServer, LJID, mnesia) -> case catch mnesia:dirty_read(roster, {LUser, LServer, LJID}) of [#roster{subscription = Subscription, groups = Groups}] -> {Subscription, Groups}; _ -> error 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]]} -> Subscription = case SSubscription of <<"B">> -> both; <<"T">> -> to; <<"F">> -> from; _ -> none end, Groups = case catch odbc_queries:get_rostergroup_by_jid(LServer, Username, SJID) of {selected, [<<"grp">>], JGrps} when is_list(JGrps) -> [JGrp || [JGrp] <- JGrps]; _ -> [] end, {Subscription, Groups}; _ -> error end; read_subscription_and_groups(LUser, LServer, LJID, riak) -> case ejabberd_riak:get(roster, roster_schema(), {LUser, LServer, LJID}) of {ok, #roster{subscription = Subscription, groups = Groups}} -> {Subscription, Groups}; _ -> error end. get_jid_info(_, User, Server, JID) -> LJID = jid:tolower(JID), case read_subscription_and_groups(User, Server, LJID) of {Subscription, Groups} -> {Subscription, Groups}; error -> LRJID = jid:tolower(jid:remove_resource(JID)), if LRJID == LJID -> {none, []}; true -> case read_subscription_and_groups(User, Server, LRJID) of {Subscription, Groups} -> {Subscription, Groups}; error -> {none, []} end end end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% raw_to_record(LServer, [User, SJID, Nick, SSubscription, SAsk, SAskMessage, _SServer, _SSubscribe, _SType]) -> case jid:from_string(SJID) of error -> error; JID -> LJID = jid:tolower(JID), Subscription = case SSubscription of <<"B">> -> both; <<"T">> -> to; <<"F">> -> from; _ -> none end, Ask = case SAsk of <<"S">> -> subscribe; <<"U">> -> unsubscribe; <<"B">> -> both; <<"O">> -> out; <<"I">> -> in; _ -> none end, #roster{usj = {User, LServer, LJID}, us = {User, LServer}, jid = LJID, name = Nick, subscription = Subscription, ask = Ask, askmessage = SAskMessage} end. record_to_string(#roster{us = {User, _Server}, jid = JID, name = Name, subscription = Subscription, ask = Ask, askmessage = AskMessage}) -> Username = ejabberd_odbc:escape(User), SJID = ejabberd_odbc:escape(jid:to_string(jid:tolower(JID))), Nick = ejabberd_odbc:escape(Name), 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, SAskMessage = ejabberd_odbc:escape(AskMessage), [Username, SJID, Nick, SSubscription, SAsk, SAskMessage, <<"N">>, <<"">>, <<"item">>]. groups_to_string(#roster{us = {User, _Server}, jid = JID, groups = Groups}) -> Username = ejabberd_odbc:escape(User), SJID = ejabberd_odbc:escape(jid:to_string(jid:tolower(JID))), lists:foldl(fun (<<"">>, Acc) -> Acc; (Group, Acc) -> G = ejabberd_odbc:escape(Group), [[Username, SJID, G] | Acc] end, [], Groups). update_tables() -> update_roster_table(), update_roster_version_table(). update_roster_table() -> Fields = record_info(fields, roster), case mnesia:table_info(roster, attributes) of Fields -> ejabberd_config:convert_table_to_binary( roster, Fields, set, fun(#roster{usj = {U, _, _}}) -> U end, fun(#roster{usj = {U, S, {LU, LS, LR}}, us = {U1, S1}, jid = {U2, S2, R2}, name = Name, groups = Gs, askmessage = Ask, xs = Xs} = R) -> R#roster{usj = {iolist_to_binary(U), iolist_to_binary(S), {iolist_to_binary(LU), iolist_to_binary(LS), iolist_to_binary(LR)}}, us = {iolist_to_binary(U1), iolist_to_binary(S1)}, jid = {iolist_to_binary(U2), iolist_to_binary(S2), iolist_to_binary(R2)}, name = iolist_to_binary(Name), groups = [iolist_to_binary(G) || G <- Gs], askmessage = try iolist_to_binary(Ask) catch _:_ -> <<"">> end, xs = [xml:to_xmlel(X) || X <- Xs]} end); _ -> ?INFO_MSG("Recreating roster table", []), mnesia:transform_table(roster, ignore, Fields) end. %% Convert roster table to support virtual host %% Convert roster table: xattrs fields become update_roster_version_table() -> Fields = record_info(fields, roster_version), case mnesia:table_info(roster_version, attributes) of Fields -> ejabberd_config:convert_table_to_binary( roster_version, Fields, set, fun(#roster_version{us = {U, _}}) -> U end, fun(#roster_version{us = {U, S}, version = Ver} = R) -> R#roster_version{us = {iolist_to_binary(U), iolist_to_binary(S)}, version = iolist_to_binary(Ver)} end); _ -> ?INFO_MSG("Recreating roster_version table", []), mnesia:transform_table(roster_version, ignore, Fields) end. webadmin_page(_, Host, #request{us = _US, path = [<<"user">>, U, <<"roster">>], q = Query, lang = Lang} = _Request) -> Res = user_roster(U, Host, Query, Lang), {stop, Res}; webadmin_page(Acc, _, _) -> Acc. user_roster(User, Server, Query, Lang) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), US = {LUser, LServer}, Items1 = get_roster(LUser, LServer), Res = user_roster_parse_query(User, Server, Items1, Query), Items = get_roster(LUser, LServer), SItems = lists:sort(Items), FItems = case SItems of [] -> [?CT(<<"None">>)]; _ -> [?XE(<<"table">>, [?XE(<<"thead">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Jabber ID">>), ?XCT(<<"td">>, <<"Nickname">>), ?XCT(<<"td">>, <<"Subscription">>), ?XCT(<<"td">>, <<"Pending">>), ?XCT(<<"td">>, <<"Groups">>)])]), ?XE(<<"tbody">>, (lists:map(fun (R) -> Groups = lists:flatmap(fun (Group) -> [?C(Group), ?BR] end, R#roster.groups), Pending = ask_to_pending(R#roster.ask), TDJID = build_contact_jid_td(R#roster.jid), ?XE(<<"tr">>, [TDJID, ?XAC(<<"td">>, [{<<"class">>, <<"valign">>}], (R#roster.name)), ?XAC(<<"td">>, [{<<"class">>, <<"valign">>}], (iolist_to_binary(atom_to_list(R#roster.subscription)))), ?XAC(<<"td">>, [{<<"class">>, <<"valign">>}], (iolist_to_binary(atom_to_list(Pending)))), ?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], Groups), if Pending == in -> ?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], [?INPUTT(<<"submit">>, <<"validate", (ejabberd_web_admin:term_to_id(R#roster.jid))/binary>>, <<"Validate">>)]); true -> ?X(<<"td">>) end, ?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], [?INPUTT(<<"submit">>, <<"remove", (ejabberd_web_admin:term_to_id(R#roster.jid))/binary>>, <<"Remove">>)])]) end, SItems)))])] end, [?XC(<<"h1">>, (<<(?T(<<"Roster of ">>))/binary, (us_to_list(US))/binary>>))] ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], (FItems ++ [?P, ?INPUT(<<"text">>, <<"newjid">>, <<"">>), ?C(<<" ">>), ?INPUTT(<<"submit">>, <<"addjid">>, <<"Add Jabber ID">>)]))]. build_contact_jid_td(RosterJID) -> ContactJID = jid:make(RosterJID), JIDURI = case {ContactJID#jid.luser, ContactJID#jid.lserver} of {<<"">>, _} -> <<"">>; {CUser, CServer} -> case lists:member(CServer, ?MYHOSTS) of false -> <<"">>; true -> <<"/admin/server/", CServer/binary, "/user/", CUser/binary, "/">> end end, case JIDURI of <<>> -> ?XAC(<<"td">>, [{<<"class">>, <<"valign">>}], (jid:to_string(RosterJID))); URI when is_binary(URI) -> ?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], [?AC(JIDURI, (jid:to_string(RosterJID)))]) end. user_roster_parse_query(User, Server, Items, Query) -> case lists:keysearch(<<"addjid">>, 1, Query) of {value, _} -> case lists:keysearch(<<"newjid">>, 1, Query) of {value, {_, SJID}} -> case jid:from_string(SJID) of JID when is_record(JID, jid) -> user_roster_subscribe_jid(User, Server, JID), ok; error -> error end; false -> error end; false -> case catch user_roster_item_parse_query(User, Server, Items, Query) of submitted -> ok; {'EXIT', _Reason} -> error; _ -> nothing end end. user_roster_subscribe_jid(User, Server, JID) -> out_subscription(User, Server, JID, subscribe), UJID = jid:make(User, Server, <<"">>), ejabberd_router:route(UJID, JID, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"subscribe">>}], children = []}). user_roster_item_parse_query(User, Server, Items, Query) -> lists:foreach(fun (R) -> JID = R#roster.jid, case lists:keysearch(<<"validate", (ejabberd_web_admin:term_to_id(JID))/binary>>, 1, Query) of {value, _} -> JID1 = jid:make(JID), out_subscription(User, Server, JID1, subscribed), UJID = jid:make(User, Server, <<"">>), ejabberd_router:route(UJID, JID1, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"subscribed">>}], children = []}), throw(submitted); false -> case lists:keysearch(<<"remove", (ejabberd_web_admin:term_to_id(JID))/binary>>, 1, Query) of {value, _} -> UJID = jid:make(User, Server, <<"">>), process_iq_set(UJID, UJID, #iq{type = set, sub_el = #xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_ROSTER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string(JID)}, {<<"subscription">>, <<"remove">>}], children = []}]}}), throw(submitted); false -> ok end end end, Items), nothing. us_to_list({User, Server}) -> jid:to_string({User, Server, <<"">>}). webadmin_user(Acc, _User, _Server, Lang) -> Acc ++ [?XE(<<"h3">>, [?ACT(<<"roster/">>, <<"Roster">>)])]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Implement XEP-0321 Remote Roster Management process_iq_manager(From, To, IQ) -> %% Check what access is allowed for From to To MatchDomain = From#jid.lserver, case is_domain_managed(MatchDomain, To#jid.lserver) of true -> process_iq_manager2(MatchDomain, To, IQ); false -> #iq{sub_el = SubEl} = IQ, IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end. process_iq_manager2(MatchDomain, To, IQ) -> %% If IQ is SET, filter the input IQ IQFiltered = maybe_filter_request(MatchDomain, IQ), %% Call the standard function with reversed JIDs IdInitial = IQFiltered#iq.id, ResIQ = process_iq(To, To, IQFiltered#iq{id = <<"roster-remotely-managed">>}), %% Filter the output IQ filter_stanza(MatchDomain, ResIQ#iq{id = IdInitial}). is_domain_managed(ContactHost, UserHost) -> Managers = gen_mod:get_module_opt(UserHost, ?MODULE, managers, fun(B) when is_list(B) -> B end, []), lists:member(ContactHost, Managers). maybe_filter_request(MatchDomain, IQ) when IQ#iq.type == set -> filter_stanza(MatchDomain, IQ); maybe_filter_request(_MatchDomain, IQ) -> IQ. filter_stanza(_MatchDomain, #iq{sub_el = []} = IQ) -> IQ; filter_stanza(MatchDomain, #iq{sub_el = [SubEl | _]} = IQ) -> #iq{sub_el = SubElFiltered} = IQRes = filter_stanza(MatchDomain, IQ#iq{sub_el = SubEl}), IQRes#iq{sub_el = [SubElFiltered]}; filter_stanza(MatchDomain, #iq{sub_el = SubEl} = IQ) -> #xmlel{name = Type, attrs = Attrs, children = Items} = SubEl, ItemsFiltered = lists:filter( fun(Item) -> is_item_of_domain(MatchDomain, Item) end, Items), SubElFiltered = #xmlel{name=Type, attrs = Attrs, children = ItemsFiltered}, IQ#iq{sub_el = SubElFiltered}. is_item_of_domain(MatchDomain, #xmlel{} = El) -> lists:any(fun(Attr) -> is_jid_of_domain(MatchDomain, Attr) end, El#xmlel.attrs); is_item_of_domain(_MatchDomain, {xmlcdata, _}) -> false. is_jid_of_domain(MatchDomain, {<<"jid">>, JIDString}) -> case jid:from_string(JIDString) of JID when JID#jid.lserver == MatchDomain -> true; _ -> false end; is_jid_of_domain(_, _) -> false. process_item_attrs_managed(Item, Attrs, true) -> process_item_attrs_ws(Item, Attrs); process_item_attrs_managed(Item, _Attrs, false) -> process_item_attrs(Item, _Attrs). send_itemset_to_managers(_From, _Item, true) -> ok; send_itemset_to_managers(From, Item, false) -> {_, UserHost} = Item#roster.us, {_ContactUser, ContactHost, _ContactResource} = Item#roster.jid, %% Check if the component is an allowed manager IsManager = is_domain_managed(ContactHost, UserHost), case IsManager of true -> push_item(<<"">>, ContactHost, <<"">>, From, Item); false -> ok end. is_managed_from_id(<<"roster-remotely-managed">>) -> true; is_managed_from_id(_Id) -> false. roster_schema() -> {record_info(fields, roster), #roster{}}. roster_version_schema() -> {record_info(fields, roster_version), #roster_version{}}. export(_Server) -> [{roster, fun(Host, #roster{usj = {LUser, LServer, LJID}} = R) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), 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, ItemVals, ItemGroups); (_Host, _R) -> [] end}, {roster_version, fun(Host, #roster_version{us = {LUser, LServer}, version = Ver}) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), SVer = ejabberd_odbc:escape(Ver), [[<<"delete from roster_version where username='">>, Username, <<"';">>], [<<"insert into roster_version(username, version) values('">>, Username, <<"', '">>, SVer, <<"');">>]]; (_Host, _R) -> [] end}]. import(LServer) -> [{<<"select username, jid, nick, subscription, " "ask, askmessage, server, subscribe, type from rosterusers;">>, fun([LUser, JID|_] = Row) -> Item = raw_to_record(LServer, Row), Username = ejabberd_odbc:escape(LUser), SJID = ejabberd_odbc:escape(JID), {selected, _, Rows} = ejabberd_odbc:sql_query_t( [<<"select grp from rostergroups where username='">>, Username, <<"' and jid='">>, SJID, <<"'">>]), Groups = [Grp || [Grp] <- Rows], Item#roster{groups = Groups} end}, {<<"select username, version from roster_version;">>, fun([LUser, Ver]) -> #roster_version{us = {LUser, LServer}, version = Ver} end}]. import(_LServer, mnesia, #roster{} = R) -> mnesia:dirty_write(R); import(_LServer, mnesia, #roster_version{} = RV) -> mnesia:dirty_write(RV); import(_LServer, riak, #roster{us = {LUser, LServer}} = R) -> ejabberd_riak:put(R, roster_schema(), [{'2i', [{<<"us">>, {LUser, LServer}}]}]); 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]. ejabberd-16.01/src/ejabberd_auth.erl0000644000232200023220000003730512645157216017720 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_auth.erl %%% Author : Alexey Shchepin %%% Purpose : Authentification %%% Created : 23 Nov 2002 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. %%% %%%---------------------------------------------------------------------- %% TODO: Use the functions in ejabberd auth to add and remove users. -module(ejabberd_auth). -behaviour(ejabberd_config). -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, 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, get_vh_registered_users_number/2, get_password/2, get_password_s/2, get_password_with_authmodule/2, is_user_exists/2, is_user_exists_in_other_modules/3, remove_user/2, remove_user/3, plain_password_required/1, store_type/1, entropy/1]). -export([auth_modules/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- -type opts() :: [{prefix, binary()} | {from, integer()} | {to, integer()} | {limit, integer()} | {offset, integer()}]. -callback start(binary()) -> any(). -callback plain_password_required() -> boolean(). -callback store_type() -> plain | external | scram. -callback set_password(binary(), binary(), binary()) -> ok | {error, atom()}. -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(), fun((binary()) -> binary())) -> boolean(). -callback try_register(binary(), binary(), binary()) -> {atomic, atom()} | {error, atom()}. -callback dirty_get_registered_users() -> [{binary(), binary()}]. -callback get_vh_registered_users(binary()) -> [{binary(), binary()}]. -callback get_vh_registered_users(binary(), opts()) -> [{binary(), binary()}]. -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() | {binary(), binary(), binary(), integer()}. start() -> %% 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)) end, ?MYHOSTS). plain_password_required(Server) -> lists:any(fun (M) -> M:plain_password_required() end, auth_modules(Server)). store_type(Server) -> %% @doc Check if the user and password can login in server. %% @spec (User::string(), Server::string(), Password::string()) -> %% true | false lists:foldl(fun (_, external) -> external; (M, scram) -> case M:store_type() of external -> external; _Else -> scram end; (M, plain) -> M:store_type() end, plain, auth_modules(Server)). -spec check_password(binary(), binary(), binary()) -> boolean(). check_password(User, Server, Password) -> case check_password_with_authmodule(User, Server, Password) of {true, _AuthModule} -> true; false -> false end. %% @doc Check if the user and password can login in server. %% @spec (User::string(), Server::string(), Password::string(), %% Digest::string(), DigestGen::function()) -> %% true | false -spec check_password(binary(), binary(), binary(), binary(), fun((binary()) -> binary())) -> boolean(). check_password(User, Server, Password, Digest, DigestGen) -> case check_password_with_authmodule(User, Server, Password, Digest, DigestGen) of {true, _AuthModule} -> true; false -> false end. %% @doc Check if the user and password can login in server. %% 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()) -> %% {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 | {true, atom()}. check_password_with_authmodule(User, Server, Password) -> check_password_loop(auth_modules(Server), [User, Server, Password]). -spec check_password_with_authmodule(binary(), binary(), binary(), binary(), fun((binary()) -> binary())) -> false | {true, atom()}. check_password_with_authmodule(User, Server, Password, Digest, DigestGen) -> check_password_loop(auth_modules(Server), [User, Server, Password, Digest, DigestGen]). check_password_loop([], _Args) -> false; check_password_loop([AuthModule | AuthModules], Args) -> case apply(AuthModule, check_password, Args) of true -> {true, AuthModule}; false -> check_password_loop(AuthModules, Args) end. -spec set_password(binary(), binary(), binary()) -> ok | {error, atom()}. %% @spec (User::string(), Server::string(), Password::string()) -> %% ok | {error, ErrorType} %% where ErrorType = empty_password | not_allowed | invalid_jid set_password(_User, _Server, <<"">>) -> {error, empty_password}; set_password(User, Server, Password) -> %% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, not_allowed} lists:foldl(fun (M, {error, _}) -> M:set_password(User, Server, Password); (_M, Res) -> Res end, {error, not_allowed}, auth_modules(Server)). -spec try_register(binary(), binary(), binary()) -> {atomic, atom()} | {error, atom()}. try_register(_User, _Server, <<"">>) -> {error, not_allowed}; try_register(User, Server, Password) -> case is_user_exists(User, Server) of true -> {atomic, exists}; false -> LServer = jid:nameprep(Server), case lists:member(LServer, ?MYHOSTS) of true -> Res = lists:foldl(fun (_M, {atomic, ok} = Res) -> Res; (M, _) -> M:try_register(User, Server, Password) end, {error, not_allowed}, auth_modules(Server)), case Res of {atomic, ok} -> ejabberd_hooks:run(register_user, Server, [User, Server]), {atomic, ok}; _ -> Res end; false -> {error, not_allowed} end end. %% Registered users list do not include anonymous users logged -spec dirty_get_registered_users() -> [{binary(), binary()}]. dirty_get_registered_users() -> lists:flatmap(fun (M) -> M:dirty_get_registered_users() end, auth_modules()). -spec get_vh_registered_users(binary()) -> [{binary(), binary()}]. %% Registered users list do not include anonymous users logged get_vh_registered_users(Server) -> lists:flatmap(fun (M) -> M:get_vh_registered_users(Server) end, auth_modules(Server)). -spec get_vh_registered_users(binary(), opts()) -> [{binary(), binary()}]. get_vh_registered_users(Server, Opts) -> lists:flatmap(fun (M) -> case erlang:function_exported(M, get_vh_registered_users, 2) of true -> M:get_vh_registered_users(Server, Opts); false -> M:get_vh_registered_users(Server) end end, auth_modules(Server)). get_vh_registered_users_number(Server) -> lists:sum(lists:map(fun (M) -> case erlang:function_exported(M, get_vh_registered_users_number, 1) of true -> M:get_vh_registered_users_number(Server); false -> length(M:get_vh_registered_users(Server)) end end, auth_modules(Server))). -spec get_vh_registered_users_number(binary(), opts()) -> number(). get_vh_registered_users_number(Server, Opts) -> %% @doc Get the password of the user. %% @spec (User::string(), Server::string()) -> Password::string() lists:sum(lists:map(fun (M) -> case erlang:function_exported(M, get_vh_registered_users_number, 2) of true -> M:get_vh_registered_users_number(Server, Opts); false -> length(M:get_vh_registered_users(Server)) end end, auth_modules(Server))). -spec get_password(binary(), binary()) -> false | binary() | {binary(), binary(), binary(), integer()}. get_password(User, Server) -> lists:foldl(fun (M, false) -> M:get_password(User, Server); (_M, Password) -> Password end, false, auth_modules(Server)). -spec get_password_s(binary(), binary()) -> binary() | {binary(), binary(), binary(), integer()}. get_password_s(User, Server) -> case get_password(User, Server) of false -> <<"">>; Password -> Password end. %% @doc Get the password of the user and the auth module. %% @spec (User::string(), Server::string()) -> %% {Password::string(), AuthModule::atom()} | {false, none} -spec get_password_with_authmodule(binary(), binary()) -> {false | binary(), atom()}. get_password_with_authmodule(User, Server) -> %% Returns true if the user exists in the DB or if an anonymous user is logged %% under the given name lists:foldl(fun (M, {false, _}) -> {M:get_password(User, Server), M}; (_M, {Password, AuthModule}) -> {Password, AuthModule} end, {false, none}, auth_modules(Server)). -spec is_user_exists(binary(), binary()) -> boolean(). is_user_exists(_User, <<"">>) -> false; is_user_exists(User, Server) -> %% Check if the user exists in all authentications module except the module %% passed as parameter %% @spec (Module::atom(), User, Server) -> true | false | maybe lists:any(fun (M) -> case M:is_user_exists(User, Server) of {error, Error} -> ?ERROR_MSG("The authentication module ~p returned " "an error~nwhen checking user ~p in server " "~p~nError message: ~p", [M, User, Server, Error]), false; Else -> Else end end, auth_modules(Server)). -spec is_user_exists_in_other_modules(atom(), binary(), binary()) -> boolean() | maybe. is_user_exists_in_other_modules(Module, User, Server) -> is_user_exists_in_other_modules_loop(auth_modules(Server) -- [Module], User, Server). is_user_exists_in_other_modules_loop([], _User, _Server) -> false; is_user_exists_in_other_modules_loop([AuthModule | AuthModules], User, Server) -> case AuthModule:is_user_exists(User, Server) of true -> true; false -> is_user_exists_in_other_modules_loop(AuthModules, User, Server); {error, Error} -> ?DEBUG("The authentication module ~p returned " "an error~nwhen checking user ~p in server " "~p~nError message: ~p", [AuthModule, User, Server, Error]), maybe end. -spec remove_user(binary(), binary()) -> ok. %% @spec (User, Server) -> ok %% @doc Remove user. %% Note: it may return ok even if there was some problem removing the user. remove_user(User, Server) -> lists:foreach(fun (M) -> M:remove_user(User, Server) end, auth_modules(Server)), ejabberd_hooks:run(remove_user, jid:nameprep(Server), [User, Server]), ok. %% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error %% @doc Try to remove user if the provided password is correct. %% The removal is attempted in each auth method provided: %% when one returns 'ok' the loop stops; %% if no method returns 'ok' then it returns the error message indicated by the last method attempted. -spec remove_user(binary(), binary(), binary()) -> any(). remove_user(User, Server, Password) -> R = lists:foldl(fun (_M, ok = Res) -> Res; (M, _) -> M:remove_user(User, Server, Password) end, error, auth_modules(Server)), case R of ok -> ejabberd_hooks:run(remove_user, jid:nameprep(Server), [User, Server]); _ -> none end, R. %% @spec (IOList) -> non_negative_float() %% @doc Calculate informational entropy. entropy(B) -> case binary_to_list(B) of "" -> 0.0; S -> Set = lists:foldl(fun (C, [Digit, Printable, LowLetter, HiLetter, Other]) -> if C >= $a, C =< $z -> [Digit, Printable, 26, HiLetter, Other]; C >= $0, C =< $9 -> [9, Printable, LowLetter, HiLetter, Other]; C >= $A, C =< $Z -> [Digit, Printable, LowLetter, 26, Other]; C >= 33, C =< 126 -> [Digit, 33, LowLetter, HiLetter, Other]; true -> [Digit, Printable, LowLetter, HiLetter, 128] end end, [0, 0, 0, 0, 0], S), length(S) * math:log(lists:sum(Set)) / math:log(2) end. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- %% Return the lists of all the auth modules actually used in the %% configuration auth_modules() -> lists:usort(lists:flatmap(fun (Server) -> auth_modules(Server) end, ?MYHOSTS)). -spec auth_modules(binary()) -> [atom()]. %% Return the list of authenticated modules for a given host auth_modules(Server) -> LServer = jid:nameprep(Server), Default = case gen_mod:default_db(LServer) of mnesia -> internal; DBType -> DBType end, Methods = ejabberd_config:get_option( {auth_method, LServer}, fun(V) when is_list(V) -> true = lists:all(fun is_atom/1, V), V; (V) when is_atom(V) -> [V] end, [Default]), [jlib:binary_to_atom(<<"ejabberd_auth_", (jlib:atom_to_binary(M))/binary>>) || M <- Methods]. export(Server) -> ejabberd_auth_internal:export(Server). import(Server) -> ejabberd_auth_internal:import(Server). import(Server, mnesia, Passwd) -> ejabberd_auth_internal:import(Server, mnesia, Passwd); 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]. ejabberd-16.01/src/translate.erl0000644000232200023220000001301612645157216017127 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : translate.erl %%% Author : Alexey Shchepin %%% Purpose : Localization helper %%% Created : 6 Jan 2003 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(translate). -author('alexey@process-one.net'). -export([start/0, load_dir/1, load_file/2, translate/2]). -include("ejabberd.hrl"). -include("logger.hrl"). start() -> ets:new(translations, [named_table, public]), Dir = case os:getenv("EJABBERD_MSGS_PATH") of false -> case code:priv_dir(ejabberd) of {error, _} -> ?MSGS_DIR; Path -> filename:join([Path, "msgs"]) end; Path -> Path end, load_dir(iolist_to_binary(Dir)), ok. -spec load_dir(binary()) -> ok. load_dir(Dir) -> case file:list_dir(Dir) of {ok, Files} -> MsgFiles = lists:filter(fun (FN) -> case length(FN) > 4 of true -> string:substr(FN, length(FN) - 3) == ".msg"; _ -> false end end, Files), lists:foreach(fun (FNS) -> FN = list_to_binary(FNS), LP = ascii_tolower(str:substr(FN, 1, byte_size(FN) - 4)), L = case str:tokens(LP, <<".">>) of [Language] -> Language; [Language, _Project] -> Language end, load_file(L, <>) end, MsgFiles), ok; {error, Reason} -> ?ERROR_MSG("~p", [Reason]) end. load_file(Lang, File) -> case file:open(File, [read]) of {ok, Fd} -> io:setopts(Fd, [{encoding,latin1}]), load_file_loop(Fd, 1, File, Lang), file:close(Fd); {error, Error} -> ExitText = iolist_to_binary([File, ": ", file:format_error(Error)]), ?ERROR_MSG("Problem loading translation file ~n~s", [ExitText]), exit(ExitText) end. load_file_loop(Fd, Line, File, Lang) -> case io:read(Fd, '', Line) of {ok,{Orig, Trans}, NextLine} -> Trans1 = case Trans of <<"">> -> Orig; _ -> Trans end, ets:insert(translations, {{Lang, iolist_to_binary(Orig)}, iolist_to_binary(Trans1)}), load_file_loop(Fd, NextLine, File, Lang); {ok,_, _NextLine} -> ExitText = iolist_to_binary([File, " approximately in the line ", Line]), ?ERROR_MSG("Problem loading translation file ~n~s", [ExitText]), exit(ExitText); {error, {_LineNumber, erl_parse, _ParseMessage} = Reason} -> ExitText = iolist_to_binary([File, " approximately in the line ", file:format_error(Reason)]), ?ERROR_MSG("Problem loading translation file ~n~s", [ExitText]), exit(ExitText); {error, Reason} -> ExitText = iolist_to_binary([File, ": ", file:format_error(Reason)]), ?ERROR_MSG("Problem loading translation file ~n~s", [ExitText]), exit(ExitText); {eof,_Line} -> ok end. -spec translate(binary(), binary()) -> binary(). translate(Lang, Msg) -> LLang = ascii_tolower(Lang), case ets:lookup(translations, {LLang, Msg}) of [{_, Trans}] -> Trans; _ -> ShortLang = case str:tokens(LLang, <<"-">>) of [] -> LLang; [SL | _] -> SL end, case ShortLang of <<"en">> -> Msg; LLang -> translate(Msg); _ -> case ets:lookup(translations, {ShortLang, Msg}) of [{_, Trans}] -> Trans; _ -> translate(Msg) end end end. translate(Msg) -> case ?MYLANG of <<"en">> -> Msg; Lang -> LLang = ascii_tolower(Lang), case ets:lookup(translations, {LLang, Msg}) of [{_, Trans}] -> Trans; _ -> ShortLang = case str:tokens(LLang, <<"-">>) of [] -> LLang; [SL | _] -> SL end, case ShortLang of <<"en">> -> Msg; Lang -> Msg; _ -> case ets:lookup(translations, {ShortLang, Msg}) of [{_, Trans}] -> Trans; _ -> Msg end end end end. ascii_tolower(B) -> iolist_to_binary(ascii_tolower_s(binary_to_list(B))). ascii_tolower_s([C | Cs]) when C >= $A, C =< $Z -> [C + ($a - $A) | ascii_tolower_s(Cs)]; ascii_tolower_s([C | Cs]) -> [C | ascii_tolower_s(Cs)]; ascii_tolower_s([]) -> []. ejabberd-16.01/src/ejabberd_regexp.erl0000644000232200023220000000626212645157216020247 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_regexp.erl %%% Author : Badlop %%% Purpose : Frontend to Re and Regexp OTP modules %%% Created : 8 Dec 2011 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_regexp). -compile([export_all]). exec({ReM, ReF, ReA}, {RgM, RgF, RgA}) -> try apply(ReM, ReF, ReA) catch error:undef -> apply(RgM, RgF, RgA); A:B -> {error, {A, B}} end. -spec run(binary(), binary()) -> match | nomatch | {error, any()}. run(String, Regexp) -> case exec({re, run, [String, Regexp, [{capture, none}]]}, {regexp, first_match, [binary_to_list(String), binary_to_list(Regexp)]}) of {match, _, _} -> match; {match, _} -> match; match -> match; nomatch -> nomatch; {error, Error} -> {error, Error} end. -spec split(binary(), binary()) -> [binary()]. split(String, Regexp) -> case exec({re, split, [String, Regexp, [{return, binary}]]}, {regexp, split, [binary_to_list(String), binary_to_list(Regexp)]}) of {ok, FieldList} -> [iolist_to_binary(F) || F <- FieldList]; {error, Error} -> throw(Error); A -> A end. -spec replace(binary(), binary(), binary()) -> binary(). replace(String, Regexp, New) -> case exec({re, replace, [String, Regexp, New, [{return, binary}]]}, {regexp, sub, [binary_to_list(String), binary_to_list(Regexp), binary_to_list(New)]}) of {ok, NewString, _RepCount} -> iolist_to_binary(NewString); {error, Error} -> throw(Error); A -> A end. -spec greplace(binary(), binary(), binary()) -> binary(). greplace(String, Regexp, New) -> case exec({re, replace, [String, Regexp, New, [global, {return, binary}]]}, {regexp, sub, [binary_to_list(String), binary_to_list(Regexp), binary_to_list(New)]}) of {ok, NewString, _RepCount} -> iolist_to_binary(NewString); {error, Error} -> throw(Error); A -> A end. -spec sh_to_awk(binary()) -> binary(). sh_to_awk(ShRegExp) -> case exec({xmerl_regexp, sh_to_awk, [binary_to_list(ShRegExp)]}, {regexp, sh_to_awk, [binary_to_list(ShRegExp)]}) of A -> iolist_to_binary(A) end. ejabberd-16.01/src/win32_dns.erl0000644000232200023220000001065712645157216016750 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : win32_dns.erl %%% Author : Geoff Cant %%% Purpose : Get name servers in a Windows machine %%% Created : 5 Mar 2009 by Geoff Cant %%% %%% %%% 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(win32_dns). -export([get_nameservers/0]). -include("ejabberd.hrl"). -include("logger.hrl"). -define(IF_KEY, "\\hklm\\system\\CurrentControlSet\\Services\\TcpIp\\Parameters\\Interfaces"). -define(TOP_KEY, "\\hklm\\system\\CurrentControlSet\\Services\\TcpIp\\Parameters"). get_nameservers() -> {_, Config} = pick_config(), IPTs = get_value(["NameServer"], Config), lists:filter(fun(IPTuple) -> is_good_ns(IPTuple) end, IPTs). is_good_ns(Addr) -> element(1, inet_res:nnslookup("a.root-servers.net", in, any, [{Addr,53}], timer:seconds(5) ) ) =:= ok. reg() -> {ok, R} = win32reg:open([read]), R. interfaces(R) -> ok = win32reg:change_key(R, ?IF_KEY), {ok, I} = win32reg:sub_keys(R), I. config_keys(R, Key) -> ok = win32reg:change_key(R, Key), [ {K, case win32reg:value(R, K) of {ok, V} -> try_translate(K, V); _ -> undefined end } || K <- ["Domain", "DhcpDomain", "NameServer", "DhcpNameServer", "SearchList"]]. try_translate(K, V) -> try translate(K, V) of Res -> Res catch A:B -> ?ERROR_MSG("Error '~p' translating Win32 registry~n" "K: ~p~nV: ~p~nError: ~p", [A, K, V, B]), undefined end. translate(NS, V) when NS =:= "NameServer"; NS =:= "DhcpNameServer" -> %% The IPs may be separated by commas ',' or by spaces " " %% The parts of an IP are separated by dots '.' IPsStrings = [string:tokens(IP, ".") || IP <- string:tokens(V, " ,")], [ list_to_tuple([list_to_integer(String) || String <- IpStrings]) || IpStrings <- IPsStrings]; translate(_, V) -> V. interface_configs(R) -> [{If, config_keys(R, ?IF_KEY ++ "\\" ++ If)} || If <- interfaces(R)]. sort_configs(Configs) -> lists:sort(fun ({_, A}, {_, B}) -> ANS = proplists:get_value("NameServer", A), BNS = proplists:get_value("NameServer", B), if ANS =/= undefined, BNS =:= undefined -> false; true -> count_undef(A) < count_undef(B) end end, Configs). count_undef(L) when is_list(L) -> lists:foldl(fun ({_K, undefined}, Acc) -> Acc +1; ({_K, []}, Acc) -> Acc +1; (_, Acc) -> Acc end, 0, L). all_configs() -> R = reg(), TopConfig = config_keys(R, ?TOP_KEY), Configs = [{top, TopConfig} | interface_configs(R)], win32reg:close(R), {TopConfig, Configs}. pick_config() -> {TopConfig, Configs} = all_configs(), NSConfigs = [{If, C} || {If, C} <- Configs, get_value(["DhcpNameServer","NameServer"], C) =/= undefined], case get_value(["DhcpNameServer","NameServer"], TopConfig) of %% No top level nameserver to pick interface with undefined -> hd(sort_configs(NSConfigs)); %% Top level has a nameserver - use this to select an interface. NS -> Cs = [ {If, C} || {If, C} <- Configs, lists:member(NS, [get_value(["NameServer"], C), get_value(["DhcpNameServer"], C)])], hd(sort_configs(Cs)) end. get_value([], _Config) -> undefined; get_value([K|Keys], Config) -> case proplists:get_value(K, Config) of undefined -> get_value(Keys, Config); V -> V end. ejabberd-16.01/src/mod_proxy65_service.erl0000644000232200023220000002265312645157216021054 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_proxy65_service.erl %%% Author : Evgeniy Khramtsov %%% Purpose : SOCKS5 Bytestreams XMPP service. %%% Created : 12 Oct 2006 by Evgeniy 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(mod_proxy65_service). -author('xram@jabber.ru'). -behaviour(gen_server). %% gen_server callbacks. -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -export([start_link/2, add_listener/2, transform_module_options/1, delete_listener/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -define(PROCNAME, ejabberd_mod_proxy65_service). -record(state, {myhost = <<"">> :: binary(), serverhost = <<"">> :: binary(), name = <<"">> :: binary(), stream_addr = [] :: [attr()], port = 0 :: inet:port_number(), ip = {127,0,0,1} :: inet:ip_address(), acl = none :: atom()}). %%%------------------------ %%% gen_server callbacks %%%------------------------ start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). init([Host, Opts]) -> State = parse_options(Host, Opts), ejabberd_router:register_route(State#state.myhost), {ok, State}. terminate(_Reason, #state{myhost = MyHost}) -> ejabberd_router:unregister_route(MyHost), ok. handle_info({route, From, To, #xmlel{name = <<"iq">>} = Packet}, State) -> IQ = jlib:iq_query_info(Packet), case catch process_iq(From, IQ, State) of Result when is_record(Result, iq) -> ejabberd_router:route(To, From, jlib:iq_to_xml(Result)); {'EXIT', Reason} -> ?ERROR_MSG("Error when processing IQ stanza: ~p", [Reason]), Err = jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR), ejabberd_router:route(To, From, Err); _ -> ok end, {noreply, State}; handle_info(_Info, State) -> {noreply, State}. handle_call(get_port_ip, _From, State) -> {reply, {port_ip, State#state.port, State#state.ip}, State}; handle_call(_Request, _From, State) -> {reply, ok, State}. handle_cast(_Request, State) -> {noreply, State}. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%%------------------------ %%% Listener management %%%------------------------ add_listener(Host, Opts) -> State = parse_options(Host, Opts), NewOpts = [Host | Opts], ejabberd_listener:add_listener({State#state.port, State#state.ip}, mod_proxy65_stream, NewOpts). delete_listener(Host) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), {port_ip, Port, IP} = gen_server:call(Proc, get_port_ip), catch ejabberd_listener:delete_listener({Port, IP}, mod_proxy65_stream). %%%------------------------ %%% IQ Processing %%%------------------------ %% disco#info request process_iq(_, #iq{type = get, xmlns = ?NS_DISCO_INFO, lang = Lang} = IQ, #state{name = Name, serverhost = ServerHost}) -> Info = ejabberd_hooks:run_fold(disco_info, ServerHost, [], [ServerHost, ?MODULE, <<"">>, <<"">>]), IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_INFO}], children = iq_disco_info(Lang, Name) ++ Info}]}; %% disco#items request process_iq(_, #iq{type = get, xmlns = ?NS_DISCO_ITEMS} = IQ, _) -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_ITEMS}], children = []}]}; %% vCard request process_iq(_, #iq{type = get, xmlns = ?NS_VCARD, lang = Lang} = IQ, _) -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"vCard">>, attrs = [{<<"xmlns">>, ?NS_VCARD}], children = iq_vcard(Lang)}]}; %% bytestreams info request process_iq(JID, #iq{type = get, sub_el = SubEl, xmlns = ?NS_BYTESTREAMS} = IQ, #state{acl = ACL, stream_addr = StreamAddr, serverhost = ServerHost}) -> case acl:match_rule(ServerHost, ACL, JID) of allow -> StreamHostEl = [#xmlel{name = <<"streamhost">>, attrs = StreamAddr, children = []}], IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_BYTESTREAMS}], children = StreamHostEl}]}; deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} end; %% bytestream activation request process_iq(InitiatorJID, #iq{type = set, sub_el = SubEl, xmlns = ?NS_BYTESTREAMS} = IQ, #state{acl = ACL, serverhost = ServerHost}) -> case acl:match_rule(ServerHost, ACL, InitiatorJID) of allow -> ActivateEl = xml:get_path_s(SubEl, [{elem, <<"activate">>}]), SID = xml:get_tag_attr_s(<<"sid">>, SubEl), case catch jid:from_string(xml:get_tag_cdata(ActivateEl)) of TargetJID when is_record(TargetJID, jid), SID /= <<"">>, byte_size(SID) =< 128, TargetJID /= InitiatorJID -> Target = jid:to_string(jid:tolower(TargetJID)), Initiator = jid:to_string(jid:tolower(InitiatorJID)), SHA1 = p1_sha:sha(<>), case mod_proxy65_sm:activate_stream(SHA1, InitiatorJID, TargetJID, ServerHost) of ok -> IQ#iq{type = result, sub_el = []}; false -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}; limit -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_RESOURCE_CONSTRAINT]}; conflict -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_CONFLICT]}; _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} end; _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end; deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} end; %% Unknown "set" or "get" request process_iq(_, #iq{type = Type, sub_el = SubEl} = IQ, _) when Type == get; Type == set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; %% IQ "result" or "error". process_iq(_, _, _) -> ok. %%%------------------------- %%% Auxiliary functions. %%%------------------------- -define(FEATURE(Feat), #xmlel{name = <<"feature">>, attrs = [{<<"var">>, Feat}], children = []}). iq_disco_info(Lang, Name) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"proxy">>}, {<<"type">>, <<"bytestreams">>}, {<<"name">>, translate:translate(Lang, Name)}], children = []}, ?FEATURE((?NS_DISCO_INFO)), ?FEATURE((?NS_VCARD)), ?FEATURE((?NS_BYTESTREAMS))]. iq_vcard(Lang) -> [#xmlel{name = <<"FN">>, attrs = [], children = [{xmlcdata, <<"ejabberd/mod_proxy65">>}]}, #xmlel{name = <<"URL">>, attrs = [], children = [{xmlcdata, ?EJABBERD_URI}]}, #xmlel{name = <<"DESC">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd SOCKS5 Bytestreams module">>))/binary, "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. parse_options(ServerHost, Opts) -> MyHost = gen_mod:get_opt_host(ServerHost, Opts, <<"proxy.@HOST@">>), Port = gen_mod:get_opt(port, Opts, fun(P) when is_integer(P), P>0, P<65536 -> P end, 7777), ACL = gen_mod:get_opt(access, Opts, fun(A) when is_atom(A) -> A end, all), Name = gen_mod:get_opt(name, Opts, fun iolist_to_binary/1, <<"SOCKS5 Bytestreams">>), IP = gen_mod:get_opt(ip, Opts, fun(S) -> {ok, Addr} = inet_parse:address( binary_to_list( iolist_to_binary(S))), Addr end, get_my_ip()), HostName = gen_mod:get_opt(hostname, Opts, fun iolist_to_binary/1, jlib:ip_to_list(IP)), StreamAddr = [{<<"jid">>, MyHost}, {<<"host">>, HostName}, {<<"port">>, jlib:integer_to_binary(Port)}], #state{myhost = MyHost, serverhost = ServerHost, name = Name, port = Port, ip = IP, stream_addr = StreamAddr, acl = ACL}. transform_module_options(Opts) -> lists:map( fun({ip, IP}) when is_tuple(IP) -> {ip, jlib:ip_to_list(IP)}; ({hostname, IP}) when is_tuple(IP) -> {hostname, jlib:ip_to_list(IP)}; (Opt) -> Opt end, Opts). get_my_ip() -> {ok, MyHostName} = inet:gethostname(), case inet:getaddr(MyHostName, inet) of {ok, Addr} -> Addr; {error, _} -> {127, 0, 0, 1} end. ejabberd-16.01/src/ejabberd_receiver.erl0000644000232200023220000002564512645157216020567 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_receiver.erl %%% Author : Alexey Shchepin %%% Purpose : Socket receiver for C2S and S2S connections %%% Created : 10 Nov 2003 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_receiver). -author('alexey@process-one.net'). -behaviour(gen_server). %% API -export([start_link/4, start/3, start/4, change_shaper/2, reset_stream/1, starttls/2, compress/2, become_controller/2, close/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("ejabberd.hrl"). -include("logger.hrl"). -record(state, {socket :: inet:socket() | p1_tls:tls_socket() | ezlib:zlib_socket(), sock_mod = gen_tcp :: gen_tcp | p1_tls | ezlib, shaper_state = none :: shaper:shaper(), c2s_pid :: pid(), max_stanza_size = infinity :: non_neg_integer() | infinity, xml_stream_state :: xml_stream:xml_stream_state(), timeout = infinity:: timeout()}). -define(HIBERNATE_TIMEOUT, 90000). -spec start_link(inet:socket(), atom(), shaper:shaper(), non_neg_integer() | infinity) -> ignore | {error, any()} | {ok, pid()}. start_link(Socket, SockMod, Shaper, MaxStanzaSize) -> gen_server:start_link(?MODULE, [Socket, SockMod, Shaper, MaxStanzaSize], []). -spec start(inet:socket(), atom(), shaper:shaper()) -> undefined | pid(). start(Socket, SockMod, Shaper) -> start(Socket, SockMod, Shaper, infinity). -spec start(inet:socket(), atom(), shaper:shaper(), non_neg_integer() | infinity) -> undefined | pid(). start(Socket, SockMod, Shaper, MaxStanzaSize) -> {ok, Pid} = gen_server:start(ejabberd_receiver, [Socket, SockMod, Shaper, MaxStanzaSize], []), Pid. -spec change_shaper(pid(), shaper:shaper()) -> ok. change_shaper(Pid, Shaper) -> gen_server:cast(Pid, {change_shaper, Shaper}). -spec reset_stream(pid()) -> ok | {error, any()}. reset_stream(Pid) -> do_call(Pid, reset_stream). -spec starttls(pid(), p1_tls:tls_socket()) -> ok. starttls(Pid, TLSSocket) -> do_call(Pid, {starttls, TLSSocket}). -spec compress(pid(), iodata() | undefined) -> {error, any()} | {ok, ezlib:zlib_socket()}. compress(Pid, Data) -> do_call(Pid, {compress, Data}). -spec become_controller(pid(), pid()) -> ok | {error, any()}. become_controller(Pid, C2SPid) -> do_call(Pid, {become_controller, C2SPid}). -spec close(pid()) -> ok. close(Pid) -> gen_server:cast(Pid, close). %%==================================================================== %% gen_server callbacks %%==================================================================== init([Socket, SockMod, Shaper, MaxStanzaSize]) -> ShaperState = shaper:new(Shaper), Timeout = case SockMod of ssl -> 20; _ -> infinity end, {ok, #state{socket = Socket, sock_mod = SockMod, shaper_state = ShaperState, max_stanza_size = MaxStanzaSize, timeout = Timeout}}. 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 {ok, TLSData} -> {reply, ok, process_data(TLSData, NewState), ?HIBERNATE_TIMEOUT}; {error, _Reason} -> {stop, normal, ok, NewState} end; handle_call({compress, Data}, _From, #state{socket = Socket, sock_mod = SockMod} = State) -> {ok, ZlibSocket} = ezlib:enable_zlib(SockMod, Socket), if Data /= undefined -> do_send(State, Data); true -> ok end, State1 = reset_parser(State), NewState = State1#state{socket = ZlibSocket, sock_mod = ezlib}, case ezlib:recv_data(ZlibSocket, <<"">>) of {ok, ZlibData} -> {reply, {ok, ZlibSocket}, process_data(ZlibData, NewState), ?HIBERNATE_TIMEOUT}; {error, _Reason} -> {stop, normal, ok, NewState} end; handle_call(reset_stream, _From, State) -> NewState = reset_parser(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), NewState = State#state{c2s_pid = C2SPid, xml_stream_state = XMLStreamState}, activate_socket(NewState), Reply = ok, {reply, Reply, NewState, ?HIBERNATE_TIMEOUT}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State, ?HIBERNATE_TIMEOUT}. handle_cast({change_shaper, Shaper}, State) -> NewShaperState = shaper:new(Shaper), {noreply, State#state{shaper_state = NewShaperState}, ?HIBERNATE_TIMEOUT}; handle_cast(close, State) -> {stop, normal, State}; handle_cast(_Msg, State) -> {noreply, State, ?HIBERNATE_TIMEOUT}. handle_info({Tag, _TCPSocket, Data}, #state{socket = Socket, sock_mod = SockMod} = State) when (Tag == tcp) or (Tag == ssl) or (Tag == ejabberd_xml) -> case SockMod of p1_tls -> case p1_tls:recv_data(Socket, Data) of {ok, TLSData} -> {noreply, process_data(TLSData, State), ?HIBERNATE_TIMEOUT}; {error, Reason} -> if is_binary(Reason) -> ?DEBUG("TLS error = ~s", [Reason]); true -> ok end, {stop, normal, State} end; ezlib -> case ezlib:recv_data(Socket, Data) of {ok, ZlibData} -> {noreply, process_data(ZlibData, State), ?HIBERNATE_TIMEOUT}; {error, _Reason} -> {stop, normal, State} end; _ -> {noreply, process_data(Data, State), ?HIBERNATE_TIMEOUT} end; handle_info({Tag, _TCPSocket}, State) when (Tag == tcp_closed) or (Tag == ssl_closed) -> {stop, normal, State}; handle_info({Tag, _TCPSocket, Reason}, State) when (Tag == tcp_error) or (Tag == ssl_error) -> case Reason of timeout -> {noreply, State, ?HIBERNATE_TIMEOUT}; _ -> {stop, normal, State} end; handle_info({timeout, _Ref, activate}, State) -> activate_socket(State), {noreply, State, ?HIBERNATE_TIMEOUT}; handle_info(timeout, State) -> proc_lib:hibernate(gen_server, enter_loop, [?MODULE, [], State]), {noreply, State, ?HIBERNATE_TIMEOUT}; handle_info(_Info, State) -> {noreply, State, ?HIBERNATE_TIMEOUT}. terminate(_Reason, #state{xml_stream_state = XMLStreamState, c2s_pid = C2SPid} = State) -> close_stream(XMLStreamState), if C2SPid /= undefined -> gen_fsm:send_event(C2SPid, closed); true -> ok end, catch (State#state.sock_mod):close(State#state.socket), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- activate_socket(#state{socket = Socket, sock_mod = SockMod}) -> PeerName = case SockMod of gen_tcp -> inet:setopts(Socket, [{active, once}]), inet:peername(Socket); _ -> SockMod:setopts(Socket, [{active, once}]), SockMod:peername(Socket) end, case PeerName of {error, _Reason} -> self() ! {tcp_closed, Socket}; {ok, _} -> ok end. %% Data processing for connectors directly generating xmlelement in %% Erlang data structure. %% WARNING: Shaper does not work with Erlang data structure. process_data([], State) -> activate_socket(State), State; process_data([Element | Els], #state{c2s_pid = C2SPid} = State) when element(1, Element) == xmlel; element(1, Element) == xmlstreamstart; element(1, Element) == xmlstreamelement; element(1, Element) == xmlstreamend -> if C2SPid == undefined -> State; true -> catch gen_fsm:send_event(C2SPid, element_wrapper(Element)), process_data(Els, State) end; %% Data processing for connectors receivind data as string. process_data(Data, #state{xml_stream_state = XMLStreamState, shaper_state = ShaperState, c2s_pid = C2SPid} = State) -> ?DEBUG("Received XML on stream = ~p", [(Data)]), XMLStreamState1 = case XMLStreamState of undefined -> XMLStreamState; _ -> xml_stream:parse(XMLStreamState, Data) end, {NewShaperState, Pause} = shaper:update(ShaperState, byte_size(Data)), if C2SPid == undefined -> ok; Pause > 0 -> erlang:start_timer(Pause, self(), activate); true -> activate_socket(State) end, State#state{xml_stream_state = XMLStreamState1, shaper_state = NewShaperState}. %% Element coming from XML parser are wrapped inside xmlstreamelement %% When we receive directly xmlelement tuple (from a socket module %% speaking directly Erlang XML), we wrap it inside the same %% xmlstreamelement coming from the XML parser. element_wrapper(XMLElement) when element(1, XMLElement) == xmlel -> {xmlstreamelement, XMLElement}; element_wrapper(Element) -> Element. close_stream(undefined) -> ok; close_stream(XMLStreamState) -> xml_stream:close(XMLStreamState). reset_parser(#state{xml_stream_state = undefined} = State) -> State; reset_parser(#state{c2s_pid = C2SPid, max_stanza_size = MaxStanzaSize, xml_stream_state = XMLStreamState} = State) -> NewStreamState = try xml_stream:reset(XMLStreamState) catch error:_ -> close_stream(XMLStreamState), case C2SPid of undefined -> undefined; _ -> xml_stream:new(C2SPid, MaxStanzaSize) end end, State#state{xml_stream_state = NewStreamState}. do_send(State, Data) -> (State#state.sock_mod):send(State#state.socket, Data). do_call(Pid, Msg) -> case catch gen_server:call(Pid, Msg) of {'EXIT', Why} -> {error, Why}; Res -> Res end. ejabberd-16.01/src/ejabberd_idna.erl0000644000232200023220000001422212645157216017663 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_idna.erl %%% Author : Alexey Shchepin %%% Purpose : Support for IDNA (RFC3490) %%% Created : 10 Apr 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_idna). -author('alexey@process-one.net'). -export([domain_utf8_to_ascii/1, domain_ucs2_to_ascii/1, utf8_to_ucs2/1]). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. -spec domain_utf8_to_ascii(binary()) -> false | binary(). domain_utf8_to_ascii(Domain) -> domain_ucs2_to_ascii(utf8_to_ucs2(Domain)). utf8_to_ucs2(S) -> utf8_to_ucs2(binary_to_list(S), ""). utf8_to_ucs2([], R) -> lists:reverse(R); utf8_to_ucs2([C | S], R) when C < 128 -> utf8_to_ucs2(S, [C | R]); utf8_to_ucs2([C1, C2 | S], R) when C1 < 224 -> utf8_to_ucs2(S, [C1 band 31 bsl 6 bor C2 band 63 | R]); utf8_to_ucs2([C1, C2, C3 | S], R) when C1 < 240 -> utf8_to_ucs2(S, [C1 band 15 bsl 12 bor (C2 band 63 bsl 6) bor C3 band 63 | R]). -spec domain_ucs2_to_ascii(list()) -> false | binary(). domain_ucs2_to_ascii(Domain) -> case catch domain_ucs2_to_ascii1(Domain) of {'EXIT', _Reason} -> false; Res -> iolist_to_binary(Res) end. domain_ucs2_to_ascii1(Domain) -> Parts = string:tokens(Domain, [46, 12290, 65294, 65377]), ASCIIParts = lists:map(fun (P) -> to_ascii(P) end, Parts), string:strip(lists:flatmap(fun (P) -> [$. | P] end, ASCIIParts), left, $.). %% Domain names are already nameprep'ed in ejabberd, so we skiping this step to_ascii(Name) -> false = lists:any(fun (C) when (0 =< C) and (C =< 44) or (46 =< C) and (C =< 47) or (58 =< C) and (C =< 64) or (91 =< C) and (C =< 96) or (123 =< C) and (C =< 127) -> true; (_) -> false end, Name), case Name of [H | _] when H /= $- -> true = lists:last(Name) /= $- end, ASCIIName = case lists:any(fun (C) -> C > 127 end, Name) of true -> true = case Name of "xn--" ++ _ -> false; _ -> true end, "xn--" ++ punycode_encode(Name); false -> Name end, L = length(ASCIIName), true = (1 =< L) and (L =< 63), ASCIIName. %%% PUNYCODE (RFC3492) -define(BASE, 36). -define(TMIN, 1). -define(TMAX, 26). -define(SKEW, 38). -define(DAMP, 700). -define(INITIAL_BIAS, 72). -define(INITIAL_N, 128). punycode_encode(Input) -> N = (?INITIAL_N), Delta = 0, Bias = (?INITIAL_BIAS), Basic = lists:filter(fun (C) -> C =< 127 end, Input), NonBasic = lists:filter(fun (C) -> C > 127 end, Input), L = length(Input), B = length(Basic), SNonBasic = lists:usort(NonBasic), Output1 = if B > 0 -> Basic ++ "-"; true -> "" end, Output2 = punycode_encode1(Input, SNonBasic, B, B, L, N, Delta, Bias, ""), Output1 ++ Output2. punycode_encode1(Input, [M | SNonBasic], B, H, L, N, Delta, Bias, Out) when H < L -> Delta1 = Delta + (M - N) * (H + 1), % let n = m {NewDelta, NewBias, NewH, NewOut} = lists:foldl(fun (C, {ADelta, ABias, AH, AOut}) -> if C < M -> {ADelta + 1, ABias, AH, AOut}; C == M -> NewOut = punycode_encode_delta(ADelta, ABias, AOut), NewBias = adapt(ADelta, H + 1, H == B), {0, NewBias, AH + 1, NewOut}; true -> {ADelta, ABias, AH, AOut} end end, {Delta1, Bias, H, Out}, Input), punycode_encode1(Input, SNonBasic, B, NewH, L, M + 1, NewDelta + 1, NewBias, NewOut); punycode_encode1(_Input, _SNonBasic, _B, _H, _L, _N, _Delta, _Bias, Out) -> lists:reverse(Out). punycode_encode_delta(Delta, Bias, Out) -> punycode_encode_delta(Delta, Bias, Out, ?BASE). punycode_encode_delta(Delta, Bias, Out, K) -> T = if K =< Bias -> ?TMIN; K >= Bias + (?TMAX) -> ?TMAX; true -> K - Bias end, if Delta < T -> [codepoint(Delta) | Out]; true -> C = T + (Delta - T) rem ((?BASE) - T), punycode_encode_delta((Delta - T) div ((?BASE) - T), Bias, [codepoint(C) | Out], K + (?BASE)) end. adapt(Delta, NumPoints, FirstTime) -> Delta1 = if FirstTime -> Delta div (?DAMP); true -> Delta div 2 end, Delta2 = Delta1 + Delta1 div NumPoints, adapt1(Delta2, 0). adapt1(Delta, K) -> if Delta > ((?BASE) - (?TMIN)) * (?TMAX) div 2 -> adapt1(Delta div ((?BASE) - (?TMIN)), K + (?BASE)); true -> K + ((?BASE) - (?TMIN) + 1) * Delta div (Delta + (?SKEW)) end. codepoint(C) -> if (0 =< C) and (C =< 25) -> C + 97; (26 =< C) and (C =< 35) -> C + 22 end. %%%=================================================================== %%% Unit tests %%%=================================================================== -ifdef(TEST). acsii_test() -> ?assertEqual(<<"test.org">>, domain_utf8_to_ascii(<<"test.org">>)). utf8_test() -> ?assertEqual( <<"xn--d1acufc.xn--p1ai">>, domain_utf8_to_ascii( <<208,180,208,190,208,188,208,181,208,189,46,209,128,209,132>>)). -endif. ejabberd-16.01/src/cyrsasl.erl0000644000232200023220000001613712645157216016621 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : cyrsasl.erl %%% Author : Alexey Shchepin %%% Purpose : Cyrus SASL-like library %%% Created : 8 Mar 2003 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). -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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). %% -export_type([ mechanism/0, mechanisms/0, sasl_mechanism/0 ]). -record(sasl_mechanism, {mechanism = <<"">> :: mechanism() | '$1', module :: atom(), password_type = plain :: password_type() | '$2'}). -type(mechanism() :: binary()). -type(mechanisms() :: [mechanism(),...]). -type(password_type() :: plain | digest | scram). -type(props() :: [{username, binary()} | {authzid, binary()} | {auth_module, atom()}]). -type(sasl_mechanism() :: #sasl_mechanism{}). -record(sasl_state, { service, myname, realm, get_password, check_password, check_password_digest, mech_mod, mech_state }). -callback mech_new(binary(), fun(), fun(), fun()) -> any(). -callback mech_step(any(), binary()) -> {ok, props()} | {ok, props(), binary()} | {continue, binary(), any()} | {error, binary()} | {error, binary(), binary()}. start() -> ets:new(sasl_mechanism, [named_table, public, {keypos, #sasl_mechanism.mechanism}]), cyrsasl_plain:start([]), cyrsasl_digest:start([]), cyrsasl_scram:start([]), cyrsasl_anonymous:start([]), cyrsasl_oauth:start([]), ok. %% -spec(register_mechanism/3 :: ( Mechanim :: mechanism(), Module :: module(), PasswordType :: password_type()) -> any() ). register_mechanism(Mechanism, Module, PasswordType) -> case is_disabled(Mechanism) of false -> ets:insert(sasl_mechanism, #sasl_mechanism{mechanism = Mechanism, module = Module, password_type = PasswordType}); true -> ?DEBUG("SASL mechanism ~p is disabled", [Mechanism]), true end. %%% TODO: use callbacks %%-include("ejabberd.hrl"). %%-include("jlib.hrl"). %%check_authzid(_State, Props) -> %% AuthzId = xml: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)), %% {U, S, R} = jid:tolower(JID), %% case R of %% "" -> %% {error, "invalid-authzid"}; %% _ -> %% case {LUser, ?MYNAME} of %% {U, S} -> %% ok; %% _ -> %% {error, "invalid-authzid"} %% end %% end %% end. check_credentials(_State, Props) -> User = proplists:get_value(username, Props, <<>>), case jid:nodeprep(User) of error -> {error, <<"not-authorized">>}; <<"">> -> {error, <<"not-authorized">>}; _LUser -> ok end. -spec(listmech/1 :: ( Host ::binary()) -> Mechanisms::mechanisms() ). listmech(Host) -> Mechs = ets:select(sasl_mechanism, [{#sasl_mechanism{mechanism = '$1', password_type = '$2', _ = '_'}, case catch ejabberd_auth:store_type(Host) of external -> [{'==', '$2', plain}]; scram -> [{'/=', '$2', digest}]; {'EXIT', {undef, [{Module, store_type, []} | _]}} -> ?WARNING_MSG("~p doesn't implement the function store_type/0", [Module]), []; _Else -> [] end, ['$1']}]), filter_anonymous(Host, Mechs). server_new(Service, ServerFQDN, UserRealm, _SecFlags, GetPassword, CheckPassword, CheckPasswordDigest) -> #sasl_state{service = Service, myname = ServerFQDN, realm = UserRealm, get_password = GetPassword, check_password = CheckPassword, check_password_digest = CheckPasswordDigest}. server_start(State, Mech, ClientIn) -> case lists:member(Mech, listmech(State#sasl_state.myname)) of true -> case ets:lookup(sasl_mechanism, Mech) of [#sasl_mechanism{module = Module}] -> {ok, MechState} = Module:mech_new(State#sasl_state.myname, State#sasl_state.get_password, State#sasl_state.check_password, State#sasl_state.check_password_digest), server_step(State#sasl_state{mech_mod = Module, mech_state = MechState}, ClientIn); _ -> {error, <<"no-mechanism">>} end; false -> {error, <<"no-mechanism">>} end. server_step(State, ClientIn) -> Module = State#sasl_state.mech_mod, MechState = State#sasl_state.mech_state, case Module:mech_step(MechState, ClientIn) of {ok, Props} -> case check_credentials(State, Props) of ok -> {ok, Props}; {error, Error} -> {error, Error} end; {ok, Props, ServerOut} -> case check_credentials(State, Props) of ok -> {ok, Props, ServerOut}; {error, Error} -> {error, Error} end; {continue, ServerOut, NewMechState} -> {continue, ServerOut, State#sasl_state{mech_state = NewMechState}}; {error, Error, Username} -> {error, Error, Username}; {error, Error} -> {error, Error} end. %% Remove the anonymous mechanism from the list if not enabled for the given %% host %% -spec(filter_anonymous/2 :: ( Host :: binary(), Mechs :: mechanisms()) -> mechanisms() ). filter_anonymous(Host, Mechs) -> case ejabberd_auth_anonymous:is_sasl_anonymous_enabled(Host) of true -> Mechs; false -> Mechs -- [<<"ANONYMOUS">>] end. -spec(is_disabled/1 :: ( Mechanism :: mechanism()) -> boolean() ). is_disabled(Mechanism) -> Disabled = ejabberd_config:get_option( 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, []), 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]. ejabberd-16.01/src/jlib.erl0000644000232200023220000006603412645157216016062 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : jlib.erl %%% Author : Alexey Shchepin %%% Purpose : General XMPP library. %%% Created : 23 Nov 2002 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(jlib). -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]}). -export([make_result_iq_reply/1, make_error_reply/3, 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, 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, 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, datetime_string_to_timestamp/1, term_to_base64/1, base64_to_term/1, decode_base64/1, encode_base64/1, ip_to_list/1, rsm_encode/1, rsm_encode/2, rsm_decode/1, binary_to_integer/1, binary_to_integer/2, integer_to_binary/1, integer_to_binary/2, atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1, l2i/1, i2l/1, i2l/2, queue_drop_while/2]). %% 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]). -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"). %send_iq(From, To, ID, SubTags) -> % ok. -spec make_result_iq_reply(xmlel()) -> xmlel(). make_result_iq_reply(#xmlel{name = Name, attrs = Attrs, children = SubTags}) -> NewAttrs = make_result_iq_reply_attrs(Attrs), #xmlel{name = Name, attrs = NewAttrs, children = SubTags}. -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), Attrs1 = lists:keydelete(<<"to">>, 1, Attrs), Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1), Attrs3 = case To of {value, ToVal} -> [{<<"from">>, ToVal} | Attrs2]; _ -> Attrs2 end, Attrs4 = case From of {value, FromVal} -> [{<<"to">>, FromVal} | Attrs3]; _ -> Attrs3 end, Attrs5 = lists:keydelete(<<"type">>, 1, Attrs4), Attrs6 = [{<<"type">>, <<"result">>} | Attrs5], Attrs6. -spec make_error_reply(xmlel(), binary(), binary()) -> xmlel(). make_error_reply(#xmlel{name = Name, attrs = Attrs, children = SubTags}, Code, Desc) -> NewAttrs = make_error_reply_attrs(Attrs), #xmlel{name = Name, attrs = NewAttrs, children = SubTags ++ [#xmlel{name = <<"error">>, attrs = [{<<"code">>, Code}], children = [{xmlcdata, Desc}]}]}. -spec make_error_reply(xmlel(), xmlel()) -> xmlel(). make_error_reply(#xmlel{name = Name, attrs = Attrs, children = SubTags}, Error) -> NewAttrs = make_error_reply_attrs(Attrs), #xmlel{name = Name, attrs = NewAttrs, children = SubTags ++ [Error]}. -spec make_error_reply_attrs([attr()]) -> [attr()]. make_error_reply_attrs(Attrs) -> To = xml:get_attr(<<"to">>, Attrs), From = xml:get_attr(<<"from">>, Attrs), Attrs1 = lists:keydelete(<<"to">>, 1, Attrs), Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1), Attrs3 = case To of {value, ToVal} -> [{<<"from">>, ToVal} | Attrs2]; _ -> Attrs2 end, Attrs4 = case From of {value, FromVal} -> [{<<"to">>, FromVal} | Attrs3]; _ -> Attrs3 end, Attrs5 = lists:keydelete(<<"type">>, 1, Attrs4), Attrs6 = [{<<"type">>, <<"error">>} | Attrs5], Attrs6. -spec make_error_element(binary(), binary()) -> xmlel(). make_error_element(Code, Desc) -> #xmlel{name = <<"error">>, attrs = [{<<"code">>, Code}], children = [{xmlcdata, Desc}]}. -spec make_correct_from_to_attrs(binary(), binary(), [attr()]) -> [attr()]. make_correct_from_to_attrs(From, To, Attrs) -> Attrs1 = lists:keydelete(<<"from">>, 1, Attrs), Attrs2 = case xml:get_attr(<<"to">>, Attrs) of {value, _} -> Attrs1; _ -> [{<<"to">>, To} | Attrs1] end, Attrs3 = [{<<"from">>, From} | Attrs2], Attrs3. -spec replace_from_to_attrs(binary(), binary(), [attr()]) -> [attr()]. replace_from_to_attrs(From, To, Attrs) -> Attrs1 = lists:keydelete(<<"to">>, 1, Attrs), Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1), Attrs3 = [{<<"to">>, To} | Attrs2], Attrs4 = [{<<"from">>, From} | Attrs3], Attrs4. -spec replace_from_to(jid(), jid(), xmlel()) -> xmlel(). replace_from_to(From, To, #xmlel{name = Name, attrs = Attrs, children = Els}) -> NewAttrs = 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()]. replace_from_attrs(From, Attrs) -> Attrs1 = lists:keydelete(<<"from">>, 1, Attrs), [{<<"from">>, From} | Attrs1]. -spec replace_from(jid(), xmlel()) -> xmlel(). replace_from(From, #xmlel{name = Name, attrs = Attrs, children = Els}) -> NewAttrs = replace_from_attrs(jid:to_string(From), Attrs), #xmlel{name = Name, attrs = NewAttrs, children = Els}. -spec remove_attr(binary(), xmlel()) -> xmlel(). remove_attr(Attr, #xmlel{name = Name, attrs = Attrs, children = Els}) -> NewAttrs = lists:keydelete(Attr, 1, Attrs), #xmlel{name = Name, attrs = NewAttrs, children = Els}. -spec make_jid(binary(), binary(), binary()) -> jid() | error. make_jid(User, Server, Resource) -> jid:make(User, Server, Resource). -spec make_jid({binary(), binary(), binary()}) -> jid() | error. 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(J) -> jid:split(J). -spec string_to_jid(binary()) -> jid() | error. string_to_jid(S) -> jid:from_string(S). -spec jid_to_string(jid() | ljid()) -> binary(). jid_to_string(J) -> jid:to_string(J). -spec is_nodename(binary()) -> boolean(). is_nodename(Node) -> jid:is_nodename(Node). %tolower_c(C) when C >= $A, C =< $Z -> % C + 32; %tolower_c(C) -> % C. -define(LOWER(Char), if Char >= $A, Char =< $Z -> Char + 32; true -> Char end). %tolower(S) -> % lists:map(fun tolower_c/1, S). %tolower(S) -> % [?LOWER(Char) || Char <- S]. -spec tolower(binary()) -> binary(). tolower(B) -> iolist_to_binary(tolower_s(binary_to_list(B))). tolower_s([C | Cs]) -> if C >= $A, C =< $Z -> [C + 32 | tolower_s(Cs)]; true -> [C | tolower_s(Cs)] end; tolower_s([]) -> []. %tolower([C | Cs]) when C >= $A, C =< $Z -> % [C + 32 | tolower(Cs)]; %tolower([C | Cs]) -> % [C | tolower(Cs)]; %tolower([]) -> % []. -spec nodeprep(binary()) -> binary() | error. nodeprep(S) -> jid:nodeprep(S). -spec nameprep(binary()) -> binary() | error. nameprep(S) -> jid:nameprep(S). -spec resourceprep(binary()) -> binary() | error. resourceprep(S) -> jid:resourceprep(S). -spec jid_tolower(jid() | ljid()) -> error | ljid(). jid_tolower(J) -> jid:tolower(J). -spec jid_remove_resource(jid()) -> jid(); (ljid()) -> ljid(). jid_remove_resource(J) -> jid:remove_resource(J). -spec jid_replace_resource(jid(), binary()) -> error | jid(). jid_replace_resource(JID, Resource) -> 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); _ -> <<"">> end; get_iq_namespace(_) -> <<"">>. %% -spec(iq_query_info/1 :: ( Xmlel :: xmlel()) -> iq_request() | 'reply' | 'invalid' | 'not_iq' ). %% @spec (xmlelement()) -> iq() | reply | invalid | not_iq iq_query_info(El) -> iq_info_internal(El, request). %% -spec(iq_query_or_response_info/1 :: ( Xmlel :: xmlel()) -> iq_request() | iq_reply() | 'reply' | 'invalid' | 'not_iq' ). 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 <<"set">> -> {set, request}; <<"get">> -> {get, request}; <<"result">> -> {result, reply}; <<"error">> -> {error, reply}; _ -> {invalid, invalid} end, if Type == invalid -> invalid; Class == request; Filter == any -> FilteredEls = xml:remove_cdata(Els), {XMLNS, SubEl} = case {Class, FilteredEls} of {request, [#xmlel{attrs = Attrs2}]} -> {xml: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); _ -> <<"">> end, FilteredEls}; _ -> {<<"">>, []} end, if XMLNS == <<"">>, Class == request -> invalid; true -> #iq{id = ID, type = Type, xmlns = XMLNS, lang = Lang, sub_el = SubEl} end; Class == reply, Filter /= any -> reply end; iq_info_internal(_, _) -> not_iq. -spec is_iq_request_type(set | get | result | error) -> boolean(). is_iq_request_type(set) -> true; is_iq_request_type(get) -> true; is_iq_request_type(_) -> false. iq_type_to_string(set) -> <<"set">>; iq_type_to_string(get) -> <<"get">>; iq_type_to_string(result) -> <<"result">>; iq_type_to_string(error) -> <<"error">>. -spec(iq_to_xml/1 :: ( IQ :: iq()) -> xmlel() ). iq_to_xml(#iq{id = ID, type = Type, sub_el = SubEl}) -> if ID /= <<"">> -> #xmlel{name = <<"iq">>, attrs = [{<<"id">>, ID}, {<<"type">>, iq_type_to_string(Type)}], children = SubEl}; true -> #xmlel{name = <<"iq">>, attrs = [{<<"type">>, iq_type_to_string(Type)}], children = SubEl} end. -spec(parse_xdata_submit/1 :: ( El :: xmlel()) -> [{Var::binary(), Values::[binary()]}] %% | 'invalid' ). parse_xdata_submit(#xmlel{attrs = Attrs, children = Els}) -> case xml:get_attr_s(<<"type">>, Attrs) of <<"submit">> -> lists:reverse(parse_xdata_fields(Els, [])); <<"form">> -> %% This is a workaround to accept Psi's wrong forms lists:reverse(parse_xdata_fields(Els, [])); _ -> invalid end. -spec(parse_xdata_fields/2 :: ( Xmlels :: [xmlel() | cdata()], Res :: [{Var::binary(), Values :: [binary()]}]) -> [{Var::binary(), Values::[binary()]}] ). 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 <<>> -> parse_xdata_fields(Els, Res); Var -> Field = {Var, lists:reverse(parse_xdata_values(SubEls, []))}, parse_xdata_fields(Els, [Field | Res]) end; parse_xdata_fields([_ | Els], Res) -> parse_xdata_fields(Els, Res). -spec(parse_xdata_values/2 :: ( Xmlels :: [xmlel() | cdata()], Res :: [binary()]) -> [binary()] ). parse_xdata_values([], Res) -> Res; parse_xdata_values([#xmlel{name = <<"value">>, children = SubEls} | Els], Res) -> Val = xml:get_cdata(SubEls), parse_xdata_values(Els, [Val | Res]); parse_xdata_values([_ | Els], Res) -> parse_xdata_values(Els, Res). -spec rsm_decode(iq() | xmlel()) -> none | rsm_in(). rsm_decode(#iq{sub_el = SubEl}) -> rsm_decode(SubEl); rsm_decode(#xmlel{} = SubEl) -> case xml:get_subtag(SubEl, <<"set">>) of false -> none; #xmlel{name = <<"set">>, children = SubEls} -> lists:foldl(fun rsm_parse_element/2, #rsm_in{}, SubEls) end. rsm_parse_element(#xmlel{name = <<"max">>, attrs = []} = Elem, RsmIn) -> CountStr = xml: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), RsmIn#rsm_in{direction = before, id = UID}; rsm_parse_element(#xmlel{name = <<"after">>, attrs = []} = Elem, RsmIn) -> UID = xml: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), {Index, _} = str:to_integer(IndexStr), RsmIn#rsm_in{index = Index}; rsm_parse_element(_, RsmIn) -> RsmIn. -spec rsm_encode(iq(), rsm_out()) -> iq(). rsm_encode(#iq{sub_el = SubEl} = IQ, RsmOut) -> Set = #xmlel{name = <<"set">>, attrs = [{<<"xmlns">>, ?NS_RSM}], children = lists:reverse(rsm_encode_out(RsmOut))}, #xmlel{name = Name, attrs = Attrs, children = SubEls} = SubEl, New = #xmlel{name = Name, attrs = Attrs, children = [Set | SubEls]}, IQ#iq{sub_el = New}. -spec rsm_encode(none | rsm_out()) -> [xmlel()]. rsm_encode(none) -> []; rsm_encode(RsmOut) -> [#xmlel{name = <<"set">>, attrs = [{<<"xmlns">>, ?NS_RSM}], children = lists:reverse(rsm_encode_out(RsmOut))}]. rsm_encode_out(#rsm_out{count = Count, index = Index, first = First, last = Last}) -> El = rsm_encode_first(First, Index, []), El2 = rsm_encode_last(Last, El), rsm_encode_count(Count, El2). rsm_encode_first(undefined, undefined, Arr) -> Arr; rsm_encode_first(First, undefined, Arr) -> [#xmlel{name = <<"first">>, attrs = [], children = [{xmlcdata, First}]} | Arr]; rsm_encode_first(First, Index, Arr) -> [#xmlel{name = <<"first">>, attrs = [{<<"index">>, i2l(Index)}], children = [{xmlcdata, First}]} | Arr]. rsm_encode_last(undefined, Arr) -> Arr; rsm_encode_last(Last, Arr) -> [#xmlel{name = <<"last">>, attrs = [], children = [{xmlcdata, Last}]} | Arr]. rsm_encode_count(undefined, Arr) -> Arr; rsm_encode_count(Count, Arr) -> [#xmlel{name = <<"count">>, attrs = [], 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(). add_delay_info(El, From, Time) -> add_delay_info(El, From, Time, <<"">>). -spec add_delay_info(xmlel(), jid() | ljid() | binary(), erlang:timestamp(), binary()) -> xmlel(). add_delay_info(El, From, Time, Desc) -> case xml: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]); DelayTag -> %% Update existing tag NewDelayTag = case {xml:get_tag_cdata(DelayTag), Desc} of {<<"">>, <<"">>} -> DelayTag; {OldDesc, <<"">>} -> DelayTag#xmlel{children = [{xmlcdata, OldDesc}]}; {<<"">>, NewDesc} -> DelayTag#xmlel{children = [{xmlcdata, NewDesc}]}; {OldDesc, NewDesc} -> case binary:match(OldDesc, NewDesc) of nomatch -> FinalDesc = <>, DelayTag#xmlel{children = [{xmlcdata, FinalDesc}]}; _ -> DelayTag#xmlel{children = [{xmlcdata, OldDesc}]} end end, 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()) -> xmlel() | error. create_delay_tag(TimeStamp, FromJID, Desc) when is_tuple(FromJID) -> From = jid:to_string(FromJID), Stamp = now_to_utc_string(TimeStamp, 3), Children = case Desc of <<"">> -> []; _ -> [{xmlcdata, Desc}] end, #xmlel{name = <<"delay">>, attrs = [{<<"xmlns">>, ?NS_DELAY}, {<<"from">>, From}, {<<"stamp">>, Stamp}], children = Children}; create_delay_tag(DateTime, Host, Desc) when is_binary(Host) -> FromJID = jid:make(<<"">>, Host, <<"">>), create_delay_tag(DateTime, FromJID, Desc). -type tz() :: {binary(), {integer(), integer()}} | {integer(), integer()} | utc. %% Timezone = utc | {Sign::string(), {Hours, Minutes}} | {Hours, Minutes} %% Hours = integer() %% Minutes = integer() -spec timestamp_to_iso(calendar:datetime(), tz()) -> {binary(), binary()}. timestamp_to_iso({{Year, Month, Day}, {Hour, Minute, Second}}, Timezone) -> Timestamp_string = lists:flatten(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B", [Year, Month, Day, Hour, Minute, Second])), Timezone_string = case Timezone of utc -> "Z"; {Sign, {TZh, TZm}} -> io_lib:format("~s~2..0B:~2..0B", [Sign, TZh, TZm]); {TZh, TZm} -> Sign = case TZh >= 0 of true -> "+"; false -> "-" end, io_lib:format("~s~2..0B:~2..0B", [Sign, abs(TZh), TZm]) end, {iolist_to_binary(Timestamp_string), iolist_to_binary(Timezone_string)}. -spec timestamp_to_iso(calendar:datetime()) -> binary(). timestamp_to_iso({{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}) -> now_to_utc_string({MegaSecs, Secs, MicroSecs}, 6). -spec now_to_utc_string(erlang:timestamp(), 1..6) -> binary(). now_to_utc_string({MegaSecs, Secs, MicroSecs}, Precision) -> {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:now_to_universal_time({MegaSecs, Secs, MicroSecs}), Max = round(math:pow(10, Precision)), case round(MicroSecs / math:pow(10, 6 - Precision)) of Max -> now_to_utc_string({MegaSecs, Secs + 1, 0}, Precision); FracOfSec -> list_to_binary(io_lib:format("~4..0B-~2..0B-~2..0BT" "~2..0B:~2..0B:~2..0B.~*..0BZ", [Year, Month, Day, Hour, Minute, Second, Precision, FracOfSec])) end. -spec now_to_local_string(erlang:timestamp()) -> binary(). now_to_local_string({MegaSecs, Secs, MicroSecs}) -> LocalTime = calendar:now_to_local_time({MegaSecs, Secs, MicroSecs}), UTCTime = calendar:now_to_universal_time({MegaSecs, Secs, MicroSecs}), Seconds = calendar:datetime_to_gregorian_seconds(LocalTime) - calendar:datetime_to_gregorian_seconds(UTCTime), {{H, M, _}, Sign} = if Seconds < 0 -> {calendar:seconds_to_time(-Seconds), "-"}; true -> {calendar:seconds_to_time(Seconds), "+"} end, {{Year, Month, Day}, {Hour, Minute, Second}} = LocalTime, list_to_binary(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B.~6." ".0B~s~2..0B:~2..0B", [Year, Month, Day, Hour, Minute, Second, MicroSecs, Sign, H, M])). -spec datetime_string_to_timestamp(binary()) -> undefined | erlang:timestamp(). datetime_string_to_timestamp(TimeStr) -> case catch parse_datetime(TimeStr) of {'EXIT', _Err} -> undefined; TimeStamp -> TimeStamp end. parse_datetime(TimeStr) -> [Date, Time] = str:tokens(TimeStr, <<"T">>), D = parse_date(Date), {T, MS, TZH, TZM} = parse_time(Time), S = calendar:datetime_to_gregorian_seconds({D, T}), S1 = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}), Seconds = S - S1 - TZH * 60 * 60 - TZM * 60, {Seconds div 1000000, Seconds rem 1000000, MS}. % yyyy-mm-dd parse_date(Date) -> [Y, M, D] = str:tokens(Date, <<"-">>), Date1 = {binary_to_integer(Y), binary_to_integer(M), binary_to_integer(D)}, case calendar:valid_date(Date1) of true -> Date1; _ -> false end. % hh:mm:ss[.sss]TZD parse_time(Time) -> case str:str(Time, <<"Z">>) of 0 -> parse_time_with_timezone(Time); _ -> [T | _] = str:tokens(Time, <<"Z">>), {TT, MS} = parse_time1(T), {TT, MS, 0, 0} end. parse_time_with_timezone(Time) -> case str:str(Time, <<"+">>) of 0 -> case str:str(Time, <<"-">>) of 0 -> false; _ -> parse_time_with_timezone(Time, <<"-">>) end; _ -> parse_time_with_timezone(Time, <<"+">>) end. parse_time_with_timezone(Time, Delim) -> [T, TZ] = str:tokens(Time, Delim), {TZH, TZM} = parse_timezone(TZ), {TT, MS} = parse_time1(T), case Delim of <<"-">> -> {TT, MS, -TZH, -TZM}; <<"+">> -> {TT, MS, TZH, TZM} end. parse_timezone(TZ) -> [H, M] = str:tokens(TZ, <<":">>), {[H1, M1], true} = check_list([{H, 12}, {M, 60}]), {H1, M1}. parse_time1(Time) -> [HMS | T] = str:tokens(Time, <<".">>), MS = case T of [] -> 0; [Val] -> binary_to_integer(str:left(Val, 6, $0)) end, [H, M, S] = str:tokens(HMS, <<":">>), {[H1, M1, S1], true} = check_list([{H, 24}, {M, 60}, {S, 60}]), {{H1, M1, S1}, MS}. check_list(List) -> lists:mapfoldl(fun ({L, N}, B) -> V = binary_to_integer(L), if (V >= 0) and (V =< N) -> {V, B}; true -> {false, false} end end, true, List). % % Base64 stuff (based on httpd_util.erl) % -spec term_to_base64(term()) -> binary(). term_to_base64(Term) -> encode_base64(term_to_binary(Term)). -spec base64_to_term(binary()) -> {term, term()} | error. base64_to_term(Base64) -> case catch binary_to_term(decode_base64(Base64), [safe]) of {'EXIT', _} -> error; Term -> {term, Term} end. -spec decode_base64(binary()) -> binary(). decode_base64(S) -> case catch binary:last(S) of C when C == $\n; C == $\s -> decode_base64(binary:part(S, 0, byte_size(S) - 1)); _ -> decode_base64_bin(S, <<>>) end. take_without_spaces(Bin, Count) -> take_without_spaces(Bin, Count, <<>>). take_without_spaces(Bin, 0, Acc) -> {Acc, Bin}; take_without_spaces(<<>>, _, Acc) -> {Acc, <<>>}; take_without_spaces(<<$\s, Tail/binary>>, Count, Acc) -> take_without_spaces(Tail, Count, Acc); take_without_spaces(<<$\t, Tail/binary>>, Count, Acc) -> take_without_spaces(Tail, Count, Acc); take_without_spaces(<<$\n, Tail/binary>>, Count, Acc) -> take_without_spaces(Tail, Count, Acc); take_without_spaces(<<$\r, Tail/binary>>, Count, Acc) -> take_without_spaces(Tail, Count, Acc); take_without_spaces(<>, Count, Acc) -> take_without_spaces(Tail, Count-1, <>). decode_base64_bin(<<>>, Acc) -> Acc; decode_base64_bin(Bin, Acc) -> case take_without_spaces(Bin, 4) of {<>, _} -> <>; {<>, _} -> <>; {<>, Tail} -> Acc2 = <>, decode_base64_bin(Tail, Acc2); _ -> <<"">> end. d(X) when X >= $A, X =< $Z -> X - 65; d(X) when X >= $a, X =< $z -> X - 71; d(X) when X >= $0, X =< $9 -> X + 4; d($+) -> 62; d($/) -> 63; d(_) -> 63. %% Convert Erlang inet IP to list -spec encode_base64(binary()) -> binary(). encode_base64(Data) -> encode_base64_bin(Data, <<>>). encode_base64_bin(<>, Acc) -> encode_base64_bin(Tail, <>); encode_base64_bin(<>, Acc) -> <>; encode_base64_bin(<>, Acc) -> <>; encode_base64_bin(<<>>, Acc) -> Acc. e(X) when X >= 0, X < 26 -> X + 65; e(X) when X > 25, X < 52 -> X + 71; e(X) when X > 51, X < 62 -> X - 4; e(62) -> $+; e(63) -> $/; e(X) -> exit({bad_encode_base64_token, X}). -spec ip_to_list(inet:ip_address() | undefined | {inet:ip_address(), inet:port_number()}) -> binary(). ip_to_list({IP, _Port}) -> ip_to_list(IP); %% This function clause could use inet_parse too: ip_to_list(undefined) -> <<"unknown">>; ip_to_list(IP) -> list_to_binary(inet_parse:ntoa(IP)). binary_to_atom(Bin) -> erlang:binary_to_atom(Bin, utf8). binary_to_integer(Bin) -> erlang:binary_to_integer(Bin). binary_to_integer(Bin, Base) -> erlang:binary_to_integer(Bin, Base). integer_to_binary(I) -> erlang:integer_to_binary(I). integer_to_binary(I, Base) -> erlang:integer_to_binary(I, Base). tuple_to_binary(T) -> iolist_to_binary(tuple_to_list(T)). atom_to_binary(A) -> erlang:atom_to_binary(A, utf8). l2i(I) when is_integer(I) -> I; l2i(L) when is_binary(L) -> binary_to_integer(L). i2l(I) when is_integer(I) -> integer_to_binary(I); i2l(L) when is_binary(L) -> L. i2l(I, N) when is_integer(I) -> i2l(i2l(I), N); i2l(L, N) when is_binary(L) -> case str:len(L) of N -> L; C when C > N -> L; _ -> i2l(<<$0, L/binary>>, N) end. -spec queue_drop_while(fun((term()) -> boolean()), ?TQUEUE) -> ?TQUEUE. queue_drop_while(F, Q) -> case queue:peek(Q) of {value, Item} -> case F(Item) of true -> queue_drop_while(F, queue:drop(Q)); _ -> Q end; empty -> Q end. ejabberd-16.01/src/ejabberd_odbc.erl0000644000232200023220000006427212645157216017671 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_odbc.erl %%% Author : Alexey Shchepin %%% Purpose : Serve ODBC connection %%% Created : 8 Dec 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_odbc). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -define(GEN_FSM, p1_fsm). -behaviour(?GEN_FSM). %% External exports -export([start/1, start_link/2, sql_query/2, sql_query_t/1, sql_transaction/2, sql_bloc/2, escape/1, escape_like/1, to_bool/1, sqlite_db/1, 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 -export([init/1, handle_event/3, handle_sync_event/4, handle_info/3, terminate/3, print_state/1, code_change/4]). -export([connecting/2, connecting/3, session_established/2, session_established/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -record(state, {db_ref = self() :: pid(), db_type = odbc :: pgsql | mysql | sqlite | odbc | mssql, start_interval = 0 :: non_neg_integer(), host = <<"">> :: binary(), max_pending_requests_len :: non_neg_integer(), pending_requests = {0, queue:new()} :: {non_neg_integer(), ?TQUEUE}}). -define(STATE_KEY, ejabberd_odbc_state). -define(NESTING_KEY, ejabberd_odbc_nesting_level). -define(TOP_LEVEL_TXN, 0). -define(PGSQL_PORT, 5432). -define(MYSQL_PORT, 3306). -define(MSSQL_PORT, 1433). -define(MAX_TRANSACTION_RESTARTS, 10). -define(TRANSACTION_TIMEOUT, 60000). -define(KEEPALIVE_TIMEOUT, 60000). -define(KEEPALIVE_QUERY, [<<"SELECT 1;">>]). %%-define(DBGFSM, true). -ifdef(DBGFSM). -define(FSMOPTS, [{debug, [trace]}]). -else. -define(FSMOPTS, []). -endif. %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start(Host) -> (?GEN_FSM):start(ejabberd_odbc, [Host], fsm_limit_opts() ++ (?FSMOPTS)). start_link(Host, StartInterval) -> (?GEN_FSM):start_link(ejabberd_odbc, [Host, StartInterval], fsm_limit_opts() ++ (?FSMOPTS)). -type sql_query() :: [sql_query() | binary()]. -type sql_query_result() :: {updated, non_neg_integer()} | {error, binary()} | {selected, [binary()], [[binary()]]}. -spec sql_query(binary(), sql_query()) -> sql_query_result(). sql_query(Host, Query) -> sql_call(Host, {sql_query, Query}). %% SQL transaction based on a list of queries %% This function automatically -spec sql_transaction(binary(), [sql_query()] | fun(() -> any())) -> {atomic, any()} | {aborted, any()}. sql_transaction(Host, Queries) when is_list(Queries) -> F = fun () -> lists:foreach(fun (Query) -> sql_query_t(Query) end, Queries) end, sql_transaction(Host, F); %% SQL transaction, based on a erlang anonymous function (F = fun) sql_transaction(Host, F) when is_function(F) -> sql_call(Host, {sql_transaction, F}). %% SQL bloc, based on a erlang anonymous function (F = fun) sql_bloc(Host, F) -> sql_call(Host, {sql_bloc, F}). sql_call(Host, Msg) -> case get(?STATE_KEY) of undefined -> case ejabberd_odbc_sup:get_random_pid(Host) of none -> {error, <<"Unknown Host">>}; Pid -> (?GEN_FSM):sync_send_event(Pid,{sql_cmd, Msg, p1_time_compat:monotonic_time(milli_seconds)}, ?TRANSACTION_TIMEOUT) end; _State -> nested_op(Msg) end. keep_alive(PID) -> (?GEN_FSM):sync_send_event(PID, {sql_cmd, {sql_query, ?KEEPALIVE_QUERY}, p1_time_compat:monotonic_time(milli_seconds)}, ?KEEPALIVE_TIMEOUT). -spec sql_query_t(sql_query()) -> sql_query_result(). %% This function is intended to be used from inside an sql_transaction: sql_query_t(Query) -> QRes = sql_query_internal(Query), case QRes of {error, Reason} -> throw({aborted, Reason}); Rs when is_list(Rs) -> case lists:keysearch(error, 1, Rs) of {value, {error, Reason}} -> throw({aborted, Reason}); _ -> QRes end; _ -> QRes end. %% Escape character that will confuse an SQL engine escape(S) -> << <<(odbc_queries:escape(Char))/binary>> || <> <= S >>. %% Escape character that will confuse an SQL engine %% Percent and underscore only need to be escaped for pattern matching like %% statement escape_like(S) when is_binary(S) -> << <<(escape_like(C))/binary>> || <> <= S >>; escape_like($%) -> <<"\\%">>; escape_like($_) -> <<"\\_">>; escape_like(C) when is_integer(C), C >= 0, C =< 255 -> odbc_queries:escape(C). to_bool(<<"t">>) -> true; to_bool(<<"true">>) -> true; to_bool(<<"1">>) -> true; to_bool(true) -> true; to_bool(1) -> true; to_bool(_) -> false. encode_term(Term) -> escape(list_to_binary( erl_prettypr:format(erl_syntax:abstract(Term), [{paper, 65535}, {ribbon, 65535}]))). decode_term(Bin) -> Str = binary_to_list(<>), {ok, Tokens, _} = erl_scan:string(Str), {ok, Term} = erl_parse:parse_term(Tokens), Term. -spec sqlite_db(binary()) -> atom(). sqlite_db(Host) -> list_to_atom("ejabberd_sqlite_" ++ binary_to_list(Host)). -spec sqlite_file(binary()) -> string(). sqlite_file(Host) -> case ejabberd_config:get_option({odbc_database, Host}, fun iolist_to_binary/1) of undefined -> {ok, Cwd} = file:get_cwd(), filename:join([Cwd, "sqlite", atom_to_list(node()), binary_to_list(Host), "ejabberd.db"]); File -> binary_to_list(File) end. %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- init([Host, StartInterval]) -> case ejabberd_config:get_option( {odbc_keepalive_interval, Host}, fun(I) when is_integer(I), I>0 -> I end) of undefined -> ok; KeepaliveInterval -> timer:apply_interval(KeepaliveInterval * 1000, ?MODULE, keep_alive, [self()]) end, [DBType | _] = db_opts(Host), (?GEN_FSM):send_event(self(), connect), ejabberd_odbc_sup:add_pid(Host, self()), {ok, connecting, #state{db_type = DBType, host = Host, max_pending_requests_len = max_fsm_queue(), pending_requests = {0, queue:new()}, start_interval = StartInterval}}. connecting(connect, #state{host = Host} = State) -> ConnectRes = case db_opts(Host) of [mysql | Args] -> apply(fun mysql_connect/5, Args); [pgsql | Args] -> apply(fun pgsql_connect/5, Args); [sqlite | Args] -> apply(fun sqlite_connect/1, Args); [odbc | Args] -> apply(fun odbc_connect/1, Args) 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()}}}; {error, Reason} -> ?INFO_MSG("~p connection failed:~n** Reason: ~p~n** " "Retry after: ~p seconds", [State#state.db_type, Reason, State#state.start_interval div 1000]), (?GEN_FSM):send_event_after(State#state.start_interval, connect), {next_state, connecting, State} end; connecting(Event, State) -> ?WARNING_MSG("unexpected event in 'connecting': ~p", [Event]), {next_state, connecting, State}. connecting({sql_cmd, {sql_query, ?KEEPALIVE_QUERY}, _Timestamp}, From, State) -> (?GEN_FSM):reply(From, {error, <<"SQL connection failed">>}), {next_state, connecting, State}; connecting({sql_cmd, Command, Timestamp} = Req, From, State) -> ?DEBUG("queuing pending request while connecting:~n\t~p", [Req]), {Len, PendingRequests} = State#state.pending_requests, NewPendingRequests = if Len < State#state.max_pending_requests_len -> {Len + 1, queue:in({sql_cmd, Command, From, Timestamp}, PendingRequests)}; true -> lists:foreach(fun ({sql_cmd, _, To, _Timestamp}) -> (?GEN_FSM):reply(To, {error, <<"SQL connection failed">>}) end, queue:to_list(PendingRequests)), {1, queue:from_list([{sql_cmd, Command, From, Timestamp}])} end, {next_state, connecting, State#state{pending_requests = NewPendingRequests}}; connecting(Request, {Who, _Ref}, State) -> ?WARNING_MSG("unexpected call ~p from ~p in 'connecting'", [Request, Who]), {reply, {error, badarg}, connecting, State}. session_established({sql_cmd, Command, Timestamp}, From, State) -> run_sql_cmd(Command, From, State, Timestamp); session_established(Request, {Who, _Ref}, State) -> ?WARNING_MSG("unexpected call ~p from ~p in 'session_establ" "ished'", [Request, Who]), {reply, {error, badarg}, session_established, State}. session_established({sql_cmd, Command, From, Timestamp}, State) -> run_sql_cmd(Command, From, State, Timestamp); session_established(Event, State) -> ?WARNING_MSG("unexpected event in 'session_established': ~p", [Event]), {next_state, session_established, State}. handle_event(_Event, StateName, State) -> {next_state, StateName, State}. handle_sync_event(_Event, _From, StateName, State) -> {reply, {error, badarg}, StateName, State}. code_change(_OldVsn, StateName, State, _Extra) -> {ok, StateName, State}. %% We receive the down signal when we loose the MySQL connection (we are %% monitoring the connection) handle_info({'DOWN', _MonitorRef, process, _Pid, _Info}, _StateName, State) -> (?GEN_FSM):send_event(self(), connect), {next_state, connecting, State}; handle_info(Info, StateName, State) -> ?WARNING_MSG("unexpected info in ~p: ~p", [StateName, Info]), {next_state, StateName, State}. terminate(_Reason, _StateName, State) -> ejabberd_odbc_sup:remove_pid(State#state.host, self()), case State#state.db_type of mysql -> catch p1_mysql_conn:stop(State#state.db_ref); sqlite -> catch sqlite3:close(sqlite_db(State#state.host)); _ -> ok end, ok. %%---------------------------------------------------------------------- %% Func: print_state/1 %% Purpose: Prepare the state to be printed on error log %% Returns: State to print %%---------------------------------------------------------------------- print_state(State) -> State. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- run_sql_cmd(Command, From, State, Timestamp) -> 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), abort_on_driver_error(outer_op(Command), From); Age -> ?ERROR_MSG("Database was not available or too slow, " "discarding ~p milliseconds old request~n~p~n", [Age, Command]), {next_state, session_established, State} end. %% Only called by handle_call, only handles top level operations. %% @spec outer_op(Op) -> {error, Reason} | {aborted, Reason} | {atomic, Result} outer_op({sql_query, Query}) -> sql_query_internal(Query); outer_op({sql_transaction, F}) -> outer_transaction(F, ?MAX_TRANSACTION_RESTARTS, <<"">>); outer_op({sql_bloc, F}) -> execute_bloc(F). %% Called via sql_query/transaction/bloc from client code when inside a %% nested operation nested_op({sql_query, Query}) -> sql_query_internal(Query); nested_op({sql_transaction, F}) -> NestingLevel = get(?NESTING_KEY), if NestingLevel =:= (?TOP_LEVEL_TXN) -> outer_transaction(F, ?MAX_TRANSACTION_RESTARTS, <<"">>); true -> inner_transaction(F) end; nested_op({sql_bloc, F}) -> execute_bloc(F). %% Never retry nested transactions - only outer transactions inner_transaction(F) -> PreviousNestingLevel = get(?NESTING_KEY), case get(?NESTING_KEY) of ?TOP_LEVEL_TXN -> {backtrace, T} = process_info(self(), backtrace), ?ERROR_MSG("inner transaction called at outer txn " "level. Trace: ~s", [T]), erlang:exit(implementation_faulty); _N -> ok end, put(?NESTING_KEY, PreviousNestingLevel + 1), Result = (catch F()), put(?NESTING_KEY, PreviousNestingLevel), case Result of {aborted, Reason} -> {aborted, Reason}; {'EXIT', Reason} -> {'EXIT', Reason}; {atomic, Res} -> {atomic, Res}; Res -> {atomic, Res} end. outer_transaction(F, NRestarts, _Reason) -> PreviousNestingLevel = get(?NESTING_KEY), case get(?NESTING_KEY) of ?TOP_LEVEL_TXN -> ok; _N -> {backtrace, T} = process_info(self(), backtrace), ?ERROR_MSG("outer transaction called at inner txn " "level. Trace: ~s", [T]), erlang:exit(implementation_faulty) end, 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;">>]), outer_transaction(F, NRestarts - 1, Reason); {aborted, Reason} when NRestarts =:= 0 -> ?ERROR_MSG("SQL transaction restarts exceeded~n** " "Restarts: ~p~n** Last abort reason: " "~p~n** Stacktrace: ~p~n** When State " "== ~p", [?MAX_TRANSACTION_RESTARTS, Reason, erlang:get_stacktrace(), get(?STATE_KEY)]), sql_query_internal([<<"rollback;">>]), {aborted, Reason}; {'EXIT', Reason} -> sql_query_internal([<<"rollback;">>]), {aborted, Reason}; Res -> sql_query_internal([<<"commit;">>]), {atomic, Res} end. execute_bloc(F) -> case catch F() of {aborted, Reason} -> {aborted, Reason}; {'EXIT', Reason} -> {aborted, Reason}; Res -> {atomic, Res} end. 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, (?TRANSACTION_TIMEOUT) - 1000)); pgsql -> pgsql_to_odbc(pgsql:squery(State#state.db_ref, Query)); mysql -> R = mysql_to_odbc(p1_mysql_conn:squery(State#state.db_ref, [Query], self(), [{timeout, (?TRANSACTION_TIMEOUT) - 1000}, {result_type, binary}])), %% ?INFO_MSG("MySQL, Received result~n~p~n", [R]), R; sqlite -> Host = State#state.host, sqlite_to_odbc(Host, sqlite3:sql_exec(sqlite_db(Host), Query)) end, case Res of {error, <<"No SQL-driver information available.">>} -> {updated, 0}; _Else -> Res end. %% Generate the OTP callback return tuple depending on the driver result. abort_on_driver_error({error, <<"query timed out">>} = Reply, From) -> (?GEN_FSM):reply(From, Reply), {stop, timeout, get(?STATE_KEY)}; abort_on_driver_error({error, <<"Failed sending data on socket", _/binary>>} = Reply, From) -> (?GEN_FSM):reply(From, Reply), {stop, closed, get(?STATE_KEY)}; abort_on_driver_error(Reply, From) -> (?GEN_FSM):reply(From, Reply), {next_state, session_established, get(?STATE_KEY)}. %% == pure ODBC code %% part of init/1 %% Open an ODBC database connection odbc_connect(SQLServer) -> ejabberd:start_app(odbc), odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}, {tuple_row, off}, {binary_strings, on}]). %% == Native SQLite code %% part of init/1 %% Open a database connection to SQLite sqlite_connect(Host) -> File = sqlite_file(Host), case filelib:ensure_dir(File) of ok -> case sqlite3:open(sqlite_db(Host), [{file, File}]) of {ok, Ref} -> sqlite3:sql_exec( sqlite_db(Host), "pragma foreign_keys = on"), {ok, Ref}; {error, {already_started, Ref}} -> {ok, Ref}; {error, Reason} -> {error, Reason} end; Err -> Err end. %% Convert SQLite query result to Erlang ODBC result formalism sqlite_to_odbc(Host, ok) -> {updated, sqlite3:changes(sqlite_db(Host))}; sqlite_to_odbc(Host, {rowid, _}) -> {updated, sqlite3:changes(sqlite_db(Host))}; sqlite_to_odbc(_Host, [{columns, Columns}, {rows, TRows}]) -> Rows = [lists:map( fun(I) when is_integer(I) -> jlib:integer_to_binary(I); (B) -> B end, tuple_to_list(Row)) || Row <- TRows], {selected, [list_to_binary(C) || C <- Columns], Rows}; sqlite_to_odbc(_Host, {error, _Code, Reason}) -> {error, Reason}; sqlite_to_odbc(_Host, _) -> {updated, undefined}. %% == Native PostgreSQL code %% part of init/1 %% Open a database connection to PostgreSQL pgsql_connect(Server, Port, DB, Username, Password) -> case pgsql:connect([{host, Server}, {database, DB}, {user, Username}, {password, Password}, {port, Port}, {as_binary, true}]) of {ok, Ref} -> pgsql:squery(Ref, [<<"alter database ">>, DB, <<" set ">>, <<"standard_conforming_strings='off';">>]), pgsql:squery(Ref, [<<"set standard_conforming_strings to 'off';">>]), {ok, Ref}; Err -> Err end. %% Convert PostgreSQL query result to Erlang ODBC result formalism pgsql_to_odbc({ok, PGSQLResult}) -> case PGSQLResult of [Item] -> pgsql_item_to_odbc(Item); Items -> [pgsql_item_to_odbc(Item) || Item <- Items] end. pgsql_item_to_odbc({<<"SELECT", _/binary>>, Rows, Recs}) -> {selected, [element(1, Row) || Row <- Rows], Recs}; pgsql_item_to_odbc({<<"FETCH", _/binary>>, Rows, Recs}) -> {selected, [element(1, Row) || Row <- Rows], Recs}; pgsql_item_to_odbc(<<"INSERT ", OIDN/binary>>) -> [_OID, N] = str:tokens(OIDN, <<" ">>), {updated, jlib:binary_to_integer(N)}; pgsql_item_to_odbc(<<"DELETE ", N/binary>>) -> {updated, jlib:binary_to_integer(N)}; pgsql_item_to_odbc(<<"UPDATE ", N/binary>>) -> {updated, jlib:binary_to_integer(N)}; pgsql_item_to_odbc({error, Error}) -> {error, Error}; pgsql_item_to_odbc(_) -> {updated, undefined}. %% == Native MySQL code %% part of init/1 %% 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) of {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 mysql_to_odbc({updated, MySQLRes}) -> {updated, p1_mysql:get_result_affected_rows(MySQLRes)}; mysql_to_odbc({data, MySQLRes}) -> mysql_item_to_odbc(p1_mysql:get_result_field_info(MySQLRes), p1_mysql:get_result_rows(MySQLRes)); mysql_to_odbc({error, MySQLRes}) when is_binary(MySQLRes) -> {error, MySQLRes}; mysql_to_odbc({error, MySQLRes}) when is_list(MySQLRes) -> {error, list_to_binary(MySQLRes)}; mysql_to_odbc({error, MySQLRes}) -> {error, p1_mysql:get_result_reason(MySQLRes)}; mysql_to_odbc(ok) -> ok. %% When tabular data is returned, convert it to the ODBC formalism mysql_item_to_odbc(Columns, Recs) -> {selected, [element(2, Column) || Column <- Columns], Recs}. to_odbc({selected, Columns, 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. log(Level, Format, Args) -> case Level of debug -> ?DEBUG(Format, Args); normal -> ?INFO_MSG(Format, Args); error -> ?ERROR_MSG(Format, Args) end. db_opts(Host) -> Type = ejabberd_config:get_option({odbc_type, Host}, fun(mysql) -> mysql; (pgsql) -> pgsql; (sqlite) -> sqlite; (mssql) -> mssql; (odbc) -> odbc end, odbc), Server = ejabberd_config:get_option({odbc_server, Host}, fun iolist_to_binary/1, <<"localhost">>), case Type of odbc -> [odbc, Server]; sqlite -> [sqlite, Host]; _ -> Port = ejabberd_config:get_option( {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), DB = ejabberd_config:get_option({odbc_database, Host}, fun iolist_to_binary/1, <<"ejabberd">>), User = ejabberd_config:get_option({odbc_username, Host}, fun iolist_to_binary/1, <<"ejabberd">>), 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, fun(N) when is_integer(N), N > 0 -> N end). fsm_limit_opts() -> case max_fsm_queue() of 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; (mssql) -> mssql; (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]. ejabberd-16.01/src/ejabberd_http_ws.erl0000644000232200023220000003524312645157216020446 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_websocket.erl %%% Author : Eric Cestari %%% Purpose : XMPP Websocket support %%% Created : 09-10-2010 by Eric Cestari %%% %%% %%% 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_ws). -behaviour(ejabberd_config). -author('ecestari@process-one.net'). -behaviour(gen_fsm). -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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_http.hrl"). -define(PING_INTERVAL, 60). -define(WEBSOCKET_TIMEOUT, 300). -record(state, {socket :: ws_socket(), ping_interval = ?PING_INTERVAL :: non_neg_integer(), ping_timer = make_ref() :: reference(), pong_expected :: boolean(), timeout = ?WEBSOCKET_TIMEOUT :: non_neg_integer(), timer = make_ref() :: reference(), input = [] :: list(), waiting_input = false :: false | pid(), last_receiver :: pid(), ws :: {#ws{}, pid()}, rfc_compilant = undefined :: boolean() | undefined}). %-define(DBGFSM, true). -ifdef(DBGFSM). -define(FSMOPTS, [{debug, [trace]}]). -else. -define(FSMOPTS, []). -endif. -type ws_socket() :: {http_ws, pid(), {inet:ip_address(), inet:port_number()}}. -export_type([ws_socket/0]). start(WS) -> gen_fsm:start(?MODULE, [WS], ?FSMOPTS). start_link(WS) -> gen_fsm:start_link(?MODULE, [WS], ?FSMOPTS). send_xml({http_ws, FsmRef, _IP}, Packet) -> gen_fsm:sync_send_all_state_event(FsmRef, {send_xml, Packet}). setopts({http_ws, 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_ws, _FsmRef, IP}) -> {ok, IP}. controlling_process(_Socket, _Pid) -> ok. become_controller(FsmRef, C2SPid) -> gen_fsm:send_all_state_event(FsmRef, {become_controller, C2SPid}). close({http_ws, FsmRef, _IP}) -> catch gen_fsm:sync_send_all_state_event(FsmRef, close). socket_handoff(LocalPath, Request, Socket, SockMod, Buf, Opts) -> ejabberd_websocket:socket_handoff(LocalPath, Request, Socket, SockMod, Buf, Opts, ?MODULE, fun get_human_html_xmlel/0). %%% Internal 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), Opts = [{xml_socket, true} | ejabberd_c2s_config:get_c2s_limits() ++ SOpts], PingInterval = ejabberd_config:get_option( {websocket_ping_interval, ?MYNAME}, fun(I) when is_integer(I), I>=0 -> I end, ?PING_INTERVAL) * 1000, WSTimeout = ejabberd_config:get_option( {websocket_timeout, ?MYNAME}, fun(I) when is_integer(I), I>0 -> I end, ?WEBSOCKET_TIMEOUT) * 1000, Socket = {http_ws, self(), IP}, ?DEBUG("Client connected through websocket ~p", [Socket]), ejabberd_socket:start(ejabberd_c2s, ?MODULE, Socket, Opts), Timer = erlang:start_timer(WSTimeout, self(), []), {ok, loop, #state{socket = Socket, timeout = WSTimeout, timer = Timer, ws = WS, ping_interval = PingInterval}}. handle_event({activate, From}, StateName, StateData) -> case StateData#state.input of [] -> {next_state, StateName, StateData#state{waiting_input = From}}; Input -> Receiver = From, 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, last_receiver = Receiver}} end. handle_sync_event({send_xml, Packet}, _From, StateName, #state{ws = {_, WsPid}, rfc_compilant = R} = StateData) -> Packet2 = case {case R of undefined -> true; V -> V end, Packet} of {true, {xmlstreamstart, _, Attrs}} -> Attrs2 = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>} | lists:keydelete(<<"xmlns">>, 1, lists:keydelete(<<"xmlns:stream">>, 1, Attrs))], {xmlstreamelement, #xmlel{name = <<"open">>, attrs = Attrs2}}; {true, {xmlstreamend, _}} -> {xmlstreamelement, #xmlel{name = <<"close">>, attrs = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>}]}}; {true, {xmlstreamraw, <<"\r\n\r\n">>}} -> % cdata ping skip; {true, {xmlstreamelement, #xmlel{name=Name2} = El2}} -> El3 = case Name2 of <<"stream:", _/binary>> -> xml:replace_tag_attr(<<"xmlns:stream">>, ?NS_STREAM, El2); _ -> case xml:get_tag_attr_s(<<"xmlns">>, El2) of <<"">> -> xml:replace_tag_attr(<<"xmlns">>, <<"jabber:client">>, El2); _ -> El2 end end, {xmlstreamelement , El3}; _ -> Packet end, case Packet2 of {xmlstreamstart, Name, Attrs3} -> B = xml: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)}; {xmlstreamraw, Bin} -> WsPid ! {send, Bin}; {xmlstreamcdata, Bin2} -> WsPid ! {send, Bin2}; skip -> ok end, SN2 = case Packet2 of {xmlstreamelement, #xmlel{name = <<"close">>}} -> stream_end_sent; _ -> StateName end, {reply, ok, SN2, StateData}; handle_sync_event(close, _From, StateName, #state{ws = {_, WsPid}, rfc_compilant = true} = StateData) 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)}, {stop, normal, StateData}; handle_sync_event(close, _From, _StateName, StateData) -> {stop, normal, StateData}. handle_info(closed, _StateName, StateData) -> {stop, normal, StateData}; handle_info({received, Packet}, StateName, StateDataI) -> {StateData, Parsed} = parse(StateDataI, Packet), SD = case StateData#state.waiting_input of false -> Input = StateData#state.input ++ if is_binary(Parsed) -> [Parsed]; true -> Parsed end, StateData#state{input = Input}; Receiver -> Receiver ! {tcp, StateData#state.socket, Parsed}, setup_timers(StateData#state{waiting_input = false, last_receiver = Receiver}) end, {next_state, StateName, SD}; handle_info(PingPong, StateName, StateData) when PingPong == ping orelse PingPong == pong -> StateData2 = setup_timers(StateData), {next_state, StateName, StateData2#state{pong_expected = false}}; handle_info({timeout, Timer, _}, _StateName, #state{timer = Timer} = StateData) -> {stop, normal, StateData}; handle_info({timeout, Timer, _}, StateName, #state{ping_timer = Timer, ws = {_, WsPid}} = StateData) -> case StateData#state.pong_expected of false -> cancel_timer(StateData#state.ping_timer), PingTimer = erlang:start_timer(StateData#state.ping_interval, self(), []), WsPid ! {ping, <<>>}, {next_state, StateName, StateData#state{ping_timer = PingTimer, pong_expected = true}}; true -> {stop, normal, StateData} end; handle_info(_, StateName, StateData) -> {next_state, StateName, StateData}. code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. terminate(_Reason, _StateName, StateData) -> case StateData#state.waiting_input of false -> ok; Receiver -> ?DEBUG("C2S Pid : ~p", [Receiver]), Receiver ! {tcp_closed, StateData#state.socket} end, ok. setup_timers(StateData) -> cancel_timer(StateData#state.timer), Timer = erlang:start_timer(StateData#state.timeout, self(), []), cancel_timer(StateData#state.ping_timer), 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}. cancel_timer(Timer) -> erlang:cancel_timer(Timer), receive {timeout, Timer, _} -> ok after 0 -> ok end. get_human_html_xmlel() -> Heading = <<"ejabberd ", (jlib:atom_to_binary(?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://tools.ietf.org/html/rfc6455">>}], children = [{xmlcdata, <<"WebSocket protocol">>}]}]}, #xmlel{name = <<"p">>, attrs = [], children = [{xmlcdata, <<"This web page is only informative. To " "use WebSocket connection you need a Jabber/XMPP " "client that supports it.">>}]}]}]}. 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), case parsed_items([]) of error -> {State#state{rfc_compilant = true}, <<"parse error">>}; [] -> {State#state{rfc_compilant = true}, <<"parse error">>}; [{xmlstreamstart, <<"open">>, _} | _] -> parse(State#state{rfc_compilant = true}, Data); _ -> parse(State#state{rfc_compilant = false}, Data) end; true -> El = xml_stream:parse_element(Data), case El of #xmlel{name = <<"open">>, attrs = Attrs} -> Attrs2 = [{<<"xmlns:stream">>, ?NS_STREAM}, {<<"xmlns">>, <<"jabber:client">>} | lists:keydelete(<<"xmlns">>, 1, lists:keydelete(<<"xmlns:stream">>, 1, Attrs))], {State, [{xmlstreamstart, <<"stream:stream">>, Attrs2}]}; #xmlel{name = <<"close">>} -> {State, [{xmlstreamend, <<"stream:stream">>}]}; {error, _} -> {State, <<"parse error">>}; _ -> {State, [El]} end; false -> {State, Data} end. parsed_items(List) -> receive {'$gen_event', El} when element(1, El) == xmlel; element(1, El) == xmlstreamstart; element(1, El) == xmlstreamelement; element(1, El) == xmlstreamend -> parsed_items([El | List]); {'$gen_event', {xmlstreamerror, _}} -> error 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]. ejabberd-16.01/src/ejabberd_node_groups.erl0000644000232200023220000001364212645157216021301 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_node_groups.erl %%% Author : Alexey Shchepin %%% Purpose : Distributed named node groups based on pg2 module %%% Created : 1 Nov 2006 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_node_groups). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_server). %% API -export([start_link/0, join/1, leave/1, get_members/1, get_closest_node/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, opt_type/1]). -define(PG2, pg2). -record(state, {}). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). join(Name) -> PG = {?MODULE, Name}, pg2:create(PG), pg2:join(PG, whereis(?MODULE)). leave(Name) -> PG = {?MODULE, Name}, pg2:leave(PG, whereis(?MODULE)). get_members(Name) -> PG = {?MODULE, Name}, [node(P) || P <- pg2:get_members(PG)]. get_closest_node(Name) -> PG = {?MODULE, Name}, node(pg2:get_closest_pid(PG)). %%==================================================================== %% gen_server callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- init([]) -> {FE, BE} = case ejabberd_config:get_option( node_type, fun(frontend) -> frontend; (backend) -> backend; (generic) -> generic end, generic) of frontend -> {true, false}; backend -> {false, true}; generic -> {true, true}; undefined -> {true, true} end, if FE -> join(frontend); true -> ok end, if BE -> join(backend); true -> ok end, {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(_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}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- opt_type(node_type) -> fun (frontend) -> frontend; (backend) -> backend; (generic) -> generic end; opt_type(_) -> [node_type]. ejabberd-16.01/src/mod_irc_connection.erl0000644000232200023220000016240012645157216020767 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_irc_connection.erl %%% Author : Alexey Shchepin %%% Purpose : %%% Created : 15 Feb 2003 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(mod_irc_connection). -author('alexey@process-one.net'). -behaviour(gen_fsm). %% External exports -export([start_link/12, start/13, route_chan/4, route_nick/3]). %% gen_fsm callbacks -export([init/1, open_socket/2, wait_for_registration/2, stream_established/2, handle_event/3, handle_sync_event/4, handle_info/3, terminate/3, code_change/4]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -define(SETS, gb_sets). -record(state, {socket :: inet:socket(), encoding = <<"">> :: binary(), port = 0 :: inet:port_number(), password = <<"">> :: binary(), queue = queue:new() :: ?TQUEUE, 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()}). %-define(DBGFSM, true). -ifdef(DBGFSM). -define(FSMOPTS, [{debug, [trace]}]). -else. -define(FSMOPTS, []). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- -endif. start(From, Host, ServerHost, Server, Username, 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, Ident, RemoteAddr, RealName, WebircPassword, Mod]). start_link(From, Host, Server, Username, Encoding, Port, Password, Ident, RemoteAddr, RealName, WebircPassword, Mod) -> gen_fsm:start_link(?MODULE, [From, Host, Server, Username, Encoding, Port, Password, Ident, RemoteAddr, RealName, WebircPassword, Mod], ?FSMOPTS). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, StateName, StateData} | %% {ok, StateName, StateData, Timeout} | %% ignore | %% {stop, StopReason} %%---------------------------------------------------------------------- init([From, Host, Server, Username, Encoding, Port, 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, ident = Ident, realname = RealName, remoteAddr = RemoteAddr, webirc_password = WebircPassword }}. %%---------------------------------------------------------------------- %% Func: StateName/2 %% Returns: {next_state, NextStateName, NextStateData} | %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- 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 {error, _} -> ?DEBUG("Connection with IPv6 to ~s:~p failed. " "Now using IPv4.", [Addr, Port]), gen_tcp:connect(binary_to_list(Addr), Port, [inet, binary, {packet, 0}]); _ -> Connect6 end, 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", [StateData#state.password])); true -> true end, send_text(NewStateData, 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.ident, StateData#state.nick, StateData#state.host, StateData#state.realname])), {next_state, wait_for_registration, NewStateData}; {error, Reason} -> ?DEBUG("connect return ~p~n", [Reason]), Text = case Reason of timeout -> <<"Server Connect Timeout">>; _ -> <<"Server Connect Failed">> end, bounce_messages(Text), {stop, normal, StateData} end. wait_for_registration(closed, StateData) -> {stop, normal, StateData}. stream_established({xmlstreamend, _Name}, StateData) -> {stop, normal, StateData}; stream_established(timeout, StateData) -> {stop, normal, StateData}; stream_established(closed, StateData) -> {stop, normal, 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) -> {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(_Event, _From, StateName, StateData) -> Reply = ok, {reply, Reply, StateName, StateData}. code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. -define(SEND(S), if StateName == stream_established -> send_text(StateData, S), StateData; true -> StateData#state{outbuf = <<(StateData#state.outbuf)/binary, (iolist_to_binary(S))/binary>>} end). get_password_from_presence(#xmlel{name = <<"presence">>, children = Els}) -> case lists:filter(fun (El) -> case El of #xmlel{name = <<"x">>, attrs = Attrs} -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC -> true; _ -> false end; _ -> false end end, Els) of [ElXMUC | _] -> case xml:get_subtag(ElXMUC, <<"password">>) of #xmlel{name = <<"password">>} = PasswordTag -> {true, xml:get_tag_cdata(PasswordTag)}; _ -> false end; _ -> false end. %%---------------------------------------------------------------------- %% Func: handle_info/3 %% Returns: {next_state, NextStateName, NextStateData} | %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- handle_info({route_chan, Channel, Resource, #xmlel{name = <<"presence">>, attrs = Attrs} = Presence}, StateName, StateData) -> NewStateData = case xml:get_attr_s(<<"type">>, Attrs) of <<"unavailable">> -> send_stanza_unavailable(Channel, StateData), S1 = (?SEND((io_lib:format("PART #~s\r\n", [Channel])))), S1#state{channels = dict:erase(Channel, S1#state.channels)}; <<"subscribe">> -> StateData; <<"subscribed">> -> StateData; <<"unsubscribe">> -> StateData; <<"unsubscribed">> -> StateData; <<"error">> -> stop; _ -> Nick = case Resource of <<"">> -> StateData#state.nick; _ -> Resource end, S1 = if Nick /= StateData#state.nick -> S11 = (?SEND((io_lib:format("NICK ~s\r\n", [Nick])))), S11#state{nickchannel = Channel}; true -> StateData end, case dict:is_key(Channel, S1#state.channels) of true -> S1; _ -> case get_password_from_presence(Presence) of {true, Password} -> S2 = (?SEND((io_lib:format("JOIN #~s ~s\r\n", [Channel, Password])))); _ -> S2 = (?SEND((io_lib:format("JOIN #~s\r\n", [Channel])))) end, S2#state{channels = dict:store(Channel, (?SETS):new(), S1#state.channels)} end end, if NewStateData == stop -> {stop, normal, StateData}; true -> case dict:fetch_keys(NewStateData#state.channels) of [] -> {stop, normal, NewStateData}; _ -> {next_state, StateName, NewStateData} end end; handle_info({route_chan, Channel, Resource, #xmlel{name = <<"message">>, attrs = Attrs} = El}, StateName, StateData) -> NewStateData = case xml:get_attr_s(<<"type">>, Attrs) of <<"groupchat">> -> case xml:get_path_s(El, [{elem, <<"subject">>}, cdata]) of <<"">> -> ejabberd_router:route( jid:make( iolist_to_binary([Channel, <<"%">>, StateData#state.server]), StateData#state.host, StateData#state.nick), StateData#state.user, El), Body = xml:get_path_s(El, [{elem, <<"body">>}, cdata]), case Body of <<"/quote ", Rest/binary>> -> ?SEND(<>); <<"/msg ", Rest/binary>> -> ?SEND(<<"PRIVMSG ", Rest/binary, "\r\n">>); <<"/me ", Rest/binary>> -> Strings = str:tokens(Rest, <<"\n">>), Res = iolist_to_binary( lists:map( fun (S) -> io_lib:format( "PRIVMSG #~s :\001ACTION ~s\001\r\n", [Channel, S]) end, Strings)), ?SEND(Res); <<"/ctcp ", Rest/binary>> -> Words = str:tokens(Rest, <<" ">>), case Words of [CtcpDest | _] -> CtcpCmd = str:to_upper( str:substr(Rest, str:str(Rest, <<" ">>) + 1)), Res = io_lib:format("PRIVMSG ~s :\001~s\001\r\n", [CtcpDest, CtcpCmd]), ?SEND(Res); _ -> ok end; _ -> Strings = str:tokens(Body, <<"\n">>), Res = iolist_to_binary( lists:map( fun (S) -> io_lib:format("PRIVMSG #~s :~s\r\n", [Channel, S]) end, Strings)), ?SEND(Res) end; Subject -> Strings = str:tokens(Subject, <<"\n">>), Res = iolist_to_binary( lists:map( fun (S) -> io_lib:format("TOPIC #~s :~s\r\n", [Channel, S]) end, Strings)), ?SEND(Res) end; Type when Type == <<"chat">>; Type == <<"">>; Type == <<"normal">> -> Body = xml:get_path_s(El, [{elem, <<"body">>}, cdata]), case Body of <<"/quote ", Rest/binary>> -> ?SEND(<>); <<"/msg ", Rest/binary>> -> ?SEND(<<"PRIVMSG ", Rest/binary, "\r\n">>); <<"/me ", Rest/binary>> -> Strings = str:tokens(Rest, <<"\n">>), Res = iolist_to_binary( lists:map( fun (S) -> io_lib:format( "PRIVMSG ~s :\001ACTION ~s\001\r\n", [Resource, S]) end, Strings)), ?SEND(Res); <<"/ctcp ", Rest/binary>> -> Words = str:tokens(Rest, <<" ">>), case Words of [CtcpDest | _] -> CtcpCmd = str:to_upper( str:substr(Rest, str:str(Rest, <<" ">>) + 1)), Res = io_lib:format("PRIVMSG ~s :~s\r\n", [CtcpDest, <<"\001", CtcpCmd/binary, "\001">>]), ?SEND(Res); _ -> ok end; _ -> Strings = str:tokens(Body, <<"\n">>), Res = iolist_to_binary( lists:map( fun (S) -> io_lib:format( "PRIVMSG ~s :~s\r\n", [Resource, S]) end, Strings)), ?SEND(Res) end; <<"error">> -> stop; _ -> StateData end, if NewStateData == stop -> {stop, normal, StateData}; true -> {next_state, StateName, NewStateData} end; handle_info({route_chan, Channel, Resource, #xmlel{name = <<"iq">>} = El}, StateName, StateData) -> From = StateData#state.user, To = jid:make(iolist_to_binary([Channel, <<"%">>, StateData#state.server]), StateData#state.host, StateData#state.nick), _ = case jlib:iq_query_info(El) of #iq{xmlns = ?NS_MUC_ADMIN} = IQ -> iq_admin(StateData, Channel, From, To, IQ); #iq{xmlns = ?NS_VERSION} -> Res = io_lib:format("PRIVMSG ~s :\001VERSION\001\r\n", [Resource]), _ = (?SEND(Res)), Err = jlib:make_error_reply(El, ?ERR_FEATURE_NOT_IMPLEMENTED), ejabberd_router:route(To, From, Err); #iq{xmlns = ?NS_TIME} -> Res = io_lib:format("PRIVMSG ~s :\001TIME\001\r\n", [Resource]), _ = (?SEND(Res)), Err = jlib:make_error_reply(El, ?ERR_FEATURE_NOT_IMPLEMENTED), ejabberd_router:route(To, From, Err); #iq{xmlns = ?NS_VCARD} -> Res = io_lib:format("WHOIS ~s \r\n", [Resource]), _ = (?SEND(Res)), Err = jlib:make_error_reply(El, ?ERR_FEATURE_NOT_IMPLEMENTED), ejabberd_router:route(To, From, Err); #iq{} -> Err = jlib:make_error_reply(El, ?ERR_FEATURE_NOT_IMPLEMENTED), ejabberd_router:route(To, From, Err); _ -> ok end, {next_state, StateName, StateData}; handle_info({route_chan, _Channel, _Resource, _Packet}, StateName, StateData) -> {next_state, StateName, StateData}; handle_info({route_nick, Nick, #xmlel{name = <<"message">>, attrs = Attrs} = El}, StateName, StateData) -> NewStateData = case xml:get_attr_s(<<"type">>, Attrs) of <<"chat">> -> Body = xml:get_path_s(El, [{elem, <<"body">>}, cdata]), case Body of <<"/quote ", Rest/binary>> -> ?SEND(<>); <<"/msg ", Rest/binary>> -> ?SEND(<<"PRIVMSG ", Rest/binary, "\r\n">>); <<"/me ", Rest/binary>> -> Strings = str:tokens(Rest, <<"\n">>), Res = iolist_to_binary( lists:map( fun (S) -> io_lib:format( "PRIVMSG ~s :\001ACTION ~s\001\r\n", [Nick, S]) end, Strings)), ?SEND(Res); <<"/ctcp ", Rest/binary>> -> Words = str:tokens(Rest, <<" ">>), case Words of [CtcpDest | _] -> CtcpCmd = str:to_upper( str:substr(Rest, str:str(Rest, <<" ">>) + 1)), Res = io_lib:format("PRIVMSG ~s :~s\r\n", [CtcpDest, <<"\001", CtcpCmd/binary, "\001">>]), ?SEND(Res); _ -> ok end; _ -> Strings = str:tokens(Body, <<"\n">>), Res = iolist_to_binary( lists:map( fun (S) -> io_lib:format( "PRIVMSG ~s :~s\r\n", [Nick, S]) end, Strings)), ?SEND(Res) end; <<"error">> -> stop; _ -> StateData end, if NewStateData == stop -> {stop, normal, StateData}; true -> {next_state, StateName, NewStateData} end; handle_info({route_nick, _Nick, _Packet}, StateName, StateData) -> {next_state, StateName, StateData}; handle_info({ircstring, <<$P, $I, $N, $G, $\s, ID/binary>>}, StateName, StateData) -> send_text(StateData, <<"PONG ", ID/binary, "\r\n">>), {next_state, StateName, StateData}; handle_info({ircstring, <<$:, String/binary>>}, wait_for_registration, StateData) -> Words = str:tokens(String, <<" ">>), {NewState, NewStateData} = case Words of [_, <<"001">> | _] -> send_text(StateData, io_lib:format("CODEPAGE ~s\r\n", [StateData#state.encoding])), {stream_established, StateData}; [_, <<"433">> | _] -> {error, {error, error_nick_in_use(StateData, String), StateData}}; [_, <<$4, _, _>> | _] -> {error, {error, error_unknown_num(StateData, String, <<"cancel">>), StateData}}; [_, <<$5, _, _>> | _] -> {error, {error, error_unknown_num(StateData, String, <<"cancel">>), StateData}}; _ -> ?DEBUG("unknown irc command '~s'~n", [String]), {wait_for_registration, StateData} end, if NewState == error -> {stop, normal, NewStateData}; true -> {next_state, NewState, NewStateData} end; handle_info({ircstring, <<$:, String/binary>>}, _StateName, StateData) -> Words = str:tokens(String, <<" ">>), NewStateData = case Words of [_, <<"353">> | Items] -> process_channel_list(StateData, Items); [_, <<"332">>, _Nick, <<$#, Chan/binary>> | _] -> process_channel_topic(StateData, Chan, String), StateData; [_, <<"333">>, _Nick, <<$#, Chan/binary>> | _] -> process_channel_topic_who(StateData, Chan, String), StateData; [_, <<"318">>, _, Nick | _] -> process_endofwhois(StateData, String, Nick), StateData; [_, <<"311">>, _, Nick, Ident, Irchost | _] -> process_whois311(StateData, String, Nick, Ident, Irchost), StateData; [_, <<"312">>, _, Nick, Ircserver | _] -> process_whois312(StateData, String, Nick, Ircserver), StateData; [_, <<"319">>, _, Nick | _] -> process_whois319(StateData, String, Nick), StateData; [_, <<"433">> | _] -> process_nick_in_use(StateData, String); % CODEPAGE isn't standard, so don't complain if it's not there. [_, <<"421">>, _, <<"CODEPAGE">> | _] -> StateData; [_, <<$4, _, _>> | _] -> process_num_error(StateData, String); [_, <<$5, _, _>> | _] -> process_num_error(StateData, String); [From, <<"PRIVMSG">>, <<$#, Chan/binary>> | _] -> process_chanprivmsg(StateData, Chan, From, String), StateData; [From, <<"NOTICE">>, <<$#, Chan/binary>> | _] -> process_channotice(StateData, Chan, From, String), StateData; [From, <<"PRIVMSG">>, Nick, <<":\001VERSION\001">> | _] -> process_version(StateData, Nick, From), StateData; [From, <<"PRIVMSG">>, Nick, <<":\001USERINFO\001">> | _] -> process_userinfo(StateData, Nick, From), StateData; [From, <<"PRIVMSG">>, Nick | _] -> process_privmsg(StateData, Nick, From, String), StateData; [From, <<"NOTICE">>, Nick | _] -> process_notice(StateData, Nick, From, String), StateData; [From, <<"TOPIC">>, <<$#, Chan/binary>> | _] -> process_topic(StateData, Chan, From, String), StateData; [From, <<"PART">>, <<$#, Chan/binary>> | _] -> process_part(StateData, Chan, From, String); [From, <<"QUIT">> | _] -> process_quit(StateData, From, String); [From, <<"JOIN">>, Chan | _] -> process_join(StateData, Chan, From, String); [From, <<"MODE">>, <<$#, Chan/binary>>, <<"+o">>, Nick | _] -> process_mode_o(StateData, Chan, From, Nick, <<"admin">>, <<"moderator">>), StateData; [From, <<"MODE">>, <<$#, Chan/binary>>, <<"-o">>, Nick | _] -> process_mode_o(StateData, Chan, From, Nick, <<"member">>, <<"participant">>), StateData; [From, <<"KICK">>, <<$#, Chan/binary>>, Nick | _] -> process_kick(StateData, Chan, From, Nick, String), StateData; [From, <<"NICK">>, Nick | _] -> process_nick(StateData, From, Nick); _ -> ?DEBUG("unknown irc command '~s'~n", [String]), StateData end, NewStateData1 = case StateData#state.outbuf of <<"">> -> NewStateData; Data -> send_text(NewStateData, Data), NewStateData#state{outbuf = <<"">>} end, {next_state, stream_established, NewStateData1}; handle_info({ircstring, <<$E, $R, $R, $O, $R, _/binary>> = String}, StateName, StateData) -> process_error(StateData, String), {next_state, StateName, StateData}; handle_info({ircstring, String}, StateName, StateData) -> ?DEBUG("unknown irc command '~s'~n", [String]), {next_state, StateName, StateData}; handle_info({send_text, Text}, StateName, StateData) -> send_text(StateData, Text), {next_state, StateName, StateData}; handle_info({tcp, _Socket, Data}, StateName, StateData) -> Buf = <<(StateData#state.inbuf)/binary, Data/binary>>, Strings = ejabberd_regexp:split(<< <> || <> <= Buf, C /= $\r >>, <<"\n">>), ?DEBUG("strings=~p~n", [Strings]), NewBuf = process_lines(StateData#state.encoding, Strings), {next_state, StateName, StateData#state{inbuf = NewBuf}}; handle_info({tcp_closed, _Socket}, StateName, StateData) -> gen_fsm:send_event(self(), closed), {next_state, StateName, StateData}; handle_info({tcp_error, _Socket, _Reason}, StateName, StateData) -> gen_fsm:send_event(self(), closed), {next_state, StateName, StateData}. %%---------------------------------------------------------------------- %% Func: terminate/3 %% Purpose: Shutdown the fsm %% Returns: any %%---------------------------------------------------------------------- terminate(_Reason, _StateName, FullStateData) -> {Error, StateData} = case FullStateData of {error, SError, SStateData} -> {SError, SStateData}; _ -> {#xmlel{name = <<"error">>, attrs = [{<<"code">>, <<"502">>}], children = [{xmlcdata, <<"Server Connect Failed">>}]}, FullStateData} end, (StateData#state.mod):closed_connection(StateData#state.host, StateData#state.user, StateData#state.server), bounce_messages(<<"Server Connect Failed">>), lists:foreach(fun (Chan) -> Stanza = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"error">>}], children = [Error]}, send_stanza(Chan, StateData, Stanza) end, dict:fetch_keys(StateData#state.channels)), case StateData#state.socket of undefined -> ok; Socket -> gen_tcp:close(Socket) end, ok. send_stanza(Chan, StateData, Stanza) -> ejabberd_router:route( jid:make( iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, StateData#state.nick), StateData#state.user, Stanza). send_stanza_unavailable(Chan, StateData) -> Affiliation = <<"member">>, Role = <<"none">>, Stanza = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, Affiliation}, {<<"role">>, Role}], children = []}, #xmlel{name = <<"status">>, attrs = [{<<"code">>, <<"110">>}], children = []}]}]}, send_stanza(Chan, StateData, Stanza). %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- send_text(#state{socket = Socket, encoding = Encoding}, Text) -> CText = iconv:convert(<<"utf-8">>, Encoding, iolist_to_binary(Text)), gen_tcp:send(Socket, CText). %send_queue(Socket, Q) -> % case queue:out(Q) of % {{value, El}, Q1} -> % send_element(Socket, El), % send_queue(Socket, Q1); % {empty, Q1} -> % ok % end. bounce_messages(Reason) -> receive {send_element, El} -> #xmlel{attrs = Attrs} = El, case xml: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">>, Attrs)), To = jid:from_string(xml:get_attr_s(<<"to">>, Attrs)), ejabberd_router:route(To, From, Err) end, bounce_messages(Reason) after 0 -> ok end. route_chan(Pid, Channel, Resource, Packet) -> Pid ! {route_chan, Channel, Resource, Packet}. route_nick(Pid, Nick, Packet) -> Pid ! {route_nick, Nick, Packet}. process_lines(_Encoding, [S]) -> S; process_lines(Encoding, [S | Ss]) -> self() ! {ircstring, iconv:convert(Encoding, <<"utf-8">>, S)}, process_lines(Encoding, Ss). process_channel_list(StateData, Items) -> process_channel_list_find_chan(StateData, Items). process_channel_list_find_chan(StateData, []) -> StateData; process_channel_list_find_chan(StateData, [<<$#, Chan/binary>> | Items]) -> process_channel_list_users(StateData, Chan, Items); process_channel_list_find_chan(StateData, [_ | Items]) -> process_channel_list_find_chan(StateData, Items). process_channel_list_users(StateData, _Chan, []) -> StateData; process_channel_list_users(StateData, Chan, [User | Items]) -> NewStateData = process_channel_list_user(StateData, Chan, User), process_channel_list_users(NewStateData, Chan, Items). process_channel_list_user(StateData, Chan, User) -> User1 = case User of <<$:, U1/binary>> -> U1; _ -> User end, {User2, Affiliation, Role} = case User1 of <<$@, U2/binary>> -> {U2, <<"admin">>, <<"moderator">>}; <<$+, U2/binary>> -> {U2, <<"member">>, <<"participant">>}; <<$%, U2/binary>> -> {U2, <<"admin">>, <<"moderator">>}; <<$&, U2/binary>> -> {U2, <<"admin">>, <<"moderator">>}; <<$~, U2/binary>> -> {U2, <<"admin">>, <<"moderator">>}; _ -> {User1, <<"member">>, <<"participant">>} end, ejabberd_router:route(jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, User2), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, Affiliation}, {<<"role">>, Role}], children = []}]}]}), case catch dict:update(Chan, fun (Ps) -> (?SETS):add_element(User2, Ps) end, StateData#state.channels) of {'EXIT', _} -> StateData; NS -> StateData#state{channels = NS} end. process_channel_topic(StateData, Chan, String) -> Msg = ejabberd_regexp:replace(String, <<".*332[^:]*:">>, <<"">>), Msg1 = filter_message(Msg), ejabberd_router:route(jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}], children = [#xmlel{name = <<"subject">>, attrs = [], children = [{xmlcdata, Msg1}]}, #xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, <<"Topic for #", Chan/binary, ": ", Msg1/binary>>}]}]}). process_channel_topic_who(StateData, Chan, String) -> Words = str:tokens(String, <<" ">>), Msg1 = case Words of [_, <<"333">>, _, _Chan, Whoset, Timeset] -> {Unixtimeset, _Rest} = str:to_integer(Timeset), <<"Topic for #", Chan/binary, " set by ", Whoset/binary, " at ", (unixtime2string(Unixtimeset))/binary>>; [_, <<"333">>, _, _Chan, Whoset | _] -> <<"Topic for #", Chan/binary, " set by ", Whoset/binary>>; _ -> String end, Msg2 = filter_message(Msg1), ejabberd_router:route(jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Msg2}]}]}). error_nick_in_use(_StateData, String) -> Msg = ejabberd_regexp:replace(String, <<".*433 +[^ ]* +">>, <<"">>), Msg1 = filter_message(Msg), #xmlel{name = <<"error">>, attrs = [{<<"code">>, <<"409">>}, {<<"type">>, <<"cancel">>}], children = [#xmlel{name = <<"conflict">>, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = []}, #xmlel{name = <<"text">>, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = [{xmlcdata, Msg1}]}]}. process_nick_in_use(StateData, String) -> Error = error_nick_in_use(StateData, String), case StateData#state.nickchannel of undefined -> % Shouldn't happen with a well behaved server StateData; Chan -> ejabberd_router:route(jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, StateData#state.nick), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"error">>}], children = [Error]}), StateData#state{nickchannel = undefined} end. process_num_error(StateData, String) -> Error = error_unknown_num(StateData, String, <<"continue">>), lists:foreach(fun (Chan) -> ejabberd_router:route( jid:make( iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, StateData#state.nick), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"error">>}], children = [Error]}) end, dict:fetch_keys(StateData#state.channels)), StateData. process_endofwhois(StateData, _String, Nick) -> ejabberd_router:route(jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, <<"End of WHOIS">>}]}]}). process_whois311(StateData, String, Nick, Ident, Irchost) -> Fullname = ejabberd_regexp:replace(String, <<".*311[^:]*:">>, <<"">>), ejabberd_router:route(jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, iolist_to_binary( [<<"WHOIS: ">>, Nick, <<" is ">>, Ident, <<"@">>, Irchost, <<" : ">>, Fullname])}]}]}). process_whois312(StateData, String, Nick, Ircserver) -> Ircserverdesc = ejabberd_regexp:replace(String, <<".*312[^:]*:">>, <<"">>), ejabberd_router:route(jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, iolist_to_binary( [<<"WHOIS: ">>, Nick, <<" use ">>, Ircserver, <<" : ">>, Ircserverdesc])}]}]}). process_whois319(StateData, String, Nick) -> Chanlist = ejabberd_regexp:replace(String, <<".*319[^:]*:">>, <<"">>), ejabberd_router:route(jid:make(iolist_to_binary( [Nick, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, iolist_to_binary( [<<"WHOIS: ">>, Nick, <<" is on ">>, Chanlist])}]}]}). process_chanprivmsg(StateData, Chan, From, String) -> [FromUser | _] = str:tokens(From, <<"!">>), Msg = ejabberd_regexp:replace(String, <<".*PRIVMSG[^:]*:">>, <<"">>), Msg1 = case Msg of <<1, $A, $C, $T, $I, $O, $N, $\s, Rest/binary>> -> <<"/me ", Rest/binary>>; _ -> Msg end, Msg2 = filter_message(Msg1), ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, FromUser), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Msg2}]}]}). process_channotice(StateData, Chan, From, String) -> [FromUser | _] = str:tokens(From, <<"!">>), Msg = ejabberd_regexp:replace(String, <<".*NOTICE[^:]*:">>, <<"">>), Msg1 = case Msg of <<1, $A, $C, $T, $I, $O, $N, $\s, Rest/binary>> -> <<"/me ", Rest/binary>>; _ -> <<"/me NOTICE: ", Msg/binary>> end, Msg2 = filter_message(Msg1), ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, FromUser), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Msg2}]}]}). process_privmsg(StateData, _Nick, From, String) -> [FromUser | _] = str:tokens(From, <<"!">>), Msg = ejabberd_regexp:replace(String, <<".*PRIVMSG[^:]*:">>, <<"">>), Msg1 = case Msg of <<1, $A, $C, $T, $I, $O, $N, $\s, Rest/binary>> -> <<"/me ", Rest/binary>>; _ -> Msg end, Msg2 = filter_message(Msg1), ejabberd_router:route(jid:make(iolist_to_binary( [FromUser, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Msg2}]}]}). process_notice(StateData, _Nick, From, String) -> [FromUser | _] = str:tokens(From, <<"!">>), Msg = ejabberd_regexp:replace(String, <<".*NOTICE[^:]*:">>, <<"">>), Msg1 = case Msg of <<1, $A, $C, $T, $I, $O, $N, $\s, Rest/binary>> -> <<"/me ", Rest/binary>>; _ -> <<"/me NOTICE: ", Msg/binary>> end, Msg2 = filter_message(Msg1), ejabberd_router:route(jid:make(iolist_to_binary( [FromUser, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Msg2}]}]}). process_version(StateData, _Nick, From) -> [FromUser | _] = str:tokens(From, <<"!">>), send_text(StateData, io_lib:format("NOTICE ~s :\001VERSION ejabberd IRC " "transport ~s (c) Alexey Shchepin\001\r\n", [FromUser, ?VERSION]) ++ io_lib:format("NOTICE ~s :\001VERSION http://ejabberd.jabber" "studio.org/\001\r\n", [FromUser])). process_userinfo(StateData, _Nick, From) -> [FromUser | _] = str:tokens(From, <<"!">>), send_text(StateData, io_lib:format("NOTICE ~s :\001USERINFO xmpp:~s\001\r\n", [FromUser, 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(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, FromUser), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}], children = [#xmlel{name = <<"subject">>, attrs = [], children = [{xmlcdata, Msg1}]}, #xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, <<"/me has changed the subject to: ", Msg1/binary>>}]}]}). process_part(StateData, Chan, From, String) -> [FromUser | FromIdent] = str:tokens(From, <<"!">>), Msg = ejabberd_regexp:replace(String, <<".*PART[^:]*:">>, <<"">>), Msg1 = filter_message(Msg), ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, FromUser), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, <<"member">>}, {<<"role">>, <<"none">>}], children = []}]}, #xmlel{name = <<"status">>, attrs = [], children = [{xmlcdata, list_to_binary( [Msg1, " (", FromIdent, ")"])}]}]}), case catch dict:update(Chan, fun (Ps) -> remove_element(FromUser, Ps) end, StateData#state.channels) of {'EXIT', _} -> StateData; NS -> StateData#state{channels = NS} end. process_quit(StateData, From, String) -> [FromUser | FromIdent] = str:tokens(From, <<"!">>), Msg = ejabberd_regexp:replace(String, <<".*QUIT[^:]*:">>, <<"">>), Msg1 = filter_message(Msg), dict:map(fun (Chan, Ps) -> case (?SETS):is_member(FromUser, Ps) of true -> ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, FromUser), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, <<"member">>}, {<<"role">>, <<"none">>}], children = []}]}, #xmlel{name = <<"status">>, attrs = [], children = [{xmlcdata, list_to_binary( [Msg1, " (", FromIdent, ")"])}]}]}), remove_element(FromUser, Ps); _ -> Ps end end, StateData#state.channels), StateData. process_join(StateData, Channel, From, _String) -> [FromUser | FromIdent] = str:tokens(From, <<"!">>), [Chan | _] = binary:split(Channel, <<":#">>), ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, FromUser), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, <<"member">>}, {<<"role">>, <<"participant">>}], children = []}]}, #xmlel{name = <<"status">>, attrs = [], children = [{xmlcdata, list_to_binary(FromIdent)}]}]}), case catch dict:update(Chan, fun (Ps) -> (?SETS):add_element(FromUser, Ps) end, StateData#state.channels) of {'EXIT', _} -> StateData; NS -> StateData#state{channels = NS} end. process_mode_o(StateData, Chan, _From, Nick, Affiliation, Role) -> ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, Nick), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, Affiliation}, {<<"role">>, Role}], children = []}]}]}). process_kick(StateData, Chan, From, Nick, String) -> Msg = lists:last(str:tokens(String, <<":">>)), Msg2 = <>, ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, <<"">>), StateData#state.user, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Msg2}]}]}), ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, Nick), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, <<"none">>}, {<<"role">>, <<"none">>}], children = []}, #xmlel{name = <<"status">>, attrs = [{<<"code">>, <<"307">>}], children = []}]}]}). process_nick(StateData, From, NewNick) -> [FromUser | _] = str:tokens(From, <<"!">>), [Nick | _] = binary:split(NewNick, <<":">>), NewChans = dict:map(fun (Chan, Ps) -> case (?SETS):is_member(FromUser, Ps) of true -> ejabberd_router:route(jid:make( iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, FromUser), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, <<"member">>}, {<<"role">>, <<"participant">>}, {<<"nick">>, Nick}], children = []}, #xmlel{name = <<"status">>, attrs = [{<<"code">>, <<"303">>}], children = []}]}]}), ejabberd_router:route(jid:make( iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, Nick), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [], children = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"affiliation">>, <<"member">>}, {<<"role">>, <<"participant">>}], children = []}]}]}), (?SETS):add_element(Nick, remove_element(FromUser, Ps)); _ -> Ps end end, StateData#state.channels), if FromUser == StateData#state.nick -> StateData#state{nick = Nick, nickchannel = undefined, channels = NewChans}; true -> StateData#state{channels = NewChans} end. process_error(StateData, String) -> lists:foreach(fun (Chan) -> ejabberd_router:route(jid:make( iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), StateData#state.host, StateData#state.nick), StateData#state.user, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"error">>}], children = [#xmlel{name = <<"error">>, attrs = [{<<"code">>, <<"502">>}], children = [{xmlcdata, String}]}]}) end, dict:fetch_keys(StateData#state.channels)). error_unknown_num(_StateData, String, Type) -> Msg = ejabberd_regexp:replace(String, <<".*[45][0-9][0-9] +[^ ]* +">>, <<"">>), Msg1 = filter_message(Msg), #xmlel{name = <<"error">>, attrs = [{<<"code">>, <<"500">>}, {<<"type">>, Type}], children = [#xmlel{name = <<"undefined-condition">>, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = []}, #xmlel{name = <<"text">>, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = [{xmlcdata, Msg1}]}]}. remove_element(E, Set) -> case (?SETS):is_element(E, Set) of true -> (?SETS):del_element(E, Set); _ -> Set end. iq_admin(StateData, Channel, From, To, #iq{type = Type, xmlns = XMLNS, sub_el = SubEl} = IQ) -> case catch process_iq_admin(StateData, Channel, Type, SubEl) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); Res -> if Res /= ignore -> ResIQ = case Res of {result, ResEls} -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, XMLNS}], children = ResEls}]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end, ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)); true -> ok end end. process_iq_admin(StateData, Channel, set, SubEl) -> case xml: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">>, ItemEl), Role = xml:get_tag_attr_s(<<"role">>, ItemEl), Reason = xml:get_path_s(ItemEl, [{elem, <<"reason">>}, cdata]), process_admin(StateData, Channel, Nick, Affiliation, Role, Reason) end; process_iq_admin(_StateData, _Channel, get, _SubEl) -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED}. process_admin(_StateData, _Channel, <<"">>, _Affiliation, _Role, _Reason) -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED}; process_admin(StateData, Channel, Nick, _Affiliation, <<"none">>, Reason) -> case Reason of <<"">> -> send_text(StateData, io_lib:format("KICK #~s ~s\r\n", [Channel, Nick])); _ -> send_text(StateData, io_lib:format("KICK #~s ~s :~s\r\n", [Channel, Nick, Reason])) end, {result, []}; process_admin(_StateData, _Channel, _Nick, _Affiliation, _Role, _Reason) -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED}. filter_message(Msg) -> list_to_binary( lists:filter(fun (C) -> if (C < 32) and (C /= 9) and (C /= 10) and (C /= 13) -> false; true -> true end end, binary_to_list(filter_mirc_colors(Msg)))). filter_mirc_colors(Msg) -> ejabberd_regexp:greplace(Msg, <<"(\\003[0-9]+)(,[0-9]+)?">>, <<"">>). unixtime2string(Unixtime) -> Secs = Unixtime + calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}), {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:universal_time_to_local_time(calendar:gregorian_seconds_to_datetime(Secs)), iolist_to_binary(io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w", [Year, Month, Day, Hour, Minute, Second])). ejabberd-16.01/src/jd2ejd.erl0000644000232200023220000001214712645157216016300 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : jd2ejd.erl %%% Author : Alexey Shchepin %%% Purpose : Import of jabberd14 user spool file %%% Created : 2 Feb 2003 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(jd2ejd). -author('alexey@process-one.net'). %% External exports -export([import_file/1, import_dir/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- import_file(File) -> User = filename:rootname(filename:basename(File)), Server = filename:basename(filename:dirname(File)), case jid:nodeprep(User) /= error andalso jid:nameprep(Server) /= error of true -> case file:read_file(File) of {ok, Text} -> case xml_stream:parse_element(Text) of El when is_record(El, xmlel) -> case catch process_xdb(User, Server, El) of {'EXIT', Reason} -> ?ERROR_MSG("Error while processing file \"~s\": " "~p~n", [File, Reason]), {error, Reason}; _ -> ok end; {error, Reason} -> ?ERROR_MSG("Can't parse file \"~s\": ~p~n", [File, Reason]), {error, Reason} end; {error, Reason} -> ?ERROR_MSG("Can't read file \"~s\": ~p~n", [File, Reason]), {error, Reason} end; false -> ?ERROR_MSG("Illegal user/server name in file \"~s\"~n", [File]), {error, <<"illegal user/server">>} end. import_dir(Dir) -> {ok, Files} = file:list_dir(Dir), MsgFiles = lists:filter(fun (FN) -> case length(FN) > 4 of true -> string:substr(FN, length(FN) - 3) == ".xml"; _ -> false end end, Files), lists:foldl(fun (FN, A) -> Res = import_file(filename:join([Dir, FN])), case {A, Res} of {ok, ok} -> ok; {ok, _} -> {error, <<"see ejabberd log for details">>}; _ -> A end end, ok, MsgFiles). %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- process_xdb(User, Server, #xmlel{name = Name, children = Els}) -> case Name of <<"xdb">> -> lists:foreach(fun (El) -> xdb_data(User, Server, El) end, Els); _ -> ok end. 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 ?NS_AUTH -> Password = xml: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), catch mod_last:store_last_info(User, Server, jlib:binary_to_integer(TimeStamp), Status), ok; ?NS_VCARD -> catch mod_vcard:process_sm_iq(From, jid:make(<<"">>, Server, <<"">>), #iq{type = set, xmlns = ?NS_VCARD, sub_el = El}), ok; <<"jabber:x:offline">> -> process_offline(Server, From, El), ok; XMLNS -> case xml:get_attr_s(<<"j_private_flag">>, Attrs) of <<"1">> -> catch mod_private:process_sm_iq(From, jid:make(<<"">>, Server, <<"">>), #iq{type = set, xmlns = ?NS_PRIVATE, sub_el = #xmlel{name = <<"query">>, attrs = [], children = [jlib:remove_attr(<<"j_private_flag">>, jlib:remove_attr(<<"xdbns">>, El))]}}); _ -> ?DEBUG("jd2ejd: Unknown namespace \"~s\"~n", [XMLNS]) end, ok end. 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), From = case FromS of <<"">> -> jid:make(<<"">>, Server, <<"">>); _ -> jid:from_string(FromS) end, case From of error -> ok; _ -> ejabberd_hooks:run(offline_message_hook, LServer, [From, To, El]) end end, Els). ejabberd-16.01/src/node_hometree_odbc.erl0000644000232200023220000001315412645157216020741 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_hometree_odbc.erl %%% Author : Christophe Romain %%% Purpose : Standard tree ordered node plugin with ODBC backend %%% Created : 1 Dec 2007 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_hometree_odbc). -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, get_entity_subscriptions_for_send_last/2, get_last_items/3]). 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) -> node_flat_odbc:terminate(Host, ServerHost). options() -> [{odbc, true}, {rsm, true} | node_hometree:options()]. features() -> [<<"rsm">> | node_hometree:features()]. 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_flat_odbc:create_node(Nidx, Owner). delete_node(Nodes) -> node_flat_odbc:delete_node(Nodes). 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_entity_subscriptions_for_send_last(Host, Owner) -> node_flat_odbc:get_entity_subscriptions_for_send_last(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). 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). path_to_node(Path) -> node_hometree:path_to_node(Path). ejabberd-16.01/src/ejd2odbc.erl0000644000232200023220000002236012645157216016610 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejd2odbc.erl %%% Author : Alexey Shchepin %%% Purpose : Export some mnesia tables to SQL DB %%% Created : 22 Aug 2005 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(ejd2odbc). -author('alexey@process-one.net'). -include("logger.hrl"). -export([export/2, export/3, import_file/2, import/2, import/3]). -define(MAX_RECORDS_PER_TRANSACTION, 100). -record(dump, {fd, cont = start}). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- %%% How to use: %%% A table can be converted from Mnesia to an ODBC database by calling %%% one of the API function with the following parameters: %%% - Server is the server domain you want to convert %%% - Output can be either odbc to export to the configured relational %%% database or "Filename" to export to text file. modules() -> [ejabberd_auth, mod_announce, mod_irc, mod_last, mod_muc, mod_offline, mod_privacy, mod_private, %% mod_pubsub, mod_roster, mod_shared_roster, mod_vcard, mod_vcard_xupdate]. export(Server, Output) -> LServer = jid:nameprep(iolist_to_binary(Server)), Modules = modules(), IO = prepare_output(Output), lists:foreach( fun(Module) -> export(LServer, IO, Module) end, Modules), close_output(Output, IO). export(Server, Output, Module) -> LServer = jid:nameprep(iolist_to_binary(Server)), IO = prepare_output(Output), lists:foreach( fun({Table, ConvertFun}) -> export(LServer, Table, IO, ConvertFun) end, Module:export(Server)), close_output(Output, IO). import_file(Server, FileName) when is_binary(FileName) -> import(Server, binary_to_list(FileName)); import_file(Server, FileName) -> case disk_log:open([{name, make_ref()}, {file, FileName}, {mode, read_only}]) of {ok, Fd} -> 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, ejabberd_auth:auth_modules(LServer)) of true -> [{ejabberd_auth, mnesia}]; false -> [] end, import_dump(LServer, AuthMods ++ Mods, #dump{fd = Fd}); Err -> exit(Err) end. import(Server, Output) -> import(Server, Output, [{fast, true}]). import(Server, Output, Opts) -> LServer = jid:nameprep(iolist_to_binary(Server)), Modules = modules(), IO = prepare_output(Output, disk_log), lists:foreach( fun(Module) -> import(LServer, IO, Opts, Module) end, Modules), close_output(Output, IO). import(Server, Output, Opts, Module) -> LServer = jid:nameprep(iolist_to_binary(Server)), IO = prepare_output(Output, disk_log), lists:foreach( fun({SelectQuery, ConvertFun}) -> import(LServer, SelectQuery, IO, ConvertFun, Opts) end, Module:import(Server)), close_output(Output, IO). %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- export(LServer, Table, IO, ConvertFun) -> F = fun () -> mnesia:read_lock_table(Table), {_N, SQLs} = mnesia:foldl( fun(R, {N, SQLs} = Acc) -> case ConvertFun(LServer, R) of [] -> Acc; SQL -> if N < (?MAX_RECORDS_PER_TRANSACTION) - 1 -> {N + 1, [SQL | SQLs]}; true -> output(LServer, Table, IO, flatten([SQL | SQLs])), {0, []} end end end, {0, []}, Table), output(LServer, Table, IO, flatten(SQLs)) end, mnesia:transaction(F). output(_LServer, _Table, _IO, []) -> ok; output(LServer, _Table, odbc, SQLs) -> ejabberd_odbc:sql_transaction(LServer, SQLs); output(_LServer, Table, Fd, SQLs) -> file:write(Fd, ["-- \n-- Mnesia table: ", atom_to_list(Table), "\n--\n", SQLs]). import(LServer, SelectQuery, IO, ConvertFun, Opts) -> F = case proplists:get_bool(fast, Opts) of true -> fun() -> case ejabberd_odbc:sql_query_t(SelectQuery) of {selected, _, Rows} -> lists:foldl(fun process_sql_row/2, {IO, ConvertFun, undefined}, Rows); Err -> erlang:error(Err) end end; false -> fun() -> ejabberd_odbc:sql_query_t( [iolist_to_binary( [<<"declare c cursor for ">>, SelectQuery])]), fetch(IO, ConvertFun, undefined) end end, ejabberd_odbc:sql_transaction(LServer, F). fetch(IO, ConvertFun, PrevRow) -> case ejabberd_odbc:sql_query_t([<<"fetch c;">>]) of {selected, _, [Row]} -> process_sql_row(Row, {IO, ConvertFun, PrevRow}), fetch(IO, ConvertFun, Row); {selected, _, []} -> ok; Err -> erlang:error(Err) end. process_sql_row(Row, {IO, ConvertFun, PrevRow}) when Row == PrevRow -> %% Avoid calling ConvertFun with the same input {IO, ConvertFun, Row}; process_sql_row(Row, {IO, ConvertFun, _PrevRow}) -> case catch ConvertFun(Row) of {'EXIT', _} = Err -> ?ERROR_MSG("failed to convert ~p: ~p", [Row, Err]); Term -> ok = disk_log:log(IO#dump.fd, Term) end, {IO, ConvertFun, Row}. import_dump(LServer, Mods, #dump{fd = Fd, cont = Cont}) -> case disk_log:chunk(Fd, Cont) of {NewCont, Terms} -> import_terms(LServer, Mods, Terms), import_dump(LServer, Mods, #dump{fd = Fd, cont = NewCont}); eof -> ok; Err -> exit(Err) end. import_terms(LServer, Mods, [Term|Terms]) -> import_term(LServer, Mods, Term), import_terms(LServer, Mods, Terms); import_terms(_LServer, _Mods, []) -> ok. import_term(LServer, [{Mod, DBType}|Mods], Term) -> case catch Mod:import(LServer, DBType, Term) of pass -> import_term(LServer, Mods, Term); ok -> ok; Err -> ?ERROR_MSG("failed to import ~p for module ~p: ~p", [Term, Mod, Err]) end; import_term(_LServer, [], _Term) -> ok. prepare_output(FileName) -> prepare_output(FileName, normal). prepare_output(FileName, Type) when is_binary(FileName) -> prepare_output(binary_to_list(FileName), Type); prepare_output(FileName, normal) when is_list(FileName) -> case file:open(FileName, [write, raw]) of {ok, Fd} -> Fd; Err -> exit(Err) end; prepare_output(FileName, disk_log) when is_list(FileName) -> case disk_log:open([{name, make_ref()}, {repair, truncate}, {file, FileName}]) of {ok, Fd} -> #dump{fd = Fd}; Err -> exit(Err) end; prepare_output(Output, _Type) -> Output. close_output(FileName, Fd) when FileName /= Fd -> case Fd of #dump{} -> disk_log:close(Fd#dump.fd); _ -> file:close(Fd) end, ok; close_output(_, _) -> ok. flatten(SQLs) -> flatten(SQLs, []). flatten([L|Ls], Acc) -> flatten(Ls, flatten1(lists:reverse(L), Acc)); flatten([], Acc) -> Acc. flatten1([H|T], Acc) -> flatten1(T, [[H, $\n]|Acc]); flatten1([], Acc) -> Acc. ejabberd-16.01/src/mod_http_api.erl0000644000232200023220000003234712645157216017611 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% 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 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}}; 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]. ejabberd-16.01/src/mod_pubsub.erl0000644000232200023220000045015412645157216017301 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_pubsub.erl %%% Author : Christophe Romain %%% Purpose : Publish Subscribe service (XEP-0060) %%% Created : 1 Dec 2007 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. %%% %%%---------------------------------------------------------------------- %%% 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). -behaviour(gen_mod). -behaviour(gen_server). -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"). -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_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, 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, 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, service_jid/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, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([send_loop/1, mod_opt_type/1]). -define(PROCNAME, ejabberd_mod_pubsub). -define(LOOPNAME, ejabberd_mod_pubsub_loop). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- -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(), 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(), 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 :: {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 :: 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, max_subscriptions_node = undefined, default_node_config = [], 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(), max_subscriptions_node :: non_neg_integer()|undefined, default_node_config :: [{atom(), binary()|boolean()|integer()|atom()}], 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], []). 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 :: ( [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), 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 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, 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), 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}), 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_add, ServerHost, ?MODULE, caps_add, 80), 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), pubsub_migrate:update_node_database(Host, ServerHost), pubsub_migrate:update_state_database(Host, ServerHost), pubsub_migrate:update_lastitem_database(Host, ServerHost), {_, State} = init_send_loop(ServerHost), {ok, 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), 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 %% 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 = 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]), 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 = 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 = plugin(Host, Name), Plugin:terminate(Host, ServerHost) end, Plugins), TreePlugin:terminate(Host, ServerHost), ok. send_loop(State) -> receive {presence, JID, Pid} -> Host = State#state.host, ServerHost = State#state.server_host, DBType = State#state.db_type, 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), 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 = jid:make(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 = 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 -> 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 end. %% ------- %% disco hooks handling functions %% -spec(disco_local_identity/5 :: ( 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">>}]} | Acc]; false -> Acc end; disco_local_identity(Acc, _From, _To, _Node, _Lang) -> Acc. -spec(disco_local_features/5 :: ( 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 ++ [feature(F) || F <- 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(jid:tolower(jid:remove_resource(To)), Node, From) ++ Acc. disco_identity(_Host, <<>>, _From) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"pubsub">>}, {<<"type">>, <<"pep">>}]}]; disco_identity(Host, Node, From) -> 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; _ -> [] 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(jid:tolower(jid:remove_resource(To)), Node, From)}; disco_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. disco_features(Host, <<>>, _From) -> [?NS_PUBSUB | [feature(F) || F <- plugin_features(Host, <<"pep">>)]]; disco_features(Host, Node, From) -> 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; _ -> [] 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(jid:tolower(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 = {_, 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">>, 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 = 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">>, 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; _ -> [] end. %% ------- %% presence hooks handling functions %% 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_add hook instead of the %% presence_probe_hook for remote contacts: The latter is only called when a %% 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_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}); 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_add ok. presence(ServerHost, Presence) -> {SendLoop, _} = case whereis(gen_mod:get_module_proc(ServerHost, ?LOOPNAME)) of undefined -> init_send_loop(ServerHost); Pid -> {Pid, undefined} end, SendLoop ! Presence. %% ------- %% subscription hooks handling functions %% out_subscription(User, Server, JID, subscribed) -> Owner = jid:make(User, Server, <<>>), {PUser, PServer, PResource} = 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(jid:make(User, Server, <<>>), Owner), true; in_subscription(_, _, _, _, _, _) -> true. unsubscribe_user(Entity, Owner) -> spawn(fun () -> [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 = jid:tolower(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 %% remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), Entity = jid:make(LUser, LServer, <<>>), Host = host(LServer), HomeTreeBase = <<"/home/", LServer/binary, "/", LUser/binary>>, spawn(fun () -> 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, Affs) 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_add, ServerHost, ?MODULE, caps_add, 80), 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), 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} %% 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), 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) 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 -> 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">>}]}, {result, [IdentityEl]}; command_disco_info(_Host, ?NS_PUBSUB_GET_PENDING, _From) -> IdentityEl = #xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"automation">>}, {<<"type">>, <<"command-node">>}]}, FeaturesEl = #xmlel{name = <<"feature">>, 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, options = Options}) -> NodeType = case get_option(Options, node_type) of collection -> <<"collection">>; _ -> <<"leaf">> end, 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]} 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">>)}]}, #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/4 :: ( Host :: mod_pubsub:host(), Node :: <<>> | mod_pubsub:nodeId(), From :: jid(), Rsm :: none | rsm_in()) -> {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} 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] -> 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()) -> iq_result() | iq_error() ). iq_sm(From, To, #iq{type = Type, sub_el = SubEl, xmlns = XMLNS, lang = Lang} = IQ) -> ServerHost = To#jid.lserver, LOwner = jid:tolower(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)), 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()) -> {result, [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} 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}. %% @doc

Sends the process pending subscriptions XForm for Host to Owner.

send_pending_node_form(Host, Owner, _Lang, Plugins) -> 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 = [#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(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. %% @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", [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, Subs}} -> lists:foreach(fun ({J, pending, _SubId}) -> send_authorization_request(N, jid:make(J)); ({J, pending}) -> send_authorization_request(N, jid:make(J)); (_) -> ok end, Subs), #adhoc_response{}; Err -> Err end. %%% authorization handling 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 = <<"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, 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), jid:make(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)), 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. %% @doc Send a message to JID with the supplied Subscription 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(<<"subscription">>, [{<<"jid">>, 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]}}} -> FromLJID = jid:tolower(jid:remove_resource(From)), Subscriber = jid:from_string(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, 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}]}]}). -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 = [#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)). -define(LISTMXFIELD(Label, Var, Vals, Opts), #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 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:

%%
    %%
  • 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
  • %%
-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, 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 -> 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(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(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)}]}], 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, {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. %% @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.
  • %%
-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 = 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 = serverhost(Host), case transaction(Host, Node, Action, transaction) of {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, {_, {_, {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, {_, 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. %% @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.
  • %%
-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) -> 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, []), 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">>)}; 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">>)}; 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, 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, [#xmlel{name = <<"pubsub">>, attrs = [{<<"xmlns">>, ?NS_PUBSUB}], children = [#xmlel{name = <<"subscription">>, attrs = [{<<"jid">>, jid:to_string(Subscriber)} | SubAttrs]}]}] end, case transaction(Host, Node, Action, sync_dirty) of {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. %% @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) -> unsubscribe_node(Host, Node, From, string_to_ljid(JID), SubId); unsubscribe_node(Host, Node, From, Subscriber, SubId) -> 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 end. %% @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 = 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)}]}]}], case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, Broadcast, Removed}}} -> 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 -> 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}}} -> Nidx = TNode#pubsub_node.id, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, broadcast_retract_items(Host, Node, Nidx, Type, Options, Removed), set_cached_item(Host, Nidx, ItemId, Publisher, Payload), {result, Reply}; {result, {TNode, {Result, Removed}}} -> Nidx = TNode#pubsub_node.id, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, 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} -> Type = select_type(ServerHost, Host, Node), 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}]}]}]} -> publish_item(Host, ServerHost, NewNode, Publisher, ItemId, Payload); _ -> {error, ?ERR_ITEM_NOT_FOUND} end; false -> {error, ?ERR_ITEM_NOT_FOUND} end; Error -> Error end. %% @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.
  • %%
-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(Host, Node, Publisher, ItemId, ForceNotify) -> 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}}} -> 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. %% @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 = 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}}} -> 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.

%%

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 :: none | rsm_in()) -> {result, [xmlel(),...]} %%% | {error, xmlel()} ). get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) -> MaxItems = if SMaxItems == <<>> -> 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}; Val -> Val end end, case MaxItems of {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 = 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 end. get_item(Host, Node, ItemId) -> 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 end. get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) -> case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, none) of {result, {Items, _RSM}} -> {result, Items}; 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, []), {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, Nidx, Type, Options, LJID, last) -> case get_last_item(Host, Type, Nidx, LJID) of undefined -> ok; LastItem -> 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, 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, Options, []), dispatch_items(Host, LJID, Node, 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; _ -> 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), jid:make(To), Stanza) end; 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 :: ( Host :: mod_pubsub:host(), Node :: mod_pubsub:nodeId(), JID :: jid(), Plugins :: [binary()]) -> {result, [xmlel(),...]} %%% | {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, 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()) -> {result, [xmlel(),...]} %%% | {error, xmlel()} ). get_affiliations(Host, Node, JID) -> 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, {_, Affs}} -> Entities = lists:flatmap(fun ({_, none}) -> []; ({AJID, Aff}) -> [#xmlel{name = <<"affiliation">>, attrs = [{<<"jid">>, 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()]) -> {result, []} %%% | {error, xmlel()} ). set_affiliations(Host, Node, From, EntitiesEls) -> Owner = jid:tolower(jid:remove_resource(From)), Entities = lists:foldl(fun (_, error) -> error; (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)), if (JID == error) or (Affiliation == false) -> error; true -> [{jid:tolower(JID), Affiliation} | Acc] end end end, [], EntitiesEls), case Entities of 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 = jid:make(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 = jid:tolower(jid:remove_resource(JID)), NewOwners = [NewOwner | Owners], tree_call(Host, set_node, [N#pubsub_node{owners = NewOwners}]); none -> OldOwner = jid:tolower(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 = 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 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(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} = SubModule:get_options_xform(Lang, Options), [XdataEl] end, OptionsEl = #xmlel{name = <<"options">>, attrs = [{<<"jid">>, 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 = 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 end. 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(_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()] %% @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 = 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 = 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, 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">>, jid:to_string(SubJID)}, {<<"subid">>, SubId}, {<<"subscription">>, subscription_to_string(Sub)} | nodeAttr(SubsNode)]}]; SubsNode -> [#xmlel{name = <<"subscription">>, attrs = [{<<"jid">>, 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">>, jid:to_string(SubJID)}, {<<"subscription">>, subscription_to_string(Sub)} | nodeAttr(SubsNode)]}]; SubsNode -> [#xmlel{name = <<"subscription">>, attrs = [{<<"jid">>, 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 = 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, {_, Subs}} -> Entities = lists:flatmap(fun ({_, none}) -> []; ({_, pending, _}) -> []; ({AJID, Sub}) -> [#xmlel{name = <<"subscription">>, attrs = [{<<"jid">>, jid:to_string(AJID)}, {<<"subscription">>, subscription_to_string(Sub)}]}]; ({AJID, Sub, SubId}) -> [#xmlel{name = <<"subscription">>, attrs = [{<<"jid">>, 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 = jid:tolower(jid:remove_resource(From)), Entities = lists:foldl(fun (_, error) -> error; (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), if (JID == error) or (Sub == false) -> error; true -> [{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">>, jid:to_string(JID)}, {<<"subscription">>, subscription_to_string(Sub)} | nodeAttr(Node)]}]}]}, 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), 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()]) -> {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. get_roster_info(_, _, {<<>>, <<>>, _}, _) -> {false, false}; 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}, 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, jid:tolower(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; 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(publish_only) -> <<"publish-only">>; 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). 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}) -> p1_time_compat:timestamp() < When; sub_option_can_deliver(_, _, _) -> true. -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) -> 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()]) -> [ljid()] ). get_resource_state({U, S, R}, ShowValues, JIDs) -> case ejabberd_sm:get_session_pid(U, S, R) of 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()) -> Count :: non_neg_integer() ). 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). items_event_stanza(Node, Options, 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">>, jid:to_string(ModifUSR)}, {<<"stamp">>, <>}], children = [{xmlcdata, <<>>}]}]; _ -> [] end, BaseStanza = event_stanza_with_els([#xmlel{name = <<"items">>, attrs = nodeAttr(Node), children = itemsEls(Items)}], MoreEls), NotificationType = get_option(Options, notification_type, headline), add_message_type(BaseStanza, NotificationType). 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} | MoreEls]}. event_stanza(Event, EvAttr) -> event_stanza_with_els([#xmlel{name = Event, attrs = EvAttr}], []). %%%%%% broadcast functions 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 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, Nidx, 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, Nidx, Type, NodeOptions, SubsByDepth, items, RetractStanza, true); _ -> ok end end, {result, true}; _ -> {result, false} end. 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, 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, Nidx, Type, NodeOptions, SubsByDepth, items, Stanza, true), {result, true}; _ -> {result, false} end; _ -> {result, false} end. 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, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true}; _ -> {result, false} end; _ -> {result, false} end. broadcast_removed_node(Host, Node, Nidx, 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, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true} end; _ -> {result, false} end. broadcast_created_node(_, _, _, _, _, []) -> {result, false}; broadcast_created_node(Host, Node, Nidx, Type, NodeOptions, SubsByDepth) -> Stanza = event_stanza([#xmlel{name = <<"create">>, attrs = nodeAttr(Node)}]), broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, true), {result, true}. broadcast_config_notification(Host, Node, Nidx, 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, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true}; _ -> {result, false} end; _ -> {result, false} end. get_collection_subscriptions(Host, Node) -> Action = fun() -> {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_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}) -> 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, WithOptions); Other -> Other end. 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 #pubsub_subscription{options = Options} -> [{JID, SubID, Options} | Acc]; {error, notfound} -> [{JID, SubID, []} | Acc] end; (_, Acc) -> Acc end, [], Subs). 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), 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, [_]} -> Stanza; {true, SubIDs} -> add_shim_headers(Stanza, subid_shim(SubIDs)) end, lists:foreach(fun(To) -> ejabberd_router:route(From, jid:make(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 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 = jid:make(LUser, LServer, <<"">>), _StanzaToSend = add_extended_headers(Stanza, _ReplyTo = extended_headers([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, 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) -> 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 -> 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, {_, 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 get_configure(Host, ServerHost, Node, From, Lang) -> 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 = 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(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, [])}]}]}]}. 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, Def) -> case lists:keysearch(Var, 1, Options) of {value, {_Val, Ret}} -> Ret; _ -> 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, _}} -> DefaultModule = plugin(Host, ?STDNODE), DefaultModule:options(); 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 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 %% @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 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 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#", (atom_to_binary(Var, latin1))/binary>>, (get_option(Options, Var)))). -define(STRING_CONFIG_FIELD(Label, Var), ?STRINGXFIELD(Label, <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, (get_option(Options, Var, <<>>)))). -define(INTEGER_CONFIG_FIELD(Label, Var), ?STRINGXFIELD(Label, <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, (jlib:integer_to_binary(get_option(Options, Var))))). -define(JLIST_CONFIG_FIELD(Label, Var, Opts), ?LISTXFIELD(Label, <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, (jid:to_string(get_option(Options, Var))), [jid:to_string(O) || O <- Opts])). -define(ALIST_CONFIG_FIELD(Label, Var, 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#", (atom_to_binary(Var, latin1))/binary>>, (get_option(Options, Var)), Opts)). -define(NLIST_CONFIG_FIELD(Label, 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 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:

%%
    %%
  • 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 = 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) -> [{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). -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 -> 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). -define(SET_ALIST_XOPT(Opt, Val, Vals), 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, [], 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) -> 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). 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, Nidx, ItemId, {p1_time_compat:timestamp(), jid:tolower(jid:remove_resource(Publisher))}, Payload}); _ -> ok end. 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, Nidx}); _ -> ok end. -spec(get_cached_item/2 :: ( Host :: mod_pubsub:host(), Nidx :: mod_pubsub:nodeIdx()) -> undefined | mod_pubsub:pubsubItem() ). 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, 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) -> 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, <<"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>>); 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 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 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) end. select_type(ServerHost, Host, Node) -> 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 <<"publish-only-affiliation">>, % OPTIONAL <<"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. features(Host, <<>>) -> lists:usort(lists:foldl(fun (Plugin, Acc) -> Acc ++ plugin_features(Host, Plugin) end, features(), plugins(Host))); features(Host, Node) when is_binary(Node) -> Action = fun (#pubsub_node{type = Type}) -> {result, plugin_features(Host, Type)} end, case transaction(Host, Node, Action, sync_dirty) of {result, Features} -> lists:usort(features() ++ Features); _ -> features() 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]), 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, 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(Host, Type, Function, Args) -> ?DEBUG("node_call ~p ~p ~p", [Type, Function, Args]), 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(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(Host, fun () -> node_call(Host, 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(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, 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} | SubEls])}. string_to_ljid(JID) -> case jid:from_string(JID) of error -> {<<>>, <<>>, <<>>}; J -> case jid:tolower(J) of error -> {<<>>, <<>>, <<>>}; J1 -> J1 end end. -spec(uniqid/0 :: () -> mod_pubsub:itemId()). uniqid() -> {T1, T2, T3} = p1_time_compat:timestamp(), iolist_to_binary(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). nodeAttr(Node) -> [{<<"node">>, Node}]. itemAttr([]) -> []; itemAttr(ItemId) -> [{<<"id">>, ItemId}]. itemsEls(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()) -> 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])}. 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}]} || Jid <- Jids]. on_user_offline(_, JID, _) -> {User, Server, Resource} = jid:tolower(JID), case user_resources(User, Server) of [] -> purge_offline({User, Server, Resource}); _ -> true end. 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, unsupported, <<"retrieve-affiliations">>)}, Acc}; true -> 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_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, Items); 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(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) -> 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, max_subscriptions_node, default_node_config]. ejabberd-16.01/src/mod_proxy65_sm.erl0000644000232200023220000001327112645157216020027 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_proxy65_sm.erl %%% Author : Evgeniy Khramtsov %%% Purpose : Bytestreams manager. %%% Created : 12 Oct 2006 by Evgeniy 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(mod_proxy65_sm). -author('xram@jabber.ru'). -behaviour(gen_server). %% gen_server callbacks. -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -export([start_link/2, register_stream/1, unregister_stream/1, activate_stream/4]). -record(state, {max_connections = infinity :: non_neg_integer() | infinity}). -include("jlib.hrl"). -record(bytestream, {sha1 = <<"">> :: binary() | '$1', target :: pid() | '_', initiator :: pid() | '_', active = false :: boolean() | '_', jid_i = {<<"">>, <<"">>, <<"">>} :: ljid() | '_'}). -define(PROCNAME, ejabberd_mod_proxy65_sm). %% Unused callbacks. handle_cast(_Request, State) -> {noreply, State}. code_change(_OldVsn, State, _Extra) -> {ok, State}. handle_info(_Info, State) -> {noreply, State}. %%---------------- start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), gen_server:start_link({local, Proc}, ?MODULE, [Opts], []). init([Opts]) -> 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 -> I; (infinity) -> infinity end, infinity), {ok, #state{max_connections = MaxConnections}}. terminate(_Reason, _State) -> ok. handle_call({activate, SHA1, IJid}, _From, State) -> MaxConns = State#state.max_connections, F = fun () -> case mnesia:read(bytestream, SHA1, write) of [#bytestream{target = TPid, initiator = IPid} = ByteStream] when is_pid(TPid), is_pid(IPid) -> ActiveFlag = ByteStream#bytestream.active, if ActiveFlag == false -> ConnsPerJID = mnesia:select(bytestream, [{#bytestream{sha1 = '$1', jid_i = IJid, _ = '_'}, [], ['$1']}]), if length(ConnsPerJID) < MaxConns -> mnesia:write(ByteStream#bytestream{active = true, jid_i = IJid}), {ok, IPid, TPid}; true -> {limit, IPid, TPid} end; true -> conflict end; _ -> false end end, Reply = mnesia:transaction(F), {reply, Reply, State}; handle_call(_Request, _From, State) -> {reply, ok, State}. %%%---------------------- %%% API. %%%---------------------- %%%--------------------------------------------------- %%% register_stream(SHA1) -> {atomic, ok} | %%% {atomic, error} | %%% transaction abort %%% SHA1 = string() %%%--------------------------------------------------- register_stream(SHA1) when is_binary(SHA1) -> StreamPid = self(), F = fun () -> case mnesia:read(bytestream, SHA1, write) of [] -> mnesia:write(#bytestream{sha1 = SHA1, target = StreamPid}); [#bytestream{target = Pid, initiator = undefined} = ByteStream] when is_pid(Pid), Pid /= StreamPid -> mnesia:write(ByteStream#bytestream{initiator = StreamPid}); _ -> error end end, mnesia:transaction(F). %%%---------------------------------------------------- %%% unregister_stream(SHA1) -> ok | transaction abort %%% SHA1 = string() %%%---------------------------------------------------- unregister_stream(SHA1) when is_binary(SHA1) -> F = fun () -> mnesia:delete({bytestream, SHA1}) end, mnesia:transaction(F). %%%-------------------------------------------------------- %%% activate_stream(SHA1, IJid, TJid, Host) -> ok | %%% false | %%% limit | %%% conflict | %%% error %%% SHA1 = string() %%% IJid = TJid = jid() %%% Host = string() %%%-------------------------------------------------------- activate_stream(SHA1, IJid, TJid, Host) when is_binary(SHA1) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), case catch gen_server:call(Proc, {activate, SHA1, IJid}) of {atomic, {ok, IPid, TPid}} -> mod_proxy65_stream:activate({IPid, IJid}, {TPid, TJid}); {atomic, {limit, IPid, TPid}} -> mod_proxy65_stream:stop(IPid), mod_proxy65_stream:stop(TPid), limit; {atomic, conflict} -> conflict; {atomic, false} -> false; _ -> error end. ejabberd-16.01/src/scram.erl0000644000232200023220000000600512645157216016237 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : scram.erl %%% Author : Stephen Röttger %%% Purpose : SCRAM (RFC 5802) %%% Created : 7 Aug 2011 by Stephen Röttger %%% %%% %%% 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(scram). -author('stephen.roettger@googlemail.com'). %% External exports %% ejabberd doesn't implement SASLPREP, so we use the similar RESOURCEPREP instead -export([salted_password/3, stored_key/1, server_key/1, server_signature/2, client_signature/2, client_key/1, client_key/2]). -spec salted_password(binary(), binary(), non_neg_integer()) -> binary(). salted_password(Password, Salt, IterationCount) -> hi(jid:resourceprep(Password), Salt, IterationCount). -spec client_key(binary()) -> binary(). client_key(SaltedPassword) -> sha_mac(SaltedPassword, <<"Client Key">>). -spec stored_key(binary()) -> binary(). stored_key(ClientKey) -> p1_sha:sha1(ClientKey). -spec server_key(binary()) -> binary(). server_key(SaltedPassword) -> sha_mac(SaltedPassword, <<"Server Key">>). -spec client_signature(binary(), binary()) -> binary(). client_signature(StoredKey, AuthMessage) -> sha_mac(StoredKey, AuthMessage). -spec client_key(binary(), binary()) -> binary(). client_key(ClientProof, ClientSignature) -> list_to_binary(lists:zipwith(fun (X, Y) -> X bxor Y end, binary_to_list(ClientProof), binary_to_list(ClientSignature))). -spec server_signature(binary(), binary()) -> binary(). server_signature(ServerKey, AuthMessage) -> sha_mac(ServerKey, AuthMessage). hi(Password, Salt, IterationCount) -> U1 = sha_mac(Password, <>), list_to_binary(lists:zipwith(fun (X, Y) -> X bxor Y end, binary_to_list(U1), binary_to_list(hi_round(Password, U1, IterationCount - 1)))). hi_round(Password, UPrev, 1) -> sha_mac(Password, UPrev); hi_round(Password, UPrev, IterationCount) -> U = sha_mac(Password, UPrev), list_to_binary(lists:zipwith(fun (X, Y) -> X bxor Y end, binary_to_list(U), binary_to_list(hi_round(Password, U, IterationCount - 1)))). sha_mac(Key, Data) -> crypto:hmac(sha, Key, Data). ejabberd-16.01/src/mod_sic.erl0000644000232200023220000000636112645157216016554 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_sic.erl %%% Author : Karim Gemayel %%% Purpose : XEP-0279 Server IP Check %%% Created : 6 Mar 2010 by Karim Gemayel %%% %%% %%% 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_sic). -protocol({xep, 279, '0.2'}). -author('karim.gemayel@process-one.net'). -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, process_sm_iq/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -define(NS_SIC, <<"urn:xmpp:sic:0">>). 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_SIC, ?MODULE, process_local_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_SIC, ?MODULE, process_sm_iq, IQDisc). stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_SIC), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_SIC). process_local_iq(#jid{user = User, server = Server, resource = Resource}, _To, #iq{type = get, sub_el = _SubEl} = IQ) -> get_ip({User, Server, Resource}, IQ); process_local_iq(_From, _To, #iq{type = set, sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. process_sm_iq(#jid{user = User, server = Server, resource = Resource}, #jid{user = User, server = Server}, #iq{type = get, sub_el = _SubEl} = IQ) -> get_ip({User, Server, Resource}, IQ); process_sm_iq(_From, _To, #iq{type = get, sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}; process_sm_iq(_From, _To, #iq{type = set, sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. get_ip({User, Server, Resource}, #iq{sub_el = #xmlel{name = Name, attrs = Attrs} = SubEl} = IQ) -> case ejabberd_sm:get_user_ip(User, Server, Resource) of {IP, _} when is_tuple(IP) -> IQ#iq{type = result, sub_el = [#xmlel{name = Name, attrs = Attrs, children = [{xmlcdata, iolist_to_binary(jlib:ip_to_list(IP))}]}]}; _ -> 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]. ejabberd-16.01/src/ejabberd_s2s.erl0000644000232200023220000005334712645157216017472 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_s2s.erl %%% Author : Alexey Shchepin %%% Purpose : S2S connections manager %%% Created : 7 Dec 2002 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_s2s). -protocol({xep, 220, '1.1'}). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_server). %% API -export([start_link/0, route/3, have_connection/1, 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, list_temporarily_blocked_hosts/0, external_host_overloaded/1, is_temporarly_blocked/1, check_peer_certificate/3]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([get_info_s2s_connections/1, transform_options/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_commands.hrl"). -include_lib("public_key/include/public_key.hrl"). -define(PKIXEXPLICIT, 'OTP-PUB-KEY'). -define(PKIXIMPLICIT, 'OTP-PUB-KEY'). -include("XmppAddr.hrl"). -define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER, 1). -define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER_PER_NODE, 1). -define(S2S_OVERLOAD_BLOCK_PERIOD, 60). %% once a server is temporarly blocked, it stay blocked for 60 seconds -record(s2s, {fromto = {<<"">>, <<"">>} :: {binary(), binary()} | '_', pid = self() :: pid() | '_' | '$1'}). -record(state, {}). -record(temporarily_blocked, {host = <<"">> :: binary(), timestamp :: integer()}). -type temporarily_blocked() :: #temporarily_blocked{}. start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). -spec route(jid(), jid(), xmlel()) -> ok. route(From, To, Packet) -> case catch do_route(From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p~nwhen processing: ~p", [Reason, {From, To, Packet}]); _ -> ok end. clean_temporarily_blocked_table() -> mnesia:clear_table(temporarily_blocked). -spec list_temporarily_blocked_hosts() -> [temporarily_blocked()]. list_temporarily_blocked_hosts() -> ets:tab2list(temporarily_blocked). -spec external_host_overloaded(binary()) -> {aborted, any()} | {atomic, ok}. external_host_overloaded(Host) -> ?INFO_MSG("Disabling connections from ~s for ~p " "seconds", [Host, ?S2S_OVERLOAD_BLOCK_PERIOD]), mnesia:transaction(fun () -> Time = p1_time_compat:monotonic_time(), mnesia:write(#temporarily_blocked{host = Host, timestamp = Time}) end). -spec is_temporarly_blocked(binary()) -> boolean(). is_temporarly_blocked(Host) -> case mnesia:dirty_read(temporarily_blocked, Host) of [] -> false; [#temporarily_blocked{timestamp = T} = Entry] -> 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 end end. -spec remove_connection({binary(), binary()}, pid()) -> {atomic, ok} | ok | {aborted, any()}. remove_connection(FromTo, Pid) -> case catch mnesia:dirty_match_object(s2s, #s2s{fromto = FromTo, pid = Pid}) of [#s2s{pid = Pid}] -> F = fun () -> mnesia:delete_object(#s2s{fromto = FromTo, pid = Pid}) end, mnesia:transaction(F); _ -> ok end. -spec have_connection({binary(), binary()}) -> boolean(). have_connection(FromTo) -> case catch mnesia:dirty_read(s2s, FromTo) of [_] -> true; _ -> false end. -spec get_connections_pids({binary(), binary()}) -> [pid()]. get_connections_pids(FromTo) -> case catch mnesia:dirty_read(s2s, FromTo) of L when is_list(L) -> [Connection#s2s.pid || Connection <- L]; _ -> [] end. -spec try_register({binary(), binary()}) -> boolean(). try_register(FromTo) -> MaxS2SConnectionsNumber = max_s2s_connections_number(FromTo), MaxS2SConnectionsNumberPerNode = max_s2s_connections_number_per_node(FromTo), F = fun () -> L = mnesia:read({s2s, FromTo}), NeededConnections = needed_connections_number(L, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode), if NeededConnections > 0 -> mnesia:write(#s2s{fromto = FromTo, pid = self()}), true; true -> false end end, case mnesia:transaction(F) of {atomic, Res} -> Res; _ -> false end. -spec dirty_get_connections() -> [{binary(), binary()}]. dirty_get_connections() -> mnesia:dirty_all_keys(s2s). check_peer_certificate(SockMod, Sock, Peer) -> case SockMod:get_peer_certificate(Sock) of {ok, Cert} -> case SockMod:get_verify_result(Sock) of 0 -> case ejabberd_idna:domain_utf8_to_ascii(Peer) of false -> {error, <<"Cannot decode remote server name">>}; AsciiPeer -> case lists:any(fun(D) -> match_domain(AsciiPeer, D) end, get_cert_domains(Cert)) of true -> {ok, <<"Verification successful">>}; false -> {error, <<"Certificate host name mismatch">>} end end; VerifyRes -> {error, p1_tls:get_cert_verify_string(VerifyRes, Cert)} end; {error, _Reason} -> {error, <<"Cannot get peer certificate">>}; error -> {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 %%==================================================================== init([]) -> update_tables(), 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)}]), {ok, #state{}}. handle_call(_Request, _From, State) -> {reply, ok, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({mnesia_system_event, {mnesia_down, Node}}, State) -> clean_table_from_bad_node(Node), {noreply, State}; handle_info({route, From, To, Packet}, State) -> case catch do_route(From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p~nwhen processing: ~p", [Reason, {From, To, Packet}]); _ -> ok end, {noreply, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ejabberd_commands:unregister_commands(commands()), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- clean_table_from_bad_node(Node) -> F = fun() -> Es = mnesia:select( s2s, [{#s2s{pid = '$1', _ = '_'}, [{'==', {node, '$1'}, Node}], ['$_']}]), lists:foreach(fun(E) -> mnesia:delete_object(E) end, Es) end, mnesia:async_dirty(F). do_route(From, To, Packet) -> ?DEBUG("s2s manager~n\tfrom ~p~n\tto ~p~n\tpacket " "~P~n", [From, To, Packet, 8]), case find_connection(From, To) of {atomic, Pid} when is_pid(Pid) -> ?DEBUG("sending to process ~p~n", [Pid]), #xmlel{name = Name, attrs = Attrs, children = Els} = Packet, NewAttrs = 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]), send_element(Pid, #xmlel{name = Name, attrs = NewAttrs, children = Els}), ok; {aborted, _Reason} -> case xml:get_tag_attr_s(<<"type">>, Packet) of <<"error">> -> ok; <<"result">> -> ok; _ -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err) end, false end. -spec find_connection(jid(), jid()) -> {aborted, any()} | {atomic, pid()}. find_connection(From, To) -> #jid{lserver = MyServer} = From, #jid{lserver = Server} = To, FromTo = {MyServer, Server}, MaxS2SConnectionsNumber = max_s2s_connections_number(FromTo), MaxS2SConnectionsNumberPerNode = max_s2s_connections_number_per_node(FromTo), ?DEBUG("Finding connection for ~p~n", [FromTo]), case catch mnesia:dirty_read(s2s, FromTo) of {'EXIT', Reason} -> {aborted, Reason}; [] -> %% We try to establish all the connections if the host is not a %% service and if the s2s host is not blacklisted or %% is in whitelist: case not is_service(From, To) andalso allow_host(MyServer, Server) of true -> NeededConnections = needed_connections_number([], MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode), open_several_connections(NeededConnections, MyServer, Server, From, FromTo, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode); false -> {aborted, error} end; L when is_list(L) -> NeededConnections = needed_connections_number(L, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode), if NeededConnections > 0 -> %% We establish the missing connections for this pair. open_several_connections(NeededConnections, MyServer, Server, From, FromTo, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode); true -> %% We choose a connexion from the pool of opened ones. {atomic, choose_connection(From, L)} end end. choose_connection(From, Connections) -> choose_pid(From, [C#s2s.pid || C <- Connections]). choose_pid(From, Pids) -> Pids1 = case [P || P <- Pids, node(P) == node()] of [] -> Pids; Ps -> Ps end, Pid = lists:nth(erlang:phash(jid:remove_resource(From), length(Pids1)), Pids1), ?DEBUG("Using ejabberd_s2s_out ~p~n", [Pid]), Pid. open_several_connections(N, MyServer, Server, From, FromTo, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode) -> ConnectionsResult = [new_connection(MyServer, Server, From, FromTo, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode) || _N <- lists:seq(1, N)], case [PID || {atomic, PID} <- ConnectionsResult] of [] -> hd(ConnectionsResult); PIDs -> {atomic, choose_pid(From, PIDs)} end. new_connection(MyServer, Server, From, FromTo, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode) -> {ok, Pid} = ejabberd_s2s_out:start( 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}), ?INFO_MSG("New s2s connection started ~p", [Pid]), Pid; true -> choose_connection(From, L) end end, TRes = mnesia:transaction(F), case TRes of {atomic, Pid} -> ejabberd_s2s_out:start_connection(Pid); _ -> ejabberd_s2s_out:stop_connection(Pid) end, TRes. max_s2s_connections_number({From, To}) -> case acl:match_rule(From, max_s2s_connections, jid:make(<<"">>, To, <<"">>)) of Max when is_integer(Max) -> Max; _ -> ?DEFAULT_MAX_S2S_CONNECTIONS_NUMBER end. max_s2s_connections_number_per_node({From, To}) -> case acl:match_rule(From, max_s2s_connections_per_node, jid:make(<<"">>, To, <<"">>)) of Max when is_integer(Max) -> Max; _ -> ?DEFAULT_MAX_S2S_CONNECTIONS_NUMBER_PER_NODE end. needed_connections_number(Ls, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode) -> LocalLs = [L || L <- Ls, node(L#s2s.pid) == node()], lists:min([MaxS2SConnectionsNumber - length(Ls), MaxS2SConnectionsNumberPerNode - length(LocalLs)]). %%-------------------------------------------------------------------- %% Function: is_service(From, To) -> true | false %% Description: Return true if the destination must be considered as a %% service. %% -------------------------------------------------------------------- is_service(From, To) -> LFromDomain = From#jid.lserver, case ejabberd_config:get_option( {route_subdomains, LFromDomain}, fun(s2s) -> s2s; (local) -> local end, local) of s2s -> % bypass RFC 3920 10.3 false; local -> Hosts = (?MYHOSTS), P = fun (ParentDomain) -> lists:member(ParentDomain, Hosts) end, lists:any(P, parent_domains(To#jid.lserver)) end. parent_domains(Domain) -> lists:foldl(fun (Label, []) -> [Label]; (Label, [Head | Tail]) -> [<
">>), fw(F, <<" \"Powered">>, [Images_dir]), fw(F, <<" \"Powered">>, [Images_dir]), fw(F, <<"">>), fw(F, <<" ">>, [Images_dir]), fw(F, <<" \"Valid">>, [Images_dir]), fw(F, <<"
">>). 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, dir_name = DirName, file_format = FileFormat, file_permissions = FilePermissions, css_file = CSSFile, lang = Lang, timezone = Timezone, spam_prevention = NoFollow, top_link = TopLink} = State, Room = get_room_info(RoomJID, Opts), Nick = htmlize(Nick1, FileFormat), Nick2 = htmlize_nick(Nick1, FileFormat), Now = p1_time_compat:timestamp(), TimeStamp = case Timezone of local -> calendar:now_to_local_time(Now); universal -> calendar:now_to_universal_time(Now) end, {Fd, Fn, _Dir} = build_filename_string(TimeStamp, OutDir, Room#room.jid, DirType, DirName, FileFormat), {Date, Time} = TimeStamp, case file:read_file_info(Fn) of {ok, _} -> {ok, F} = file:open(Fn, [append]); {error, enoent} -> make_dir_rec(Fd), {ok, F} = file:open(Fn, [append]), catch set_filemode(Fn, FilePermissions), Datestring = get_dateweek(Date, Lang), TimeStampYesterday = get_timestamp_daydiff(TimeStamp, -1), {_FdYesterday, FnYesterday, DatePrev} = build_filename_string(TimeStampYesterday, OutDir, Room#room.jid, DirType, DirName, FileFormat), TimeStampTomorrow = get_timestamp_daydiff(TimeStamp, 1), {_FdTomorrow, _FnTomorrow, DateNext} = build_filename_string(TimeStampTomorrow, OutDir, Room#room.jid, DirType, DirName, FileFormat), HourOffset = calc_hour_offset(TimeStamp), put_header(F, Room, Datestring, CSSFile, Lang, HourOffset, DatePrev, DateNext, TopLink, FileFormat), Images_dir = fjoin([OutDir, <<"images">>]), file:make_dir(Images_dir), create_image_files(Images_dir), Images_url = case DirType of subdirs -> <<"../../../images">>; plain -> <<"../images">> end, close_previous_log(FnYesterday, Images_url, FileFormat) end, Text = case Message of roomconfig_change -> RoomConfig = roomconfig_to_string(Room#room.config, Lang, FileFormat), put_room_config(F, RoomConfig, Lang, FileFormat), io_lib:format("~s
", [?T(<<"Chatroom configuration modified">>)]); {roomconfig_change, Occupants} -> RoomConfig = roomconfig_to_string(Room#room.config, Lang, FileFormat), put_room_config(F, RoomConfig, Lang, FileFormat), RoomOccupants = roomoccupants_to_string(Occupants, FileFormat), put_room_occupants(F, RoomOccupants, Lang, FileFormat), io_lib:format("~s
", [?T(<<"Chatroom configuration modified">>)]); join -> io_lib:format("~s ~s
", [Nick, ?T(<<"joins the room">>)]); leave -> io_lib:format("~s ~s
", [Nick, ?T(<<"leaves the room">>)]); {leave, Reason} -> io_lib:format("~s ~s: ~s
", [Nick, ?T(<<"leaves the room">>), htmlize(Reason, NoFollow, FileFormat)]); {kickban, <<"301">>, <<"">>} -> io_lib:format("~s ~s
", [Nick, ?T(<<"has been banned">>)]); {kickban, <<"301">>, Reason} -> io_lib:format("~s ~s: ~s
", [Nick, ?T(<<"has been banned">>), htmlize(Reason, FileFormat)]); {kickban, <<"307">>, <<"">>} -> io_lib:format("~s ~s
", [Nick, ?T(<<"has been kicked">>)]); {kickban, <<"307">>, Reason} -> io_lib:format("~s ~s: ~s
", [Nick, ?T(<<"has been kicked">>), htmlize(Reason, FileFormat)]); {kickban, <<"321">>, <<"">>} -> io_lib:format("~s ~s
", [Nick, ?T(<<"has been kicked because of an affiliation " "change">>)]); {kickban, <<"322">>, <<"">>} -> io_lib:format("~s ~s
", [Nick, ?T(<<"has been kicked because the room has " "been changed to members-only">>)]); {kickban, <<"332">>, <<"">>} -> io_lib:format("~s ~s
", [Nick, ?T(<<"has been kicked because of a system " "shutdown">>)]); {nickchange, OldNick} -> io_lib:format("~s ~s ~s
", [htmlize(OldNick, FileFormat), ?T(<<"is now known as">>), Nick]); {subject, T} -> io_lib:format("~s~s~s
", [Nick, ?T(<<" has set the subject to: ">>), htmlize(T, NoFollow, FileFormat)]); {body, T} -> case {ejabberd_regexp:run(T, <<"^/me ">>), Nick} of {_, <<"">>} -> io_lib:format("~s
", [htmlize(T, NoFollow, FileFormat)]); {match, _} -> io_lib:format("~s ~s
", [Nick, str:substr(htmlize(T, FileFormat), 5)]); {nomatch, _} -> io_lib:format("~s ~s
", [Nick2, htmlize(T, NoFollow, FileFormat)]) end; {room_existence, RoomNewExistence} -> io_lib:format("~s
", [get_room_existence_string(RoomNewExistence, Lang)]) end, {Hour, Minute, Second} = Time, STime = io_lib:format("~2..0w:~2..0w:~2..0w", [Hour, Minute, Second]), {_, _, Microsecs} = Now, STimeUnique = io_lib:format("~s.~w", [STime, Microsecs]), catch fw(F, list_to_binary( io_lib:format("[~s] ", [STimeUnique, STimeUnique, STimeUnique, STime]) ++ Text), FileFormat), file:close(F), ok. %%---------------------------------------------------------------------- %% Utilities get_room_existence_string(created, Lang) -> ?T(<<"Chatroom is created">>); get_room_existence_string(destroyed, Lang) -> ?T(<<"Chatroom is destroyed">>); get_room_existence_string(started, Lang) -> ?T(<<"Chatroom is started">>); get_room_existence_string(stopped, Lang) -> ?T(<<"Chatroom is stopped">>). get_dateweek(Date, Lang) -> Weekday = case calendar:day_of_the_week(Date) of 1 -> ?T(<<"Monday">>); 2 -> ?T(<<"Tuesday">>); 3 -> ?T(<<"Wednesday">>); 4 -> ?T(<<"Thursday">>); 5 -> ?T(<<"Friday">>); 6 -> ?T(<<"Saturday">>); 7 -> ?T(<<"Sunday">>) end, {Y, M, D} = Date, Month = case M of 1 -> ?T(<<"January">>); 2 -> ?T(<<"February">>); 3 -> ?T(<<"March">>); 4 -> ?T(<<"April">>); 5 -> ?T(<<"May">>); 6 -> ?T(<<"June">>); 7 -> ?T(<<"July">>); 8 -> ?T(<<"August">>); 9 -> ?T(<<"September">>); 10 -> ?T(<<"October">>); 11 -> ?T(<<"November">>); 12 -> ?T(<<"December">>) end, list_to_binary( case Lang of <<"en">> -> io_lib:format("~s, ~s ~w, ~w", [Weekday, Month, D, Y]); <<"es">> -> io_lib:format("~s ~w de ~s de ~w", [Weekday, D, Month, Y]); _ -> io_lib:format("~s, ~w ~s ~w", [Weekday, D, Month, Y]) end). make_dir_rec(Dir) -> filelib:ensure_dir(<>). %% {ok, F1}=file:open("valid-xhtml10.png", [read]). %% {ok, F1b}=file:read(F1, 1000000). %% c("../../ejabberd/src/jlib.erl"). %% jlib:encode_base64(F1b). image_base64(<<"powered-by-erlang.png">>) -> <<"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAYAAAD+xQNoA" "AADN0lEQVRo3u1aP0waURz+rjGRRQ+nUyRCYmJyDPTapD" "ARaSIbTUjt1gVSh8ZW69aBAR0cWLSxCXWp59LR1jbdqKn" "GxoQuRZZrSYyHEVM6iZMbHewROA7u3fHvkr5vOn737vcu" "33ffu9/vcQz+gef5Cij6CkmSGABgFEH29r5SVvqIsTEOH" "o8HkiQxDBXEOjg9PcHc3BxuUSqsI8jR0REAUFGsCCoKFY" "WCBAN6AxyO0Z7cyMXFb6oGqSgAsIrJut9hMQlvdNbUhKW" "shLd3HtTF4jihShgVpRaBxKKmIGX5HL920/hz/BM2+zAm" "pn2YioQaxnECj0BiEYcrG0Tzzc8/rfudSm02jaVSm9Vr1" "MdG8rSKKXlJ7lHrfjouCut2IrC82BDPbe/gc+xlXez7Kx" "Ez63H4lmIN473Rh8Si1BKhRY6aEJI8pLmbjSPN0xOnBBI" "Lmg5RC6Lg28preKOzsNmHG8R1Bf0o7GdMucUslDy1pJLG" "2sndVVG0lq3c9vum4zmBR1kuwiYMN5ybmCYXxQg57ThFO" "TYznzpPO+IQi+IK+jXjg/YhuIJ+cIIHg+wQJoJ+2N3jYN" "3Olvk4ge/IU98spne+FfGtlslm16nna8fduntfDscoVjG" "JqUgIjz686ViFUdjP4N39x9Xq638viZVtlq2tLXKncLf5" "ticuZSWU5XOUshJKxxKtfdtdvs4OyNb/68urKvlluYizg" "wwu5SLK8jllu1t9ihYOlzdwdpBBKSvh+vKKzHkCj1JW3y" "1m+hSj13WjqOiJKK0qpXKhSFxJAYBvKYaZ9TjWRu4SiWi" "2LyDtb6wghGmn5HfTml16ILGA/G5al2DW7URYTFYrOU7g" "icQ020sYqYDM9CbdgqFd4vzHL03JfvLjk6ZgADAVCSEsJ" "vHsdL+utNYrm2ufZDVZSkzPKaQkW8kthpyS297BvRdRzR" "6DdTurJbPy9Ov1K6xr3HBPQuIMowR3asegUyDuU9SuUG+" "dmIGyZ0b7FBN9St3WunyC5yMsrVv7uXzRP58s/qKn6C4q" "lQoVxVIvd4YBwzBUFKs6ZaD27U9hEdcAN98Sx2IxykafI" "YrizbfESoB+dd9/KF/d/wX3cJvREzl1vAAAAABJRU5Erk" "Jggg==">>; image_base64(<<"valid-xhtml10.png">>) -> <<"iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAAEjEcpEA" "AACiFBMVEUAAADe5+fOezmtra3ejEKlhELvvWO9WlrehE" "LOe3vepaWclHvetVLGc3PerVKcCAj3vVqUjHOUe1JjlL0" "xOUpjjL2UAAC91ueMrc7vrVKlvdbW3u+EpcbO3ufO1ucY" "WpSMKQi9SiF7e3taWkoQEAiMczkQSoxaUkpzc3O1lEoIC" "ACEazEhGAgIAACEYzFra2utjELWcznGnEr/7+9jY2POaz" "HOYzGta2NShLVrlL05OUqctdacCADGa2ucAADGpVqUtc6" "1ORg5OTmlUikYGAiUezl7YzEYEAiUczkxMTG9nEqtIRDe" "3t4AMXu9lEoQCACMazEAKXspKSmljFrW1ta1jELOzs7n7" "/fGxsa9pVqEOSkpY5xznL29tZxahLXOpVr/99ZrY1L/79" "ZjUiljSikAOYTvxmMAMYScezmchFqUczGtlFp7c2utjFq" "UlJStxt73///39/9Ce61CSkq9xsZznMbW5+9Cc62MjIxC" "Qkrv9/fv7/fOzsbnlErWjIz/3mtCORhza1IpIRBzWjH/1" "mtCMRhzY1L/zmvnvVpSQiHOpVJrUinntVr3zmOEc1L3xm" "NaWlq1nFo5QkrGWim1lFoISpRSUlK1zt4hWpwASoz////" "///8xa6WUaykAQoxKe61KSkp7nMbWtWPe5+9jWlL39/f3" "9/fWrWNCQkLera3nvWPv7+85MRjntWPetVp7c1IxKRCUl" "HtKORh7a1IxIRCUjHtaSiHWrVIpIQhzWinvvVpaQiH/1m" "PWpVKMe1L/zmP/xmNrUiGErc4YGBj/73PG1ucQWpT/53O" "9nFoQUpS1SiEQEBC9zt69vb05c6UISoxSUko5a6UICAhS" "SkohUpS1tbXetWMAQoSUgD+kAAAA2HRSTlP/////////i" "P9sSf//dP////////////////////////////////////" "////////////8M////////////ef/////////////////" "/////////////////////////////////////////////" "//////////////////////9d/////////////////////" "///////////////AP//////////////CP//RP////////" "/////////////////////////////////////////////" "///////9xPp1gAAAFvUlEQVR42pVWi18URRwfy7vsYUba" "iqBRBFmICUQGVKcZckQeaRJQUCLeycMSfKGH0uo5NELpI" "vGQGzokvTTA85VHKTpbRoeJnPno/p1+M7t3txj20e/Nzu" "7Ofve7v/k9Zg4Vc+wRQMW0eyLx1ZSANeBDxVmxZZSwEUY" "kGAewm1eIBOMRvhv1UA+q8KXIVuxGdCelFYwxAnxOrxgb" "Y8Ti1t4VA0QHYz4x3FnVC8OVLXv9fkKGSWDoW/4lG6Vbd" "tBblesOs+MjmEmzJKNIJWFEfEQTCWNPFKvcKEymjLO1b8" "bwYQd1hCiiDCl5KsrDCIlhj4fSuvcpfSpgJmyv6dzeZv+" "nMPx3dhbt94II07/JZliEtm1N2RIYPkTYshwYm245a/zk" "WjJwcyFh6ZIcYxxmqiaDSYxhOhFUsqngi3Fzcj3ljdYDN" "E9uzA1YD/5MhnzW1KRqF7mYG8jFYXLcfLpjOe2LA0fuGq" "QrQHl10sdK0sFcFSOSlzF0BgXQH9h3QZDBI0ccNEhftjX" "uippBDD2/eMRiETmwwNEYHyqhdDyo22w+3QHuNbdve5a7" "eOkHmDVJ0ixNmfbz1h0qo/Q6GuSB2wQJQbpOjOQAl7woW" "SRJ0m2ewhvAOUiYYtZtaZL0CZZmtmVOQttLfr/dbveLZo" "drfrL7W75wG/JjqkQxoNTtNsTKELQpQL6/D5loaSmyTT8" "TUhsmi8iFA0hZiyltf7OiNKdarRm5w2So2lTNdPLuIzR+" "AiLj8VTRJaj0LmX4VhJ27f/VJV/yycilWPOrk8NkXi7Qq" "mj5bHqVZlJKZIRk1wFzKrt0WUbnXMPJ1fk4TJ5oWBA61p" "1V76DeIs0MX+s3GxRlA1vtw83KhgNphc1nyErLO5zcvbO" "srq+scbZnpzc6QVFPenLwGxmC+BOfYI+DN55QYddh4Q/N" "E/yGYYj4TOGNngQavAZnzzTovEA+kcMJ+247uYexNA+4F" "svjmuv662jsWxPZx2xg890bYMYnTgya7bjmCiEY0qgJ0v" "MF3c+NoFdPyzxz6V3Uxs3AOWCDchRvOsQtBrbFsrT2fhH" "Ec7ByGzu/dA4IO0A3HdfeP9yMqAwP6NPEb6cbwn0PWVU1" "7/FDBQh/CPIrbfcg027IZrsAT/Bf3FNWyn9RSR4cvvwn3" "e4HFmYPDl/thYcRVi8qPEoXVUWBl6FTBFTtnqmKKg5wnl" "F4wZ1yeLv7TiwXKektE+iDBNicWEyLpnFhfDkpJc3q2kh" "SPyQBbE0dMJnOoDzTwGsI7cdyMkL5gWqUjCF6Txst/twx" "Cv1WzzHoy21ZDQ1xnuDzdPDWR4knr14v0tYn3IxaMFFdi" "MOlEOJHw1jOQ4sWt5rQopRkXZhMEi7pmeDCVWBlfUKwhM" "Z7rsF6elKsvbwiKxgxIdewa3ErsaYomCVZFYJb0GUu3Jq" "GUNoplBxYiYby8vLBFWef+Cri4/I1sbQ/1OtYTrNtdXS+" "rSe7kQ52eSObL99/iErCWUjCy5W4JLygmCouGfG9x9fmx" "17XhBuDCaOerbt538erta7TFktLvdHghZcCbcPQO33zIJ" "G9kxF5hoVXnzTzRz0r5js8oTj6uyPkGRf346HOLcasgFe" "xueNUWFPtuFKzjoSFYYedhwVlhsRVYWWJpltv1XPQT1Rl" "0bjZIBlb1XujVDzY/Kj4k6Ku3+Z0jo1owjVzDpFTXe1ju" "vBSWNFmNWGZy8LvzUl5PN4JCwyNDzbQ0aAj4Zrjz0FatG" "JJYhvq4j7mGSpvytGFlZtHf2C4o/28Zu8z7wo7eYPfXys" "nF0i9NnPh1t1zR7VBb9GqaOXhtTmHQdgMFXE+Z608cnpO" "DdZdjL+TuDY44Q38kJXHhccWLoOd9uv1AwwvO+48uu+fa" "CSJPJ1bmy6ThyvpivBmYWgjxPDPAp7JTemY/yGKFEiRt/" "jG/2P79s8KCwoLCgoLC/khUBA5F0SfQZ+RYfpNE/4Xosm" "q7jsZAJsAAAAASUVORK5CYII=">>; image_base64(<<"vcss.png">>) -> <<"iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAABUFvrSA" "AABKVBMVEUAAAAjIx8MR51ZVUqAdlmdnZ3ejEWLDAuNjY" "1kiMG0n2d9fX19Ghfrp1FtbW3y39+3Ph6lIRNdXV2qJBF" "cVUhcVUhPT0/dsmpUfLr57+/u7u4/PDWZAACZAADOp1Gd" "GxG+SyTgvnNdSySzk16+mkuxw+BOS0BOS0DOzs7MzMy4T" "09RRDwsJBG+vr73wV6fkG6eCQRFcLSurq6/X1+ht9nXfz" "5sepHuwV59ZTHetFjQ2+wMCQQ2ZK5tWCsmWajsz8+Sq9N" "MPh4hVaY8MRj///////////////////////9MTEyOp9Lu" "8vhXU1A8PDyjOSTBz+YLRJ2rLy8sLCwXTaKujEUcHByDn" "82dfz7/zGafDw+fDw+zRSlzlMcMDAyNcji1tbXf5vIcFg" "vATJOjAAAAY3RSTlP/8/////////////////8A//////P" "/////ov//8//////////////z///T//////////+i////" "//////////8w/////6IA/xAgMP//////////8////////" "/8w0/////////+zehebAAACkUlEQVR42u2VfVPTQBDG19" "VqC6LY+lKrRIxFQaFSBPuSvhBPF8SIUZK2J5Yav/+HcO8" "uZdLqTCsU/nKnyWwvk1/unnt2D9ZmH+8/cMAaTRFy+ng6" "9/yiwC/+gy8R3McGv5zHvGJEGAdR4eBgi1IbZwevIEZE2" "4pFtBtzG1Q4AoD5zvw5pEDcJvIQV/TE3/l+H9GnNJwcdA" "BS5wAbFQLMqI98/UReoAaOTlaJsp0zaHx7LwZvY0BUR2x" "pWTzqam0gzY8KGzG4MhBCNGucha4QbpETy+Yk/BP85nt7" "34AjpQLTsE4ZFpf/dnkUCglXVNYB+OfUZJHvAqAoa45Oe" "uPgm4+Xjtv7xm4N7PMV4C61+Mrz3H2WImm3ATiWrAiwZR" "WcUA5Ej4dgIEMxDv6yxHHcNuAutnjv2HZ1NeuycoVPh0m" "wC834zZC9Ao5dkZZKwLVGwT+WdLw0YOZ1saEkUDoT+QGW" "KZ0E2xpcrPakVW2KXwyUtYEtlEAj3GXD/fYwrryAdeiyG" "qidQSw1eqtJcA8cZq4zXqhPuCBYE1fKJjh/5X6MwRm9c2" "xf7WVdLf5oSdt64esVIwVAKC1HJ2oli8vj3L0YzC4zjkM" "agt+arDAs6bApbL1RVlWIqrJbreqKZmh4y6VR7rAJeUYD" "VRj9VqRXkErpJ9lbEwtE83KlIfeG4p52t7zWIMO1XcaGz" "54uUyet+hBM7BXXDS8Xc5+8Gmmbu1xwSoGIokA3oTptQe" "cQ4Iimm/Ew7jwbPfMi3TM91T9XVIGo+W9xC8oWpugVCXL" "uwXijjxJ3r/6PjX7nlFua8QmyM+TO/Gja2TTc2Z95C5ua" "ewGH6cJi6bJO6Z+TY276eH3tbgy+/3ly3Js+rj66osG/A" "V5htgaQ9SeRAAAAAElFTkSuQmCC">>; image_base64(<<"powered-by-ejabberd.png">>) -> <<"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAMAAADJG/NaA" "AAAw1BMVEUAAAAjBgYtBAM5AwFCAAAYGAJNAABcAABIDQ" "5qAAAoJRV7AACFAAAoKSdJHByLAAAwLwk1NQA1MzFJKyo" "4NxtDQQBEQT5KSCxSTgBSUBlgQ0JYSEpZWQJPUU5hYABb" "W0ZiYClcW1poaCVwbQRpaDhzYWNsakhuZ2VrbFZ8dwCEg" "AB3dnd4d2+OjACDhYKcmACJi4iQkpWspgCYmJm5swCmqa" "zEwACwsbS4ub3X0QLExsPLyszW1Nnc3ODm5ugMBwAWAwP" "Hm1IFAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJ" "cEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfVCRQOBA7VB" "kCMAAACcElEQVRIx72WjXKiMBSFQalIFbNiy1pdrJZaRV" "YR5deGwPs/VRNBSBB2OjvQO0oYjPfj5J6bCcdx8i2Uldx" "KcDhk1HbIPwFBF/kHKJfjPSVAyIRHF9rRZ4sUX3EDdWOv" "1+u2tESaavpnYTbv9zvd0WwDy3/QcGQXlH5uTxB1l07MJ" "lRpsUei0JF6Qi+OHyGK7ijXxPklHe/umIllim3iUBMJDI" "EULxxPP0TVWhhKJoN9fUpdmQLteV8aDgEAg9gIcTjL4F4" "L+r4WVKEF+rbJdwYYAoQHY+oQjnGootyKwxapoi73WkyF" "FySQBv988naEEp4+YMMec5VUCQDJTscEy7Kc0HsLmqNE7" "rovDjMpIHHGYeidXn4TQcaxMYqP3RV3C8oCl2WvrlSPaN" "pGZadRnmPGCk8ylM2okAJ4i9TEe1KersXxSl6jUt5uayi" "IodirtcKLOaWblj50wiyMv1F9lm9TUDArGAD0FmEpvCUs" "VoZy6dW81Fg0aDaHogQa36ekAPG5DDGsbdZrGsrzZUnzv" "Bo1I2tLmuL69kSitAweyHKN9b3leDfQMnu3nIIKWfmXnq" "GVKedJT6QpICbJvf2f8aOsvn68v+k7/cwUQdPoxaMoRTn" "KFHNlKsKQphCTOa84u64vpi8bH31CqsbF6lSONRTkTyQG" "Arq49/fEvjBwz4eDS2/JpaXRNOoXRD/VmOrDVTJJRIZCT" "Lav3VrqbPvP3vdduGEhQJzilncbpSA4F3vsihErO+dayv" "/sY5/yRE0GDEXCu2VoNiMlo5i+P2KlgMEvTNk2eYa5XEy" "h12Ex17Z8vzQUR3KEPbYd6XG87eC4Ly75RneS5ZYHAAAA" "AElFTkSuQmCC">>. create_image_files(Images_dir) -> Filenames = [<<"powered-by-ejabberd.png">>, <<"powered-by-erlang.png">>, <<"valid-xhtml10.png">>, <<"vcss.png">>], lists:foreach(fun (Filename) -> Filename_full = fjoin([Images_dir, Filename]), {ok, F} = file:open(Filename_full, [write]), Image = jlib:decode_base64(image_base64(Filename)), io:format(F, <<"~s">>, [Image]), file:close(F) end, Filenames), ok. fw(F, S) -> fw(F, S, [], html). fw(F, S, O) when is_list(O) -> fw(F, S, O, html); fw(F, S, FileFormat) when is_atom(FileFormat) -> fw(F, S, [], FileFormat). fw(F, S, O, FileFormat) -> S1 = list_to_binary(io_lib:format(binary_to_list(S) ++ "~n", O)), S2 = case FileFormat of html -> S1; plaintext -> S1a = ejabberd_regexp:greplace(S1, <<"<[^<^>]*>">>, <<"">>), S1x = ejabberd_regexp:greplace(S1a, ?PLAINTEXT_CO, <<"~~">>), S1y = ejabberd_regexp:greplace(S1x, ?PLAINTEXT_IN, <<"<">>), ejabberd_regexp:greplace(S1y, ?PLAINTEXT_OUT, <<">">>) end, file:write(F, S2). put_header(_, _, _, _, _, _, _, _, _, plaintext) -> ok; put_header(F, Room, Date, CSSFile, Lang, Hour_offset, Date_prev, Date_next, Top_link, FileFormat) -> fw(F, <<"">>), fw(F, <<"">>, [Lang, Lang]), fw(F, <<"">>), fw(F, <<"">>), fw(F, <<"~s - ~s">>, [htmlize(Room#room.title), Date]), put_header_css(F, CSSFile), put_header_script(F), fw(F, <<"">>), fw(F, <<"">>), {Top_url, Top_text} = Top_link, fw(F, <<"">>, [Top_url, Top_text]), fw(F, <<"
~s
">>, [htmlize(Room#room.title)]), fw(F, <<"~s" "">>, [Room#room.jid, Room#room.jid]), fw(F, <<"
~s" "< " "^ >">>, [Date, Date_prev, Date_next]), case {htmlize(Room#room.subject_author), htmlize(Room#room.subject)} of {<<"">>, <<"">>} -> ok; {SuA, Su} -> fw(F, <<"
~s~s~s
">>, [SuA, ?T(<<" has set the subject to: ">>), Su]) end, RoomConfig = roomconfig_to_string(Room#room.config, Lang, FileFormat), put_room_config(F, RoomConfig, Lang, FileFormat), Occupants = get_room_occupants(Room#room.jid), RoomOccupants = roomoccupants_to_string(Occupants, FileFormat), put_room_occupants(F, RoomOccupants, Lang, FileFormat), Time_offset_str = case Hour_offset < 0 of true -> io_lib:format("~p", [Hour_offset]); false -> io_lib:format("+~p", [Hour_offset]) end, fw(F, <<"
GMT~s
">>, [Time_offset_str]). put_header_css(F, false) -> fw(F, <<"">>); put_header_css(F, CSSFile) -> fw(F, <<"">>, [CSSFile]). put_header_script(F) -> fw(F, <<"">>). put_room_config(_F, _RoomConfig, _Lang, plaintext) -> ok; put_room_config(F, RoomConfig, Lang, _FileFormat) -> {_, Now2, _} = p1_time_compat:timestamp(), fw(F, <<"
">>), fw(F, <<"
~s
">>, [Now2, ?T(<<"Room Configuration">>)]), fw(F, <<"

~s
">>, [Now2, RoomConfig]), fw(F, <<"
">>). put_room_occupants(_F, _RoomOccupants, _Lang, plaintext) -> ok; put_room_occupants(F, RoomOccupants, Lang, _FileFormat) -> {_, Now2, _} = p1_time_compat:timestamp(), %% htmlize %% The default behaviour is to ignore the nofollow spam prevention on links %% (NoFollow=false) fw(F, <<"
">>), fw(F, <<"
~s
">>, [Now2, ?T(<<"Room Occupants">>)]), fw(F, <<"

~s
">>, [Now2, RoomOccupants]), fw(F, <<"
">>). htmlize(S1) -> htmlize(S1, html). htmlize(S1, plaintext) -> ejabberd_regexp:greplace(S1, <<"~">>, ?PLAINTEXT_CO); htmlize(S1, FileFormat) -> htmlize(S1, false, FileFormat). %% The NoFollow parameter tell if the spam prevention should be applied to the link found %% true means 'apply nofollow on links'. htmlize(S0, _NoFollow, plaintext) -> S1 = ejabberd_regexp:greplace(S0, <<"~">>, ?PLAINTEXT_CO), S1x = ejabberd_regexp:greplace(S1, <<"<">>, ?PLAINTEXT_IN), ejabberd_regexp:greplace(S1x, <<">">>, ?PLAINTEXT_OUT); htmlize(S1, NoFollow, _FileFormat) -> S2_list = str:tokens(S1, <<"\n">>), lists:foldl(fun (Si, Res) -> Si2 = htmlize2(Si, NoFollow), case Res of <<"">> -> Si2; _ -> <", Si2/binary>> end end, <<"">>, S2_list). htmlize2(S1, NoFollow) -> %% Regexp link %% Add the nofollow rel attribute when required S2 = ejabberd_regexp:greplace(S1, <<"\\&">>, <<"\\&">>), S3 = ejabberd_regexp:greplace(S2, <<"<">>, <<"\\<">>), S4 = ejabberd_regexp:greplace(S3, <<">">>, <<"\\>">>), S5 = ejabberd_regexp:greplace(S4, <<"((http|https|ftp)://|(mailto|xmpp):)[^] " ")'\"}]+">>, link_regexp(NoFollow)), S6 = ejabberd_regexp:greplace(S5, <<" ">>, <<"\\ \\ ">>), S7 = ejabberd_regexp:greplace(S6, <<"\\t">>, <<"\\ \\ \\ \\ ">>), S8 = ejabberd_regexp:greplace(S7, <<"~">>, <<"~~">>), ejabberd_regexp:greplace(S8, <<226, 128, 174>>, <<"[RLO]">>). link_regexp(false) -> <<"&">>; link_regexp(true) -> <<"&">>. get_room_info(RoomJID, Opts) -> Title = case lists:keysearch(title, 1, Opts) of {value, {_, T}} -> T; false -> <<"">> end, Subject = case lists:keysearch(subject, 1, Opts) of {value, {_, S}} -> S; false -> <<"">> end, SubjectAuthor = case lists:keysearch(subject_author, 1, Opts) of {value, {_, SA}} -> SA; false -> <<"">> end, #room{jid = jid:to_string(RoomJID), title = Title, subject = Subject, subject_author = SubjectAuthor, config = Opts}. roomconfig_to_string(Options, Lang, FileFormat) -> Title = case lists:keysearch(title, 1, Options) of {value, Tuple} -> [Tuple]; false -> [] end, Os1 = lists:keydelete(title, 1, Options), Os2 = lists:sort(Os1), Options2 = Title ++ Os2, lists:foldl(fun ({Opt, Val}, R) -> case get_roomconfig_text(Opt) of undefined -> R; OptT -> OptText = (?T(OptT)), R2 = case Val of false -> <<"
", OptText/binary, "
">>; true -> <<"
", OptText/binary, "
">>; <<"">> -> <<"
", OptText/binary, "
">>; T -> case Opt of password -> <<"
", OptText/binary, "
">>; max_users -> <<"
", OptText/binary, ": \"", (htmlize(jlib:integer_to_binary(T), FileFormat))/binary, "\"
">>; title -> <<"
", OptText/binary, ": \"", (htmlize(T, FileFormat))/binary, "\"
">>; description -> <<"
", OptText/binary, ": \"", (htmlize(T, FileFormat))/binary, "\"
">>; allow_private_messages_from_visitors -> <<"
", OptText/binary, ": \"", (htmlize(?T((jlib:atom_to_binary(T))), FileFormat))/binary, "\"
">>; _ -> <<"\"", T/binary, "\"">> end end, <> end end, <<"">>, Options2). get_roomconfig_text(title) -> <<"Room title">>; get_roomconfig_text(persistent) -> <<"Make room persistent">>; get_roomconfig_text(public) -> <<"Make room public searchable">>; get_roomconfig_text(public_list) -> <<"Make participants list public">>; get_roomconfig_text(password_protected) -> <<"Make room password protected">>; get_roomconfig_text(password) -> <<"Password">>; get_roomconfig_text(anonymous) -> <<"This room is not anonymous">>; get_roomconfig_text(members_only) -> <<"Make room members-only">>; get_roomconfig_text(moderated) -> <<"Make room moderated">>; get_roomconfig_text(members_by_default) -> <<"Default users as participants">>; get_roomconfig_text(allow_change_subj) -> <<"Allow users to change the subject">>; get_roomconfig_text(allow_private_messages) -> <<"Allow users to send private messages">>; get_roomconfig_text(allow_private_messages_from_visitors) -> <<"Allow visitors to send private messages to">>; get_roomconfig_text(allow_query_users) -> <<"Allow users to query other users">>; get_roomconfig_text(allow_user_invites) -> <<"Allow users to send invites">>; get_roomconfig_text(logging) -> <<"Enable logging">>; get_roomconfig_text(allow_visitor_nickchange) -> <<"Allow visitors to change nickname">>; get_roomconfig_text(allow_visitor_status) -> <<"Allow visitors to send status text in " "presence updates">>; get_roomconfig_text(captcha_protected) -> <<"Make room captcha protected">>; get_roomconfig_text(description) -> <<"Room description">>; %% get_roomconfig_text(subject) -> "Subject"; %% get_roomconfig_text(subject_author) -> "Subject author"; get_roomconfig_text(max_users) -> <<"Maximum Number of Occupants">>; get_roomconfig_text(_) -> undefined. %% Users = [{JID, Nick, Role}] roomoccupants_to_string(Users, _FileFormat) -> Res = [role_users_to_string(RoleS, Users1) || {RoleS, Users1} <- group_by_role(Users), Users1 /= []], iolist_to_binary([<<"
">>, Res, <<"
">>]). group_by_role(Users) -> {Ms, Ps, Vs, Ns} = lists:foldl(fun ({JID, Nick, moderator}, {Mod, Par, Vis, Non}) -> {[{JID, Nick}] ++ Mod, Par, Vis, Non}; ({JID, Nick, participant}, {Mod, Par, Vis, Non}) -> {Mod, [{JID, Nick}] ++ Par, Vis, Non}; ({JID, Nick, visitor}, {Mod, Par, Vis, Non}) -> {Mod, Par, [{JID, Nick}] ++ Vis, Non}; ({JID, Nick, none}, {Mod, Par, Vis, Non}) -> {Mod, Par, Vis, [{JID, Nick}] ++ Non} end, {[], [], [], []}, Users), case Ms of [] -> []; _ -> [{<<"Moderator">>, Ms}] end ++ case Ms of [] -> []; _ -> [{<<"Participant">>, Ps}] end ++ case Ms of [] -> []; _ -> [{<<"Visitor">>, Vs}] end ++ case Ms of [] -> []; _ -> [{<<"None">>, Ns}] end. role_users_to_string(RoleS, Users) -> SortedUsers = lists:keysort(2, Users), UsersString = << <">> || {_JID, Nick} <- SortedUsers >>, <>. get_room_occupants(RoomJIDString) -> RoomJID = jid:from_string(RoomJIDString), RoomName = RoomJID#jid.luser, MucService = RoomJID#jid.lserver, StateData = get_room_state(RoomName, MucService), [{U#user.jid, U#user.nick, U#user.role} || {_, U} <- (?DICT):to_list(StateData#state.users)]. -spec get_room_state(binary(), binary()) -> muc_room_state(). get_room_state(RoomName, MucService) -> case mnesia:dirty_read(muc_online_room, {RoomName, MucService}) of [R] -> RoomPid = R#muc_online_room.pid, get_room_state(RoomPid); [] -> #state{} end. -spec get_room_state(pid()) -> muc_room_state(). get_room_state(RoomPid) -> {ok, R} = gen_fsm:sync_send_all_state_event(RoomPid, get_state), R. get_proc_name(Host) -> gen_mod:get_module_proc(Host, ?PROCNAME). calc_hour_offset(TimeHere) -> TimeZero = calendar:universal_time(), TimeHereHour = calendar:datetime_to_gregorian_seconds(TimeHere) div 3600, TimeZeroHour = calendar:datetime_to_gregorian_seconds(TimeZero) div 3600, TimeHereHour - TimeZeroHour. 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; 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]. ejabberd-16.01/src/mod_mam.erl0000644000232200023220000010650412645157216016550 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @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., %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%------------------------------------------------------------------- -module(mod_mam). -protocol({xep, 313, '0.4'}). -protocol({xep, 334, '0.2'}). -behaviour(gen_mod). %% API -export([start/2, stop/1]). -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]). -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', id = <<>> :: binary() | '_', timestamp = p1_time_compat:timestamp() :: erlang:timestamp() | '_' | '$1', peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3' | undefined, 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()]}). %%%=================================================================== %%% 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_v0_2, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MAM_TMP, ?MODULE, process_iq_v0_2, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?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, 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(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, remove_user, 50), ok. 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), 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), 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, ?MODULE, remove_user, 50), ok. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid: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, IsBareCopy = is_bare_copy(JID, To), 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 {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 = [Archived, StanzaID|NewPkt#xmlel.children], NewPkt#xmlel{children = NewEls}; _ -> NewPkt end; _ -> Pkt end. user_send_packet(Pkt, C2SState, JID, Peer) -> LUser = JID#jid.luser, LServer = JID#jid.lserver, case should_archive(Pkt, LServer) of true -> NewPkt = strip_my_archived_tag(Pkt, LServer), store_msg(C2SState, jlib:replace_from_to(JID, Peer, NewPkt), LUser, LServer, Peer, send), NewPkt; false -> Pkt end. muc_filter_message(Pkt, #state{config = Config} = MUCState, RoomJID, From, FromNick) -> if Config#config.mam -> 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">>, LServer}, {<<"xmlns">>, ?NS_SID_0}, {<<"id">>, ID}]}, NewEls = [StanzaID|NewPkt#xmlel.children], NewPkt#xmlel{children = NewEls}; _ -> NewPkt end; true -> Pkt end. % 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) -> 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), process_iq(LServer, From, To, IQ, SubEl, Fs, chat); 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) -> 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, 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 -> 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; _ -> 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); {#xmlel{} = XData, #xmlel{}} -> [{<<"set">>, SubEl} | jlib:parse_xdata_submit(XData)]; {false, #xmlel{}} -> [{<<"set">>, SubEl}]; {false, false} -> [] 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 %%%=================================================================== % 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) -> 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(#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]}]}; 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) -> 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, jid:tolower(jid:from_string(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(LServer, From, To, Start, End, With, RSM, IQ, MsgType) end. 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, LServer) of true -> false; false -> 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 end; should_archive(#xmlel{}, _LServer) -> false. strip_my_archived_tag(Pkt, LServer) -> NewEls = lists:filter( fun(#xmlel{name = Tag, attrs = Attrs}) when Tag == <<"archived">>; Tag == <<"stanza-id">> -> case catch jid: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 = 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. 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. 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) -> Prefs = get_prefs(LUser, LServer), case should_archive_peer(C2SState, Prefs, Peer) of true -> US = {LUser, LServer}, store(Pkt, LServer, US, chat, Peer, <<"">>, Dir, gen_mod:db_type(LServer, ?MODULE)); false -> pass end. store_muc(MUCState, Pkt, RoomJID, Peer, Nick) -> case should_archive_muc(MUCState, Peer) of true -> LServer = MUCState#state.server_host, {U, S, _} = 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, _} = jid:tolower(Peer), TS = p1_time_compat:timestamp(), 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, <<>>}, type = Type, nick = Nick, packet = Pkt}) of ok -> {ok, ID}; Err -> Err end; store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, odbc) -> TSinteger = p1_time_compat:system_time(micro_seconds), ID = TS = jlib:integer_to_binary(TSinteger), SUser = case Type of chat -> LUser; groupchat -> jid:to_string({LUser, LHost, <<>>}) end, 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( 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) -> 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(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(LServer, From, To, Start, End, With, RSM, IQ, MsgType, 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(LServer, From, To, Start, End, With, RSM, MsgType, DBType) -> case MsgType of chat -> select(LServer, From, Start, End, With, RSM, MsgType, DBType); {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), Msgs = mnesia:dirty_select(archive_msg, MS), {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, MsgType, JidRequestor)} end, FilteredMsgs), IsComplete, Count}; select(LServer, #jid{luser = LUser} = JidRequestor, Start, End, With, RSM, MsgType, {odbc, Host}) -> User = case MsgType of chat -> LUser; {groupchat, _Role, _MUCState} -> 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 % 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]]}} -> {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:flatmap( fun([TS, XML, PeerBin, Kind, Nick]) -> 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. 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)]}. 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 moderator when Peer /= undefined -> [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string(Peer)}]}]}]; _ -> [] end, Pkt1 = Pkt#xmlel{children = Items ++ Els}, 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), 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), QIDAttr = if QID /= <<>> -> [{<<"queryid">>, QID}]; true -> [] end, CompleteAttr = if NS == ?NS_MAM_TMP -> []; NS == ?NS_MAM_0; NS == ?NS_MAM_1 -> [{<<"complete">>, jlib:atom_to_binary(IsComplete)}] 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 ++ CompleteAttr, NS), 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 == ?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([], _, 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, _, Count, Attrs, NS) -> {LastID, _, _} = lists:last(Msgs), Tag = if NS == ?NS_MAM_TMP -> <<"query">>; true -> <<"fin">> end, [#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, 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 /= <<"">> -> 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) -> {Msgs, true}; filter_by_max(Msgs, Len) when is_integer(Len), Len >= 0 -> {lists:sublist(Msgs, Len), length(Msgs) =< Len}; 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, 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(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, LimitClause = if is_integer(Max), Max >= 0 -> [<<" limit ">>, jlib:integer_to_binary(Max+1)]; true -> [] end, WithClause = case With of {text, <<>>} -> []; {text, Txt} -> [<<" and match (txt) against ('">>, ejabberd_odbc:escape(Txt), <<"')">>]; {_, _, <<>>} -> [<<" and bare_peer='">>, ejabberd_odbc:escape(jid:to_string(With)), <<"'">>]; {_, _, _} -> [<<" and peer='">>, ejabberd_odbc:escape(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 >= ">>, 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(User), Query = [<<"SELECT timestamp, xml, peer, kind, nick" " 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 [<<"SELECT timestamp, xml, peer, kind, nick FROM (">>, Query, <<" ORDER BY timestamp DESC ">>, LimitClause, <<") AS t 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. usec_to_now(Int) -> Secs = Int div 1000000, USec = Int rem 1000000, MSec = Secs div 1000000, Sec = Secs rem 1000000, {MSec, Sec, 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) -> J = jid:from_string(xml:get_tag_cdata(El)), [jid:tolower(jid:remove_resource(J)), 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]. ejabberd-16.01/src/ELDAPv3.erl0000644000232200023220000032054112645157216016234 0ustar debalancedebalance%% Generated by the Erlang ASN.1 BER_V2-compiler version, utilizing bit-syntax:2.0.1 %% Purpose: encoder and decoder to the types in mod ELDAPv3 -module('ELDAPv3'). -compile(nowarn_unused_vars). -include("ELDAPv3.hrl"). -asn1_info([{vsn,'2.0.1'}, {module,'ELDAPv3'}, {options,[{i,"src"},{outdir,"src"},noobj,{i,"."},{i,"asn1"}]}]). -export([encoding_rule/0,bit_string_format/0]). -export([ 'enc_LDAPMessage'/2, 'enc_MessageID'/2, 'enc_LDAPString'/2, 'enc_LDAPOID'/2, 'enc_LDAPDN'/2, 'enc_RelativeLDAPDN'/2, 'enc_AttributeType'/2, 'enc_AttributeDescription'/2, 'enc_AttributeDescriptionList'/2, 'enc_AttributeValue'/2, 'enc_AttributeValueAssertion'/2, 'enc_AssertionValue'/2, 'enc_Attribute'/2, 'enc_MatchingRuleId'/2, 'enc_LDAPResult'/2, 'enc_Referral'/2, 'enc_LDAPURL'/2, 'enc_Controls'/2, 'enc_Control'/2, 'enc_BindRequest'/2, 'enc_AuthenticationChoice'/2, 'enc_SaslCredentials'/2, 'enc_BindResponse'/2, 'enc_UnbindRequest'/2, 'enc_SearchRequest'/2, 'enc_Filter'/2, 'enc_SubstringFilter'/2, 'enc_MatchingRuleAssertion'/2, 'enc_SearchResultEntry'/2, 'enc_PartialAttributeList'/2, 'enc_SearchResultReference'/2, 'enc_SearchResultDone'/2, 'enc_ModifyRequest'/2, 'enc_AttributeTypeAndValues'/2, 'enc_ModifyResponse'/2, 'enc_AddRequest'/2, 'enc_AttributeList'/2, 'enc_AddResponse'/2, 'enc_DelRequest'/2, 'enc_DelResponse'/2, 'enc_ModifyDNRequest'/2, 'enc_ModifyDNResponse'/2, 'enc_CompareRequest'/2, 'enc_CompareResponse'/2, 'enc_AbandonRequest'/2, 'enc_ExtendedRequest'/2, 'enc_ExtendedResponse'/2, 'enc_PasswdModifyRequestValue'/2, 'enc_PasswdModifyResponseValue'/2 ]). -export([ 'dec_LDAPMessage'/2, 'dec_MessageID'/2, 'dec_LDAPString'/2, 'dec_LDAPOID'/2, 'dec_LDAPDN'/2, 'dec_RelativeLDAPDN'/2, 'dec_AttributeType'/2, 'dec_AttributeDescription'/2, 'dec_AttributeDescriptionList'/2, 'dec_AttributeValue'/2, 'dec_AttributeValueAssertion'/2, 'dec_AssertionValue'/2, 'dec_Attribute'/2, 'dec_MatchingRuleId'/2, 'dec_LDAPResult'/2, 'dec_Referral'/2, 'dec_LDAPURL'/2, 'dec_Controls'/2, 'dec_Control'/2, 'dec_BindRequest'/2, 'dec_AuthenticationChoice'/2, 'dec_SaslCredentials'/2, 'dec_BindResponse'/2, 'dec_UnbindRequest'/2, 'dec_SearchRequest'/2, 'dec_Filter'/2, 'dec_SubstringFilter'/2, 'dec_MatchingRuleAssertion'/2, 'dec_SearchResultEntry'/2, 'dec_PartialAttributeList'/2, 'dec_SearchResultReference'/2, 'dec_SearchResultDone'/2, 'dec_ModifyRequest'/2, 'dec_AttributeTypeAndValues'/2, 'dec_ModifyResponse'/2, 'dec_AddRequest'/2, 'dec_AttributeList'/2, 'dec_AddResponse'/2, 'dec_DelRequest'/2, 'dec_DelResponse'/2, 'dec_ModifyDNRequest'/2, 'dec_ModifyDNResponse'/2, 'dec_CompareRequest'/2, 'dec_CompareResponse'/2, 'dec_AbandonRequest'/2, 'dec_ExtendedRequest'/2, 'dec_ExtendedResponse'/2, 'dec_PasswdModifyRequestValue'/2, 'dec_PasswdModifyResponseValue'/2 ]). -export([ 'maxInt'/0, 'passwdModifyOID'/0 ]). -export([info/0]). -export([encode/2,decode/2]). encoding_rule() -> ber. bit_string_format() -> bitstring. encode(Type,Data) -> case catch encode_disp(Type,Data) of {'EXIT',{error,Reason}} -> {error,Reason}; {'EXIT',Reason} -> {error,{asn1,Reason}}; {Bytes,_Len} -> {ok,iolist_to_binary(Bytes)}; Bytes -> {ok,iolist_to_binary(Bytes)} end. decode(Type,Data) -> case catch decode_disp(Type,element(1, ber_decode_nif(Data))) of {'EXIT',{error,Reason}} -> {error,Reason}; {'EXIT',Reason} -> {error,{asn1,Reason}}; Result -> {ok,Result} end. encode_disp('LDAPMessage',Data) -> 'enc_LDAPMessage'(Data); encode_disp('MessageID',Data) -> 'enc_MessageID'(Data); encode_disp('LDAPString',Data) -> 'enc_LDAPString'(Data); encode_disp('LDAPOID',Data) -> 'enc_LDAPOID'(Data); encode_disp('LDAPDN',Data) -> 'enc_LDAPDN'(Data); encode_disp('RelativeLDAPDN',Data) -> 'enc_RelativeLDAPDN'(Data); encode_disp('AttributeType',Data) -> 'enc_AttributeType'(Data); encode_disp('AttributeDescription',Data) -> 'enc_AttributeDescription'(Data); encode_disp('AttributeDescriptionList',Data) -> 'enc_AttributeDescriptionList'(Data); encode_disp('AttributeValue',Data) -> 'enc_AttributeValue'(Data); encode_disp('AttributeValueAssertion',Data) -> 'enc_AttributeValueAssertion'(Data); encode_disp('AssertionValue',Data) -> 'enc_AssertionValue'(Data); encode_disp('Attribute',Data) -> 'enc_Attribute'(Data); encode_disp('MatchingRuleId',Data) -> 'enc_MatchingRuleId'(Data); encode_disp('LDAPResult',Data) -> 'enc_LDAPResult'(Data); encode_disp('Referral',Data) -> 'enc_Referral'(Data); encode_disp('LDAPURL',Data) -> 'enc_LDAPURL'(Data); encode_disp('Controls',Data) -> 'enc_Controls'(Data); encode_disp('Control',Data) -> 'enc_Control'(Data); encode_disp('BindRequest',Data) -> 'enc_BindRequest'(Data); encode_disp('AuthenticationChoice',Data) -> 'enc_AuthenticationChoice'(Data); encode_disp('SaslCredentials',Data) -> 'enc_SaslCredentials'(Data); encode_disp('BindResponse',Data) -> 'enc_BindResponse'(Data); encode_disp('UnbindRequest',Data) -> 'enc_UnbindRequest'(Data); encode_disp('SearchRequest',Data) -> 'enc_SearchRequest'(Data); encode_disp('Filter',Data) -> 'enc_Filter'(Data); encode_disp('SubstringFilter',Data) -> 'enc_SubstringFilter'(Data); encode_disp('MatchingRuleAssertion',Data) -> 'enc_MatchingRuleAssertion'(Data); encode_disp('SearchResultEntry',Data) -> 'enc_SearchResultEntry'(Data); encode_disp('PartialAttributeList',Data) -> 'enc_PartialAttributeList'(Data); encode_disp('SearchResultReference',Data) -> 'enc_SearchResultReference'(Data); encode_disp('SearchResultDone',Data) -> 'enc_SearchResultDone'(Data); encode_disp('ModifyRequest',Data) -> 'enc_ModifyRequest'(Data); encode_disp('AttributeTypeAndValues',Data) -> 'enc_AttributeTypeAndValues'(Data); encode_disp('ModifyResponse',Data) -> 'enc_ModifyResponse'(Data); encode_disp('AddRequest',Data) -> 'enc_AddRequest'(Data); encode_disp('AttributeList',Data) -> 'enc_AttributeList'(Data); encode_disp('AddResponse',Data) -> 'enc_AddResponse'(Data); encode_disp('DelRequest',Data) -> 'enc_DelRequest'(Data); encode_disp('DelResponse',Data) -> 'enc_DelResponse'(Data); encode_disp('ModifyDNRequest',Data) -> 'enc_ModifyDNRequest'(Data); encode_disp('ModifyDNResponse',Data) -> 'enc_ModifyDNResponse'(Data); encode_disp('CompareRequest',Data) -> 'enc_CompareRequest'(Data); encode_disp('CompareResponse',Data) -> 'enc_CompareResponse'(Data); encode_disp('AbandonRequest',Data) -> 'enc_AbandonRequest'(Data); encode_disp('ExtendedRequest',Data) -> 'enc_ExtendedRequest'(Data); encode_disp('ExtendedResponse',Data) -> 'enc_ExtendedResponse'(Data); encode_disp('PasswdModifyRequestValue',Data) -> 'enc_PasswdModifyRequestValue'(Data); encode_disp('PasswdModifyResponseValue',Data) -> 'enc_PasswdModifyResponseValue'(Data); encode_disp(Type,_Data) -> exit({error,{asn1,{undefined_type,Type}}}). decode_disp('LDAPMessage',Data) -> 'dec_LDAPMessage'(Data); decode_disp('MessageID',Data) -> 'dec_MessageID'(Data); decode_disp('LDAPString',Data) -> 'dec_LDAPString'(Data); decode_disp('LDAPOID',Data) -> 'dec_LDAPOID'(Data); decode_disp('LDAPDN',Data) -> 'dec_LDAPDN'(Data); decode_disp('RelativeLDAPDN',Data) -> 'dec_RelativeLDAPDN'(Data); decode_disp('AttributeType',Data) -> 'dec_AttributeType'(Data); decode_disp('AttributeDescription',Data) -> 'dec_AttributeDescription'(Data); decode_disp('AttributeDescriptionList',Data) -> 'dec_AttributeDescriptionList'(Data); decode_disp('AttributeValue',Data) -> 'dec_AttributeValue'(Data); decode_disp('AttributeValueAssertion',Data) -> 'dec_AttributeValueAssertion'(Data); decode_disp('AssertionValue',Data) -> 'dec_AssertionValue'(Data); decode_disp('Attribute',Data) -> 'dec_Attribute'(Data); decode_disp('MatchingRuleId',Data) -> 'dec_MatchingRuleId'(Data); decode_disp('LDAPResult',Data) -> 'dec_LDAPResult'(Data); decode_disp('Referral',Data) -> 'dec_Referral'(Data); decode_disp('LDAPURL',Data) -> 'dec_LDAPURL'(Data); decode_disp('Controls',Data) -> 'dec_Controls'(Data); decode_disp('Control',Data) -> 'dec_Control'(Data); decode_disp('BindRequest',Data) -> 'dec_BindRequest'(Data); decode_disp('AuthenticationChoice',Data) -> 'dec_AuthenticationChoice'(Data); decode_disp('SaslCredentials',Data) -> 'dec_SaslCredentials'(Data); decode_disp('BindResponse',Data) -> 'dec_BindResponse'(Data); decode_disp('UnbindRequest',Data) -> 'dec_UnbindRequest'(Data); decode_disp('SearchRequest',Data) -> 'dec_SearchRequest'(Data); decode_disp('Filter',Data) -> 'dec_Filter'(Data); decode_disp('SubstringFilter',Data) -> 'dec_SubstringFilter'(Data); decode_disp('MatchingRuleAssertion',Data) -> 'dec_MatchingRuleAssertion'(Data); decode_disp('SearchResultEntry',Data) -> 'dec_SearchResultEntry'(Data); decode_disp('PartialAttributeList',Data) -> 'dec_PartialAttributeList'(Data); decode_disp('SearchResultReference',Data) -> 'dec_SearchResultReference'(Data); decode_disp('SearchResultDone',Data) -> 'dec_SearchResultDone'(Data); decode_disp('ModifyRequest',Data) -> 'dec_ModifyRequest'(Data); decode_disp('AttributeTypeAndValues',Data) -> 'dec_AttributeTypeAndValues'(Data); decode_disp('ModifyResponse',Data) -> 'dec_ModifyResponse'(Data); decode_disp('AddRequest',Data) -> 'dec_AddRequest'(Data); decode_disp('AttributeList',Data) -> 'dec_AttributeList'(Data); decode_disp('AddResponse',Data) -> 'dec_AddResponse'(Data); decode_disp('DelRequest',Data) -> 'dec_DelRequest'(Data); decode_disp('DelResponse',Data) -> 'dec_DelResponse'(Data); decode_disp('ModifyDNRequest',Data) -> 'dec_ModifyDNRequest'(Data); decode_disp('ModifyDNResponse',Data) -> 'dec_ModifyDNResponse'(Data); decode_disp('CompareRequest',Data) -> 'dec_CompareRequest'(Data); decode_disp('CompareResponse',Data) -> 'dec_CompareResponse'(Data); decode_disp('AbandonRequest',Data) -> 'dec_AbandonRequest'(Data); decode_disp('ExtendedRequest',Data) -> 'dec_ExtendedRequest'(Data); decode_disp('ExtendedResponse',Data) -> 'dec_ExtendedResponse'(Data); decode_disp('PasswdModifyRequestValue',Data) -> 'dec_PasswdModifyRequestValue'(Data); decode_disp('PasswdModifyResponseValue',Data) -> 'dec_PasswdModifyResponseValue'(Data); decode_disp(Type,_Data) -> exit({error,{asn1,{undefined_type,Type}}}). info() -> case ?MODULE:module_info(attributes) of Attributes when is_list(Attributes) -> case lists:keyfind(asn1_info, 1, Attributes) of {_,Info} when is_list(Info) -> Info; _ -> [] end; _ -> [] end. %%================================ %% LDAPMessage %%================================ 'enc_LDAPMessage'(Val) -> 'enc_LDAPMessage'(Val, [<<48>>]). 'enc_LDAPMessage'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3} = Val, %%------------------------------------------------- %% attribute messageID(1) with type INTEGER %%------------------------------------------------- {EncBytes1,EncLen1} = encode_integer(Cindex1, [<<2>>]), %%------------------------------------------------- %% attribute protocolOp(2) with type CHOICE %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_LDAPMessage_protocolOp'(Cindex2, []), %%------------------------------------------------- %% attribute controls(3) External ELDAPv3:Controls OPTIONAL %%------------------------------------------------- {EncBytes3,EncLen3} = case Cindex3 of asn1_NOVALUE -> {<<>>,0}; _ -> 'enc_Controls'(Cindex3, [<<160>>]) end, BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], LenSoFar = EncLen1 + EncLen2 + EncLen3, encode_tags(TagIn, BytesSoFar, LenSoFar). %%================================ %% LDAPMessage_protocolOp %%================================ 'enc_LDAPMessage_protocolOp'(Val, TagIn) -> {EncBytes,EncLen} = case element(1,Val) of bindRequest -> 'enc_BindRequest'(element(2,Val), [<<96>>]); bindResponse -> 'enc_BindResponse'(element(2,Val), [<<97>>]); unbindRequest -> encode_null(element(2,Val), [<<66>>]); searchRequest -> 'enc_SearchRequest'(element(2,Val), [<<99>>]); searchResEntry -> 'enc_SearchResultEntry'(element(2,Val), [<<100>>]); searchResDone -> 'enc_SearchResultDone'(element(2,Val), [<<101>>]); searchResRef -> 'enc_SearchResultReference'(element(2,Val), [<<115>>]); modifyRequest -> 'enc_ModifyRequest'(element(2,Val), [<<102>>]); modifyResponse -> 'enc_ModifyResponse'(element(2,Val), [<<103>>]); addRequest -> 'enc_AddRequest'(element(2,Val), [<<104>>]); addResponse -> 'enc_AddResponse'(element(2,Val), [<<105>>]); delRequest -> encode_restricted_string(element(2,Val), [<<74>>]); delResponse -> 'enc_DelResponse'(element(2,Val), [<<107>>]); modDNRequest -> 'enc_ModifyDNRequest'(element(2,Val), [<<108>>]); modDNResponse -> 'enc_ModifyDNResponse'(element(2,Val), [<<109>>]); compareRequest -> 'enc_CompareRequest'(element(2,Val), [<<110>>]); compareResponse -> 'enc_CompareResponse'(element(2,Val), [<<111>>]); abandonRequest -> encode_integer(element(2,Val), [<<80>>]); extendedReq -> 'enc_ExtendedRequest'(element(2,Val), [<<119>>]); extendedResp -> 'enc_ExtendedResponse'(element(2,Val), [<<120>>]); Else -> exit({error,{asn1,{invalid_choice_type,Else}}}) end, encode_tags(TagIn, EncBytes, EncLen). 'dec_LDAPMessage_protocolOp'(Tlv, TagIn) -> Tlv1 = match_tags(Tlv, TagIn), case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of %% 'bindRequest' {65536, V1} -> {bindRequest, 'dec_BindRequest'(V1, [])}; %% 'bindResponse' {65537, V1} -> {bindResponse, 'dec_BindResponse'(V1, [])}; %% 'unbindRequest' {65538, V1} -> {unbindRequest, decode_null(V1,[])}; %% 'searchRequest' {65539, V1} -> {searchRequest, 'dec_SearchRequest'(V1, [])}; %% 'searchResEntry' {65540, V1} -> {searchResEntry, 'dec_SearchResultEntry'(V1, [])}; %% 'searchResDone' {65541, V1} -> {searchResDone, 'dec_SearchResultDone'(V1, [])}; %% 'searchResRef' {65555, V1} -> {searchResRef, 'dec_SearchResultReference'(V1, [])}; %% 'modifyRequest' {65542, V1} -> {modifyRequest, 'dec_ModifyRequest'(V1, [])}; %% 'modifyResponse' {65543, V1} -> {modifyResponse, 'dec_ModifyResponse'(V1, [])}; %% 'addRequest' {65544, V1} -> {addRequest, 'dec_AddRequest'(V1, [])}; %% 'addResponse' {65545, V1} -> {addResponse, 'dec_AddResponse'(V1, [])}; %% 'delRequest' {65546, V1} -> {delRequest, decode_restricted_string(V1,[])}; %% 'delResponse' {65547, V1} -> {delResponse, 'dec_DelResponse'(V1, [])}; %% 'modDNRequest' {65548, V1} -> {modDNRequest, 'dec_ModifyDNRequest'(V1, [])}; %% 'modDNResponse' {65549, V1} -> {modDNResponse, 'dec_ModifyDNResponse'(V1, [])}; %% 'compareRequest' {65550, V1} -> {compareRequest, 'dec_CompareRequest'(V1, [])}; %% 'compareResponse' {65551, V1} -> {compareResponse, 'dec_CompareResponse'(V1, [])}; %% 'abandonRequest' {65552, V1} -> {abandonRequest, decode_integer(V1,{0,2147483647},[])}; %% 'extendedReq' {65559, V1} -> {extendedReq, 'dec_ExtendedRequest'(V1, [])}; %% 'extendedResp' {65560, V1} -> {extendedResp, 'dec_ExtendedResponse'(V1, [])}; Else -> exit({error,{asn1,{invalid_choice_tag,Else}}}) end . 'dec_LDAPMessage'(Tlv) -> 'dec_LDAPMessage'(Tlv, [16]). 'dec_LDAPMessage'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute messageID(1) with type INTEGER %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_integer(V1,{0,2147483647},[2]), %%------------------------------------------------- %% attribute protocolOp(2) with type CHOICE %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_LDAPMessage_protocolOp'(V2, []), %%------------------------------------------------- %% attribute controls(3) External ELDAPv3:Controls OPTIONAL %%------------------------------------------------- {Term3,Tlv4} = case Tlv3 of [{131072,V3}|TempTlv4] -> {'dec_Controls'(V3, []), TempTlv4}; _ -> { asn1_NOVALUE, Tlv3} end, case Tlv4 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed end, {'LDAPMessage', Term1, Term2, Term3}. %%================================ %% MessageID %%================================ 'enc_MessageID'(Val) -> 'enc_MessageID'(Val, [<<2>>]). 'enc_MessageID'(Val, TagIn) -> encode_integer(Val, TagIn). 'dec_MessageID'(Tlv) -> 'dec_MessageID'(Tlv, [2]). 'dec_MessageID'(Tlv, TagIn) -> decode_integer(Tlv,{0,2147483647},TagIn). %%================================ %% LDAPString %%================================ 'enc_LDAPString'(Val) -> 'enc_LDAPString'(Val, [<<4>>]). 'enc_LDAPString'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_LDAPString'(Tlv) -> 'dec_LDAPString'(Tlv, [4]). 'dec_LDAPString'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% LDAPOID %%================================ 'enc_LDAPOID'(Val) -> 'enc_LDAPOID'(Val, [<<4>>]). 'enc_LDAPOID'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_LDAPOID'(Tlv) -> 'dec_LDAPOID'(Tlv, [4]). 'dec_LDAPOID'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% LDAPDN %%================================ 'enc_LDAPDN'(Val) -> 'enc_LDAPDN'(Val, [<<4>>]). 'enc_LDAPDN'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_LDAPDN'(Tlv) -> 'dec_LDAPDN'(Tlv, [4]). 'dec_LDAPDN'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% RelativeLDAPDN %%================================ 'enc_RelativeLDAPDN'(Val) -> 'enc_RelativeLDAPDN'(Val, [<<4>>]). 'enc_RelativeLDAPDN'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_RelativeLDAPDN'(Tlv) -> 'dec_RelativeLDAPDN'(Tlv, [4]). 'dec_RelativeLDAPDN'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% AttributeType %%================================ 'enc_AttributeType'(Val) -> 'enc_AttributeType'(Val, [<<4>>]). 'enc_AttributeType'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_AttributeType'(Tlv) -> 'dec_AttributeType'(Tlv, [4]). 'dec_AttributeType'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% AttributeDescription %%================================ 'enc_AttributeDescription'(Val) -> 'enc_AttributeDescription'(Val, [<<4>>]). 'enc_AttributeDescription'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_AttributeDescription'(Tlv) -> 'dec_AttributeDescription'(Tlv, [4]). 'dec_AttributeDescription'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% AttributeDescriptionList %%================================ 'enc_AttributeDescriptionList'(Val) -> 'enc_AttributeDescriptionList'(Val, [<<48>>]). 'enc_AttributeDescriptionList'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_AttributeDescriptionList_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_AttributeDescriptionList_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_AttributeDescriptionList_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]), 'enc_AttributeDescriptionList_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_AttributeDescriptionList'(Tlv) -> 'dec_AttributeDescriptionList'(Tlv, [16]). 'dec_AttributeDescriptionList'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), [decode_restricted_string(V1,[4]) || V1 <- Tlv1]. %%================================ %% AttributeValue %%================================ 'enc_AttributeValue'(Val) -> 'enc_AttributeValue'(Val, [<<4>>]). 'enc_AttributeValue'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_AttributeValue'(Tlv) -> 'dec_AttributeValue'(Tlv, [4]). 'dec_AttributeValue'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% AttributeValueAssertion %%================================ 'enc_AttributeValueAssertion'(Val) -> 'enc_AttributeValueAssertion'(Val, [<<48>>]). 'enc_AttributeValueAssertion'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute attributeDesc(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute assertionValue(2) with type OCTET STRING %%------------------------------------------------- {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<4>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_AttributeValueAssertion'(Tlv) -> 'dec_AttributeValueAssertion'(Tlv, [16]). 'dec_AttributeValueAssertion'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute attributeDesc(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute assertionValue(2) with type OCTET STRING %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = decode_restricted_string(V2,[4]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'AttributeValueAssertion', Term1, Term2}. %%================================ %% AssertionValue %%================================ 'enc_AssertionValue'(Val) -> 'enc_AssertionValue'(Val, [<<4>>]). 'enc_AssertionValue'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_AssertionValue'(Tlv) -> 'dec_AssertionValue'(Tlv, [4]). 'dec_AssertionValue'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% Attribute %%================================ 'enc_Attribute'(Val) -> 'enc_Attribute'(Val, [<<48>>]). 'enc_Attribute'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute vals(2) with type SET OF %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_Attribute_vals'(Cindex2, [<<49>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). %%================================ %% Attribute_vals %%================================ 'enc_Attribute_vals'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_Attribute_vals_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_Attribute_vals_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_Attribute_vals_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]), 'enc_Attribute_vals_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_Attribute_vals'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), [decode_restricted_string(V1,[4]) || V1 <- Tlv1]. 'dec_Attribute'(Tlv) -> 'dec_Attribute'(Tlv, [16]). 'dec_Attribute'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute vals(2) with type SET OF %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_Attribute_vals'(V2, [17]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'Attribute', Term1, Term2}. %%================================ %% MatchingRuleId %%================================ 'enc_MatchingRuleId'(Val) -> 'enc_MatchingRuleId'(Val, [<<4>>]). 'enc_MatchingRuleId'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_MatchingRuleId'(Tlv) -> 'dec_MatchingRuleId'(Tlv, [4]). 'dec_MatchingRuleId'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% LDAPResult %%================================ 'enc_LDAPResult'(Val) -> 'enc_LDAPResult'(Val, [<<48>>]). 'enc_LDAPResult'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3, Cindex4} = Val, %%------------------------------------------------- %% attribute resultCode(1) with type ENUMERATED %%------------------------------------------------- {EncBytes1,EncLen1} = case Cindex1 of success -> encode_enumerated(0, [<<10>>]); operationsError -> encode_enumerated(1, [<<10>>]); protocolError -> encode_enumerated(2, [<<10>>]); timeLimitExceeded -> encode_enumerated(3, [<<10>>]); sizeLimitExceeded -> encode_enumerated(4, [<<10>>]); compareFalse -> encode_enumerated(5, [<<10>>]); compareTrue -> encode_enumerated(6, [<<10>>]); authMethodNotSupported -> encode_enumerated(7, [<<10>>]); strongAuthRequired -> encode_enumerated(8, [<<10>>]); referral -> encode_enumerated(10, [<<10>>]); adminLimitExceeded -> encode_enumerated(11, [<<10>>]); unavailableCriticalExtension -> encode_enumerated(12, [<<10>>]); confidentialityRequired -> encode_enumerated(13, [<<10>>]); saslBindInProgress -> encode_enumerated(14, [<<10>>]); noSuchAttribute -> encode_enumerated(16, [<<10>>]); undefinedAttributeType -> encode_enumerated(17, [<<10>>]); inappropriateMatching -> encode_enumerated(18, [<<10>>]); constraintViolation -> encode_enumerated(19, [<<10>>]); attributeOrValueExists -> encode_enumerated(20, [<<10>>]); invalidAttributeSyntax -> encode_enumerated(21, [<<10>>]); noSuchObject -> encode_enumerated(32, [<<10>>]); aliasProblem -> encode_enumerated(33, [<<10>>]); invalidDNSyntax -> encode_enumerated(34, [<<10>>]); aliasDereferencingProblem -> encode_enumerated(36, [<<10>>]); inappropriateAuthentication -> encode_enumerated(48, [<<10>>]); invalidCredentials -> encode_enumerated(49, [<<10>>]); insufficientAccessRights -> encode_enumerated(50, [<<10>>]); busy -> encode_enumerated(51, [<<10>>]); unavailable -> encode_enumerated(52, [<<10>>]); unwillingToPerform -> encode_enumerated(53, [<<10>>]); loopDetect -> encode_enumerated(54, [<<10>>]); namingViolation -> encode_enumerated(64, [<<10>>]); objectClassViolation -> encode_enumerated(65, [<<10>>]); notAllowedOnNonLeaf -> encode_enumerated(66, [<<10>>]); notAllowedOnRDN -> encode_enumerated(67, [<<10>>]); entryAlreadyExists -> encode_enumerated(68, [<<10>>]); objectClassModsProhibited -> encode_enumerated(69, [<<10>>]); affectsMultipleDSAs -> encode_enumerated(71, [<<10>>]); other -> encode_enumerated(80, [<<10>>]); Enumval1 -> exit({error,{asn1, {enumerated_not_in_range,Enumval1}}}) end, %%------------------------------------------------- %% attribute matchedDN(2) with type OCTET STRING %%------------------------------------------------- {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<4>>]), %%------------------------------------------------- %% attribute errorMessage(3) with type OCTET STRING %%------------------------------------------------- {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<4>>]), %%------------------------------------------------- %% attribute referral(4) External ELDAPv3:Referral OPTIONAL %%------------------------------------------------- {EncBytes4,EncLen4} = case Cindex4 of asn1_NOVALUE -> {<<>>,0}; _ -> 'enc_Referral'(Cindex4, [<<163>>]) end, BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4], LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_LDAPResult'(Tlv) -> 'dec_LDAPResult'(Tlv, [16]). 'dec_LDAPResult'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute resultCode(1) with type ENUMERATED %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_enumerated(V1,[{success,0},{operationsError,1},{protocolError,2},{timeLimitExceeded,3},{sizeLimitExceeded,4},{compareFalse,5},{compareTrue,6},{authMethodNotSupported,7},{strongAuthRequired,8},{referral,10},{adminLimitExceeded,11},{unavailableCriticalExtension,12},{confidentialityRequired,13},{saslBindInProgress,14},{noSuchAttribute,16},{undefinedAttributeType,17},{inappropriateMatching,18},{constraintViolation,19},{attributeOrValueExists,20},{invalidAttributeSyntax,21},{noSuchObject,32},{aliasProblem,33},{invalidDNSyntax,34},{aliasDereferencingProblem,36},{inappropriateAuthentication,48},{invalidCredentials,49},{insufficientAccessRights,50},{busy,51},{unavailable,52},{unwillingToPerform,53},{loopDetect,54},{namingViolation,64},{objectClassViolation,65},{notAllowedOnNonLeaf,66},{notAllowedOnRDN,67},{entryAlreadyExists,68},{objectClassModsProhibited,69},{affectsMultipleDSAs,71},{other,80}],[10]), %%------------------------------------------------- %% attribute matchedDN(2) with type OCTET STRING %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = decode_restricted_string(V2,[4]), %%------------------------------------------------- %% attribute errorMessage(3) with type OCTET STRING %%------------------------------------------------- [V3|Tlv4] = Tlv3, Term3 = decode_restricted_string(V3,[4]), %%------------------------------------------------- %% attribute referral(4) External ELDAPv3:Referral OPTIONAL %%------------------------------------------------- {Term4,Tlv5} = case Tlv4 of [{131075,V4}|TempTlv5] -> {'dec_Referral'(V4, []), TempTlv5}; _ -> { asn1_NOVALUE, Tlv4} end, case Tlv5 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv5}}}) % extra fields not allowed end, {'LDAPResult', Term1, Term2, Term3, Term4}. %%================================ %% Referral %%================================ 'enc_Referral'(Val) -> 'enc_Referral'(Val, [<<48>>]). 'enc_Referral'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_Referral_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_Referral_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_Referral_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]), 'enc_Referral_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_Referral'(Tlv) -> 'dec_Referral'(Tlv, [16]). 'dec_Referral'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), [decode_restricted_string(V1,[4]) || V1 <- Tlv1]. %%================================ %% LDAPURL %%================================ 'enc_LDAPURL'(Val) -> 'enc_LDAPURL'(Val, [<<4>>]). 'enc_LDAPURL'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_LDAPURL'(Tlv) -> 'dec_LDAPURL'(Tlv, [4]). 'dec_LDAPURL'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% Controls %%================================ 'enc_Controls'(Val) -> 'enc_Controls'(Val, [<<48>>]). 'enc_Controls'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_Controls_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_Controls_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_Controls_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = 'enc_Control'(H, [<<48>>]), 'enc_Controls_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_Controls'(Tlv) -> 'dec_Controls'(Tlv, [16]). 'dec_Controls'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), ['dec_Control'(V1, [16]) || V1 <- Tlv1]. %%================================ %% Control %%================================ 'enc_Control'(Val) -> 'enc_Control'(Val, [<<48>>]). 'enc_Control'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3} = Val, %%------------------------------------------------- %% attribute controlType(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute criticality(2) with type BOOLEAN DEFAULT = false %%------------------------------------------------- {EncBytes2,EncLen2} = case Cindex2 of asn1_DEFAULT -> {<<>>,0}; false -> {<<>>,0}; _ -> encode_boolean(Cindex2, [<<1>>]) end, %%------------------------------------------------- %% attribute controlValue(3) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes3,EncLen3} = case Cindex3 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex3, [<<4>>]) end, BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], LenSoFar = EncLen1 + EncLen2 + EncLen3, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_Control'(Tlv) -> 'dec_Control'(Tlv, [16]). 'dec_Control'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute controlType(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute criticality(2) with type BOOLEAN DEFAULT = false %%------------------------------------------------- {Term2,Tlv3} = case Tlv2 of [{1,V2}|TempTlv3] -> {decode_boolean(V2,[]), TempTlv3}; _ -> {false,Tlv2} end, %%------------------------------------------------- %% attribute controlValue(3) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term3,Tlv4} = case Tlv3 of [{4,V3}|TempTlv4] -> {decode_restricted_string(V3,[]), TempTlv4}; _ -> { asn1_NOVALUE, Tlv3} end, case Tlv4 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed end, {'Control', Term1, Term2, Term3}. %%================================ %% BindRequest %%================================ 'enc_BindRequest'(Val) -> 'enc_BindRequest'(Val, [<<96>>]). 'enc_BindRequest'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3} = Val, %%------------------------------------------------- %% attribute version(1) with type INTEGER %%------------------------------------------------- {EncBytes1,EncLen1} = encode_integer(Cindex1, [<<2>>]), %%------------------------------------------------- %% attribute name(2) with type OCTET STRING %%------------------------------------------------- {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<4>>]), %%------------------------------------------------- %% attribute authentication(3) External ELDAPv3:AuthenticationChoice %%------------------------------------------------- {EncBytes3,EncLen3} = 'enc_AuthenticationChoice'(Cindex3, []), BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], LenSoFar = EncLen1 + EncLen2 + EncLen3, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_BindRequest'(Tlv) -> 'dec_BindRequest'(Tlv, [65536]). 'dec_BindRequest'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute version(1) with type INTEGER %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_integer(V1,{1,127},[2]), %%------------------------------------------------- %% attribute name(2) with type OCTET STRING %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = decode_restricted_string(V2,[4]), %%------------------------------------------------- %% attribute authentication(3) External ELDAPv3:AuthenticationChoice %%------------------------------------------------- [V3|Tlv4] = Tlv3, Term3 = 'dec_AuthenticationChoice'(V3, []), case Tlv4 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed end, {'BindRequest', Term1, Term2, Term3}. %%================================ %% AuthenticationChoice %%================================ 'enc_AuthenticationChoice'(Val) -> 'enc_AuthenticationChoice'(Val, []). 'enc_AuthenticationChoice'(Val, TagIn) -> {EncBytes,EncLen} = case element(1,Val) of simple -> encode_restricted_string(element(2,Val), [<<128>>]); sasl -> 'enc_SaslCredentials'(element(2,Val), [<<163>>]); Else -> exit({error,{asn1,{invalid_choice_type,Else}}}) end, encode_tags(TagIn, EncBytes, EncLen). 'dec_AuthenticationChoice'(Tlv) -> 'dec_AuthenticationChoice'(Tlv, []). 'dec_AuthenticationChoice'(Tlv, TagIn) -> Tlv1 = match_tags(Tlv, TagIn), case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of %% 'simple' {131072, V1} -> {simple, decode_restricted_string(V1,[])}; %% 'sasl' {131075, V1} -> {sasl, 'dec_SaslCredentials'(V1, [])}; Else -> exit({error,{asn1,{invalid_choice_tag,Else}}}) end . %%================================ %% SaslCredentials %%================================ 'enc_SaslCredentials'(Val) -> 'enc_SaslCredentials'(Val, [<<48>>]). 'enc_SaslCredentials'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute mechanism(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute credentials(2) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes2,EncLen2} = case Cindex2 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex2, [<<4>>]) end, BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_SaslCredentials'(Tlv) -> 'dec_SaslCredentials'(Tlv, [16]). 'dec_SaslCredentials'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute mechanism(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute credentials(2) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term2,Tlv3} = case Tlv2 of [{4,V2}|TempTlv3] -> {decode_restricted_string(V2,[]), TempTlv3}; _ -> { asn1_NOVALUE, Tlv2} end, case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'SaslCredentials', Term1, Term2}. %%================================ %% BindResponse %%================================ 'enc_BindResponse'(Val) -> 'enc_BindResponse'(Val, [<<97>>]). 'enc_BindResponse'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3, Cindex4, Cindex5} = Val, %%------------------------------------------------- %% attribute resultCode(1) with type ENUMERATED %%------------------------------------------------- {EncBytes1,EncLen1} = case Cindex1 of success -> encode_enumerated(0, [<<10>>]); operationsError -> encode_enumerated(1, [<<10>>]); protocolError -> encode_enumerated(2, [<<10>>]); timeLimitExceeded -> encode_enumerated(3, [<<10>>]); sizeLimitExceeded -> encode_enumerated(4, [<<10>>]); compareFalse -> encode_enumerated(5, [<<10>>]); compareTrue -> encode_enumerated(6, [<<10>>]); authMethodNotSupported -> encode_enumerated(7, [<<10>>]); strongAuthRequired -> encode_enumerated(8, [<<10>>]); referral -> encode_enumerated(10, [<<10>>]); adminLimitExceeded -> encode_enumerated(11, [<<10>>]); unavailableCriticalExtension -> encode_enumerated(12, [<<10>>]); confidentialityRequired -> encode_enumerated(13, [<<10>>]); saslBindInProgress -> encode_enumerated(14, [<<10>>]); noSuchAttribute -> encode_enumerated(16, [<<10>>]); undefinedAttributeType -> encode_enumerated(17, [<<10>>]); inappropriateMatching -> encode_enumerated(18, [<<10>>]); constraintViolation -> encode_enumerated(19, [<<10>>]); attributeOrValueExists -> encode_enumerated(20, [<<10>>]); invalidAttributeSyntax -> encode_enumerated(21, [<<10>>]); noSuchObject -> encode_enumerated(32, [<<10>>]); aliasProblem -> encode_enumerated(33, [<<10>>]); invalidDNSyntax -> encode_enumerated(34, [<<10>>]); aliasDereferencingProblem -> encode_enumerated(36, [<<10>>]); inappropriateAuthentication -> encode_enumerated(48, [<<10>>]); invalidCredentials -> encode_enumerated(49, [<<10>>]); insufficientAccessRights -> encode_enumerated(50, [<<10>>]); busy -> encode_enumerated(51, [<<10>>]); unavailable -> encode_enumerated(52, [<<10>>]); unwillingToPerform -> encode_enumerated(53, [<<10>>]); loopDetect -> encode_enumerated(54, [<<10>>]); namingViolation -> encode_enumerated(64, [<<10>>]); objectClassViolation -> encode_enumerated(65, [<<10>>]); notAllowedOnNonLeaf -> encode_enumerated(66, [<<10>>]); notAllowedOnRDN -> encode_enumerated(67, [<<10>>]); entryAlreadyExists -> encode_enumerated(68, [<<10>>]); objectClassModsProhibited -> encode_enumerated(69, [<<10>>]); affectsMultipleDSAs -> encode_enumerated(71, [<<10>>]); other -> encode_enumerated(80, [<<10>>]); Enumval1 -> exit({error,{asn1, {enumerated_not_in_range,Enumval1}}}) end, %%------------------------------------------------- %% attribute matchedDN(2) with type OCTET STRING %%------------------------------------------------- {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<4>>]), %%------------------------------------------------- %% attribute errorMessage(3) with type OCTET STRING %%------------------------------------------------- {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<4>>]), %%------------------------------------------------- %% attribute referral(4) External ELDAPv3:Referral OPTIONAL %%------------------------------------------------- {EncBytes4,EncLen4} = case Cindex4 of asn1_NOVALUE -> {<<>>,0}; _ -> 'enc_Referral'(Cindex4, [<<163>>]) end, %%------------------------------------------------- %% attribute serverSaslCreds(5) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes5,EncLen5} = case Cindex5 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex5, [<<135>>]) end, BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5], LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_BindResponse'(Tlv) -> 'dec_BindResponse'(Tlv, [65537]). 'dec_BindResponse'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute resultCode(1) with type ENUMERATED %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_enumerated(V1,[{success,0},{operationsError,1},{protocolError,2},{timeLimitExceeded,3},{sizeLimitExceeded,4},{compareFalse,5},{compareTrue,6},{authMethodNotSupported,7},{strongAuthRequired,8},{referral,10},{adminLimitExceeded,11},{unavailableCriticalExtension,12},{confidentialityRequired,13},{saslBindInProgress,14},{noSuchAttribute,16},{undefinedAttributeType,17},{inappropriateMatching,18},{constraintViolation,19},{attributeOrValueExists,20},{invalidAttributeSyntax,21},{noSuchObject,32},{aliasProblem,33},{invalidDNSyntax,34},{aliasDereferencingProblem,36},{inappropriateAuthentication,48},{invalidCredentials,49},{insufficientAccessRights,50},{busy,51},{unavailable,52},{unwillingToPerform,53},{loopDetect,54},{namingViolation,64},{objectClassViolation,65},{notAllowedOnNonLeaf,66},{notAllowedOnRDN,67},{entryAlreadyExists,68},{objectClassModsProhibited,69},{affectsMultipleDSAs,71},{other,80}],[10]), %%------------------------------------------------- %% attribute matchedDN(2) with type OCTET STRING %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = decode_restricted_string(V2,[4]), %%------------------------------------------------- %% attribute errorMessage(3) with type OCTET STRING %%------------------------------------------------- [V3|Tlv4] = Tlv3, Term3 = decode_restricted_string(V3,[4]), %%------------------------------------------------- %% attribute referral(4) External ELDAPv3:Referral OPTIONAL %%------------------------------------------------- {Term4,Tlv5} = case Tlv4 of [{131075,V4}|TempTlv5] -> {'dec_Referral'(V4, []), TempTlv5}; _ -> { asn1_NOVALUE, Tlv4} end, %%------------------------------------------------- %% attribute serverSaslCreds(5) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term5,Tlv6} = case Tlv5 of [{131079,V5}|TempTlv6] -> {decode_restricted_string(V5,[]), TempTlv6}; _ -> { asn1_NOVALUE, Tlv5} end, case Tlv6 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv6}}}) % extra fields not allowed end, {'BindResponse', Term1, Term2, Term3, Term4, Term5}. %%================================ %% UnbindRequest %%================================ 'enc_UnbindRequest'(Val) -> 'enc_UnbindRequest'(Val, [<<66>>]). 'enc_UnbindRequest'(Val, TagIn) -> encode_null(Val, TagIn). 'dec_UnbindRequest'(Tlv) -> 'dec_UnbindRequest'(Tlv, [65538]). 'dec_UnbindRequest'(Tlv, TagIn) -> decode_null(Tlv,TagIn). %%================================ %% SearchRequest %%================================ 'enc_SearchRequest'(Val) -> 'enc_SearchRequest'(Val, [<<99>>]). 'enc_SearchRequest'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3, Cindex4, Cindex5, Cindex6, Cindex7, Cindex8} = Val, %%------------------------------------------------- %% attribute baseObject(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute scope(2) with type ENUMERATED %%------------------------------------------------- {EncBytes2,EncLen2} = case Cindex2 of baseObject -> encode_enumerated(0, [<<10>>]); singleLevel -> encode_enumerated(1, [<<10>>]); wholeSubtree -> encode_enumerated(2, [<<10>>]); Enumval2 -> exit({error,{asn1, {enumerated_not_in_range,Enumval2}}}) end, %%------------------------------------------------- %% attribute derefAliases(3) with type ENUMERATED %%------------------------------------------------- {EncBytes3,EncLen3} = case Cindex3 of neverDerefAliases -> encode_enumerated(0, [<<10>>]); derefInSearching -> encode_enumerated(1, [<<10>>]); derefFindingBaseObj -> encode_enumerated(2, [<<10>>]); derefAlways -> encode_enumerated(3, [<<10>>]); Enumval3 -> exit({error,{asn1, {enumerated_not_in_range,Enumval3}}}) end, %%------------------------------------------------- %% attribute sizeLimit(4) with type INTEGER %%------------------------------------------------- {EncBytes4,EncLen4} = encode_integer(Cindex4, [<<2>>]), %%------------------------------------------------- %% attribute timeLimit(5) with type INTEGER %%------------------------------------------------- {EncBytes5,EncLen5} = encode_integer(Cindex5, [<<2>>]), %%------------------------------------------------- %% attribute typesOnly(6) with type BOOLEAN %%------------------------------------------------- {EncBytes6,EncLen6} = encode_boolean(Cindex6, [<<1>>]), %%------------------------------------------------- %% attribute filter(7) External ELDAPv3:Filter %%------------------------------------------------- {EncBytes7,EncLen7} = 'enc_Filter'(Cindex7, []), %%------------------------------------------------- %% attribute attributes(8) External ELDAPv3:AttributeDescriptionList %%------------------------------------------------- {EncBytes8,EncLen8} = 'enc_AttributeDescriptionList'(Cindex8, [<<48>>]), BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5, EncBytes6, EncBytes7, EncBytes8], LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5 + EncLen6 + EncLen7 + EncLen8, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_SearchRequest'(Tlv) -> 'dec_SearchRequest'(Tlv, [65539]). 'dec_SearchRequest'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute baseObject(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute scope(2) with type ENUMERATED %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = decode_enumerated(V2,[{baseObject,0},{singleLevel,1},{wholeSubtree,2}],[10]), %%------------------------------------------------- %% attribute derefAliases(3) with type ENUMERATED %%------------------------------------------------- [V3|Tlv4] = Tlv3, Term3 = decode_enumerated(V3,[{neverDerefAliases,0},{derefInSearching,1},{derefFindingBaseObj,2},{derefAlways,3}],[10]), %%------------------------------------------------- %% attribute sizeLimit(4) with type INTEGER %%------------------------------------------------- [V4|Tlv5] = Tlv4, Term4 = decode_integer(V4,{0,2147483647},[2]), %%------------------------------------------------- %% attribute timeLimit(5) with type INTEGER %%------------------------------------------------- [V5|Tlv6] = Tlv5, Term5 = decode_integer(V5,{0,2147483647},[2]), %%------------------------------------------------- %% attribute typesOnly(6) with type BOOLEAN %%------------------------------------------------- [V6|Tlv7] = Tlv6, Term6 = decode_boolean(V6,[1]), %%------------------------------------------------- %% attribute filter(7) External ELDAPv3:Filter %%------------------------------------------------- [V7|Tlv8] = Tlv7, Term7 = 'dec_Filter'(V7, []), %%------------------------------------------------- %% attribute attributes(8) External ELDAPv3:AttributeDescriptionList %%------------------------------------------------- [V8|Tlv9] = Tlv8, Term8 = 'dec_AttributeDescriptionList'(V8, [16]), case Tlv9 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv9}}}) % extra fields not allowed end, {'SearchRequest', Term1, Term2, Term3, Term4, Term5, Term6, Term7, Term8}. %%================================ %% Filter %%================================ 'enc_Filter'(Val) -> 'enc_Filter'(Val, []). 'enc_Filter'(Val, TagIn) -> {EncBytes,EncLen} = case element(1,Val) of 'and' -> 'enc_Filter_and'(element(2,Val), [<<160>>]); 'or' -> 'enc_Filter_or'(element(2,Val), [<<161>>]); 'not' -> 'enc_Filter'(element(2,Val), [<<162>>]); equalityMatch -> 'enc_AttributeValueAssertion'(element(2,Val), [<<163>>]); substrings -> 'enc_SubstringFilter'(element(2,Val), [<<164>>]); greaterOrEqual -> 'enc_AttributeValueAssertion'(element(2,Val), [<<165>>]); lessOrEqual -> 'enc_AttributeValueAssertion'(element(2,Val), [<<166>>]); present -> encode_restricted_string(element(2,Val), [<<135>>]); approxMatch -> 'enc_AttributeValueAssertion'(element(2,Val), [<<168>>]); extensibleMatch -> 'enc_MatchingRuleAssertion'(element(2,Val), [<<169>>]); Else -> exit({error,{asn1,{invalid_choice_type,Else}}}) end, encode_tags(TagIn, EncBytes, EncLen). %%================================ %% Filter_and %%================================ 'enc_Filter_and'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_Filter_and_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_Filter_and_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_Filter_and_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = 'enc_Filter'(H, []), 'enc_Filter_and_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_Filter_and'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), ['dec_Filter'(V1, []) || V1 <- Tlv1]. %%================================ %% Filter_or %%================================ 'enc_Filter_or'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_Filter_or_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_Filter_or_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_Filter_or_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = 'enc_Filter'(H, []), 'enc_Filter_or_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_Filter_or'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), ['dec_Filter'(V1, []) || V1 <- Tlv1]. 'dec_Filter'(Tlv) -> 'dec_Filter'(Tlv, []). 'dec_Filter'(Tlv, TagIn) -> Tlv1 = match_tags(Tlv, TagIn), case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of %% 'and' {131072, V1} -> {'and', 'dec_Filter_and'(V1, [])}; %% 'or' {131073, V1} -> {'or', 'dec_Filter_or'(V1, [])}; %% 'not' {131074, V1} -> {'not', 'dec_Filter'(V1, [])}; %% 'equalityMatch' {131075, V1} -> {equalityMatch, 'dec_AttributeValueAssertion'(V1, [])}; %% 'substrings' {131076, V1} -> {substrings, 'dec_SubstringFilter'(V1, [])}; %% 'greaterOrEqual' {131077, V1} -> {greaterOrEqual, 'dec_AttributeValueAssertion'(V1, [])}; %% 'lessOrEqual' {131078, V1} -> {lessOrEqual, 'dec_AttributeValueAssertion'(V1, [])}; %% 'present' {131079, V1} -> {present, decode_restricted_string(V1,[])}; %% 'approxMatch' {131080, V1} -> {approxMatch, 'dec_AttributeValueAssertion'(V1, [])}; %% 'extensibleMatch' {131081, V1} -> {extensibleMatch, 'dec_MatchingRuleAssertion'(V1, [])}; Else -> exit({error,{asn1,{invalid_choice_tag,Else}}}) end . %%================================ %% SubstringFilter %%================================ 'enc_SubstringFilter'(Val) -> 'enc_SubstringFilter'(Val, [<<48>>]). 'enc_SubstringFilter'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute substrings(2) with type SEQUENCE OF %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_SubstringFilter_substrings'(Cindex2, [<<48>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). %%================================ %% SubstringFilter_substrings %%================================ 'enc_SubstringFilter_substrings'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_SubstringFilter_substrings_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_SubstringFilter_substrings_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_SubstringFilter_substrings_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = 'enc_SubstringFilter_substrings_SEQOF'(H, []), 'enc_SubstringFilter_substrings_components'(T,[EncBytes|AccBytes], AccLen + EncLen). %%================================ %% SubstringFilter_substrings_SEQOF %%================================ 'enc_SubstringFilter_substrings_SEQOF'(Val, TagIn) -> {EncBytes,EncLen} = case element(1,Val) of initial -> encode_restricted_string(element(2,Val), [<<128>>]); any -> encode_restricted_string(element(2,Val), [<<129>>]); final -> encode_restricted_string(element(2,Val), [<<130>>]); Else -> exit({error,{asn1,{invalid_choice_type,Else}}}) end, encode_tags(TagIn, EncBytes, EncLen). 'dec_SubstringFilter_substrings_SEQOF'(Tlv, TagIn) -> Tlv1 = match_tags(Tlv, TagIn), case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of %% 'initial' {131072, V1} -> {initial, decode_restricted_string(V1,[])}; %% 'any' {131073, V1} -> {any, decode_restricted_string(V1,[])}; %% 'final' {131074, V1} -> {final, decode_restricted_string(V1,[])}; Else -> exit({error,{asn1,{invalid_choice_tag,Else}}}) end . 'dec_SubstringFilter_substrings'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), ['dec_SubstringFilter_substrings_SEQOF'(V1, []) || V1 <- Tlv1]. 'dec_SubstringFilter'(Tlv) -> 'dec_SubstringFilter'(Tlv, [16]). 'dec_SubstringFilter'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute substrings(2) with type SEQUENCE OF %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_SubstringFilter_substrings'(V2, [16]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'SubstringFilter', Term1, Term2}. %%================================ %% MatchingRuleAssertion %%================================ 'enc_MatchingRuleAssertion'(Val) -> 'enc_MatchingRuleAssertion'(Val, [<<48>>]). 'enc_MatchingRuleAssertion'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3, Cindex4} = Val, %%------------------------------------------------- %% attribute matchingRule(1) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes1,EncLen1} = case Cindex1 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex1, [<<129>>]) end, %%------------------------------------------------- %% attribute type(2) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes2,EncLen2} = case Cindex2 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex2, [<<130>>]) end, %%------------------------------------------------- %% attribute matchValue(3) with type OCTET STRING %%------------------------------------------------- {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<131>>]), %%------------------------------------------------- %% attribute dnAttributes(4) with type BOOLEAN DEFAULT = false %%------------------------------------------------- {EncBytes4,EncLen4} = case Cindex4 of asn1_DEFAULT -> {<<>>,0}; false -> {<<>>,0}; _ -> encode_boolean(Cindex4, [<<132>>]) end, BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4], LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_MatchingRuleAssertion'(Tlv) -> 'dec_MatchingRuleAssertion'(Tlv, [16]). 'dec_MatchingRuleAssertion'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute matchingRule(1) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term1,Tlv2} = case Tlv1 of [{131073,V1}|TempTlv2] -> {decode_restricted_string(V1,[]), TempTlv2}; _ -> { asn1_NOVALUE, Tlv1} end, %%------------------------------------------------- %% attribute type(2) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term2,Tlv3} = case Tlv2 of [{131074,V2}|TempTlv3] -> {decode_restricted_string(V2,[]), TempTlv3}; _ -> { asn1_NOVALUE, Tlv2} end, %%------------------------------------------------- %% attribute matchValue(3) with type OCTET STRING %%------------------------------------------------- [V3|Tlv4] = Tlv3, Term3 = decode_restricted_string(V3,[131075]), %%------------------------------------------------- %% attribute dnAttributes(4) with type BOOLEAN DEFAULT = false %%------------------------------------------------- {Term4,Tlv5} = case Tlv4 of [{131076,V4}|TempTlv5] -> {decode_boolean(V4,[]), TempTlv5}; _ -> {false,Tlv4} end, case Tlv5 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv5}}}) % extra fields not allowed end, {'MatchingRuleAssertion', Term1, Term2, Term3, Term4}. %%================================ %% SearchResultEntry %%================================ 'enc_SearchResultEntry'(Val) -> 'enc_SearchResultEntry'(Val, [<<100>>]). 'enc_SearchResultEntry'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute objectName(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute attributes(2) External ELDAPv3:PartialAttributeList %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_PartialAttributeList'(Cindex2, [<<48>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_SearchResultEntry'(Tlv) -> 'dec_SearchResultEntry'(Tlv, [65540]). 'dec_SearchResultEntry'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute objectName(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute attributes(2) External ELDAPv3:PartialAttributeList %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_PartialAttributeList'(V2, [16]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'SearchResultEntry', Term1, Term2}. %%================================ %% PartialAttributeList %%================================ 'enc_PartialAttributeList'(Val) -> 'enc_PartialAttributeList'(Val, [<<48>>]). 'enc_PartialAttributeList'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_PartialAttributeList_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_PartialAttributeList_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_PartialAttributeList_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = 'enc_PartialAttributeList_SEQOF'(H, [<<48>>]), 'enc_PartialAttributeList_components'(T,[EncBytes|AccBytes], AccLen + EncLen). %%================================ %% PartialAttributeList_SEQOF %%================================ 'enc_PartialAttributeList_SEQOF'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute vals(2) with type SET OF %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_PartialAttributeList_SEQOF_vals'(Cindex2, [<<49>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). %%================================ %% PartialAttributeList_SEQOF_vals %%================================ 'enc_PartialAttributeList_SEQOF_vals'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_PartialAttributeList_SEQOF_vals_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_PartialAttributeList_SEQOF_vals_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_PartialAttributeList_SEQOF_vals_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]), 'enc_PartialAttributeList_SEQOF_vals_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_PartialAttributeList_SEQOF_vals'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), [decode_restricted_string(V1,[4]) || V1 <- Tlv1]. 'dec_PartialAttributeList_SEQOF'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute vals(2) with type SET OF %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_PartialAttributeList_SEQOF_vals'(V2, [17]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'PartialAttributeList_SEQOF', Term1, Term2}. 'dec_PartialAttributeList'(Tlv) -> 'dec_PartialAttributeList'(Tlv, [16]). 'dec_PartialAttributeList'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), ['dec_PartialAttributeList_SEQOF'(V1, [16]) || V1 <- Tlv1]. %%================================ %% SearchResultReference %%================================ 'enc_SearchResultReference'(Val) -> 'enc_SearchResultReference'(Val, [<<115>>]). 'enc_SearchResultReference'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_SearchResultReference_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_SearchResultReference_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_SearchResultReference_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]), 'enc_SearchResultReference_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_SearchResultReference'(Tlv) -> 'dec_SearchResultReference'(Tlv, [65555]). 'dec_SearchResultReference'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), [decode_restricted_string(V1,[4]) || V1 <- Tlv1]. %%================================ %% SearchResultDone %%================================ 'enc_SearchResultDone'(Val) -> 'enc_SearchResultDone'(Val, [<<101>>]). 'enc_SearchResultDone'(Val, TagIn) -> 'enc_LDAPResult'(Val, TagIn). 'dec_SearchResultDone'(Tlv) -> 'dec_SearchResultDone'(Tlv, [65541]). 'dec_SearchResultDone'(Tlv, TagIn) -> 'dec_LDAPResult'(Tlv, TagIn). %%================================ %% ModifyRequest %%================================ 'enc_ModifyRequest'(Val) -> 'enc_ModifyRequest'(Val, [<<102>>]). 'enc_ModifyRequest'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute object(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute modification(2) with type SEQUENCE OF %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_ModifyRequest_modification'(Cindex2, [<<48>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). %%================================ %% ModifyRequest_modification %%================================ 'enc_ModifyRequest_modification'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_ModifyRequest_modification_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_ModifyRequest_modification_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_ModifyRequest_modification_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = 'enc_ModifyRequest_modification_SEQOF'(H, [<<48>>]), 'enc_ModifyRequest_modification_components'(T,[EncBytes|AccBytes], AccLen + EncLen). %%================================ %% ModifyRequest_modification_SEQOF %%================================ 'enc_ModifyRequest_modification_SEQOF'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute operation(1) with type ENUMERATED %%------------------------------------------------- {EncBytes1,EncLen1} = case Cindex1 of add -> encode_enumerated(0, [<<10>>]); delete -> encode_enumerated(1, [<<10>>]); replace -> encode_enumerated(2, [<<10>>]); Enumval1 -> exit({error,{asn1, {enumerated_not_in_range,Enumval1}}}) end, %%------------------------------------------------- %% attribute modification(2) External ELDAPv3:AttributeTypeAndValues %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_AttributeTypeAndValues'(Cindex2, [<<48>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_ModifyRequest_modification_SEQOF'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute operation(1) with type ENUMERATED %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_enumerated(V1,[{add,0},{delete,1},{replace,2}],[10]), %%------------------------------------------------- %% attribute modification(2) External ELDAPv3:AttributeTypeAndValues %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_AttributeTypeAndValues'(V2, [16]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'ModifyRequest_modification_SEQOF', Term1, Term2}. 'dec_ModifyRequest_modification'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), ['dec_ModifyRequest_modification_SEQOF'(V1, [16]) || V1 <- Tlv1]. 'dec_ModifyRequest'(Tlv) -> 'dec_ModifyRequest'(Tlv, [65542]). 'dec_ModifyRequest'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute object(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute modification(2) with type SEQUENCE OF %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_ModifyRequest_modification'(V2, [16]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'ModifyRequest', Term1, Term2}. %%================================ %% AttributeTypeAndValues %%================================ 'enc_AttributeTypeAndValues'(Val) -> 'enc_AttributeTypeAndValues'(Val, [<<48>>]). 'enc_AttributeTypeAndValues'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute vals(2) with type SET OF %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_AttributeTypeAndValues_vals'(Cindex2, [<<49>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). %%================================ %% AttributeTypeAndValues_vals %%================================ 'enc_AttributeTypeAndValues_vals'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_AttributeTypeAndValues_vals_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_AttributeTypeAndValues_vals_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_AttributeTypeAndValues_vals_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]), 'enc_AttributeTypeAndValues_vals_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_AttributeTypeAndValues_vals'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), [decode_restricted_string(V1,[4]) || V1 <- Tlv1]. 'dec_AttributeTypeAndValues'(Tlv) -> 'dec_AttributeTypeAndValues'(Tlv, [16]). 'dec_AttributeTypeAndValues'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute vals(2) with type SET OF %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_AttributeTypeAndValues_vals'(V2, [17]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'AttributeTypeAndValues', Term1, Term2}. %%================================ %% ModifyResponse %%================================ 'enc_ModifyResponse'(Val) -> 'enc_ModifyResponse'(Val, [<<103>>]). 'enc_ModifyResponse'(Val, TagIn) -> 'enc_LDAPResult'(Val, TagIn). 'dec_ModifyResponse'(Tlv) -> 'dec_ModifyResponse'(Tlv, [65543]). 'dec_ModifyResponse'(Tlv, TagIn) -> 'dec_LDAPResult'(Tlv, TagIn). %%================================ %% AddRequest %%================================ 'enc_AddRequest'(Val) -> 'enc_AddRequest'(Val, [<<104>>]). 'enc_AddRequest'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute entry(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute attributes(2) External ELDAPv3:AttributeList %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_AttributeList'(Cindex2, [<<48>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_AddRequest'(Tlv) -> 'dec_AddRequest'(Tlv, [65544]). 'dec_AddRequest'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute entry(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute attributes(2) External ELDAPv3:AttributeList %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_AttributeList'(V2, [16]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'AddRequest', Term1, Term2}. %%================================ %% AttributeList %%================================ 'enc_AttributeList'(Val) -> 'enc_AttributeList'(Val, [<<48>>]). 'enc_AttributeList'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_AttributeList_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_AttributeList_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_AttributeList_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = 'enc_AttributeList_SEQOF'(H, [<<48>>]), 'enc_AttributeList_components'(T,[EncBytes|AccBytes], AccLen + EncLen). %%================================ %% AttributeList_SEQOF %%================================ 'enc_AttributeList_SEQOF'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute vals(2) with type SET OF %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_AttributeList_SEQOF_vals'(Cindex2, [<<49>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). %%================================ %% AttributeList_SEQOF_vals %%================================ 'enc_AttributeList_SEQOF_vals'(Val, TagIn) -> {EncBytes,EncLen} = 'enc_AttributeList_SEQOF_vals_components'(Val,[],0), encode_tags(TagIn, EncBytes, EncLen). 'enc_AttributeList_SEQOF_vals_components'([], AccBytes, AccLen) -> {lists:reverse(AccBytes),AccLen}; 'enc_AttributeList_SEQOF_vals_components'([H|T],AccBytes, AccLen) -> {EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]), 'enc_AttributeList_SEQOF_vals_components'(T,[EncBytes|AccBytes], AccLen + EncLen). 'dec_AttributeList_SEQOF_vals'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), [decode_restricted_string(V1,[4]) || V1 <- Tlv1]. 'dec_AttributeList_SEQOF'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute type(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute vals(2) with type SET OF %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_AttributeList_SEQOF_vals'(V2, [17]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'AttributeList_SEQOF', Term1, Term2}. 'dec_AttributeList'(Tlv) -> 'dec_AttributeList'(Tlv, [16]). 'dec_AttributeList'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), ['dec_AttributeList_SEQOF'(V1, [16]) || V1 <- Tlv1]. %%================================ %% AddResponse %%================================ 'enc_AddResponse'(Val) -> 'enc_AddResponse'(Val, [<<105>>]). 'enc_AddResponse'(Val, TagIn) -> 'enc_LDAPResult'(Val, TagIn). 'dec_AddResponse'(Tlv) -> 'dec_AddResponse'(Tlv, [65545]). 'dec_AddResponse'(Tlv, TagIn) -> 'dec_LDAPResult'(Tlv, TagIn). %%================================ %% DelRequest %%================================ 'enc_DelRequest'(Val) -> 'enc_DelRequest'(Val, [<<74>>]). 'enc_DelRequest'(Val, TagIn) -> encode_restricted_string(Val, TagIn). 'dec_DelRequest'(Tlv) -> 'dec_DelRequest'(Tlv, [65546]). 'dec_DelRequest'(Tlv, TagIn) -> decode_restricted_string(Tlv,TagIn). %%================================ %% DelResponse %%================================ 'enc_DelResponse'(Val) -> 'enc_DelResponse'(Val, [<<107>>]). 'enc_DelResponse'(Val, TagIn) -> 'enc_LDAPResult'(Val, TagIn). 'dec_DelResponse'(Tlv) -> 'dec_DelResponse'(Tlv, [65547]). 'dec_DelResponse'(Tlv, TagIn) -> 'dec_LDAPResult'(Tlv, TagIn). %%================================ %% ModifyDNRequest %%================================ 'enc_ModifyDNRequest'(Val) -> 'enc_ModifyDNRequest'(Val, [<<108>>]). 'enc_ModifyDNRequest'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3, Cindex4} = Val, %%------------------------------------------------- %% attribute entry(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute newrdn(2) with type OCTET STRING %%------------------------------------------------- {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<4>>]), %%------------------------------------------------- %% attribute deleteoldrdn(3) with type BOOLEAN %%------------------------------------------------- {EncBytes3,EncLen3} = encode_boolean(Cindex3, [<<1>>]), %%------------------------------------------------- %% attribute newSuperior(4) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes4,EncLen4} = case Cindex4 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex4, [<<128>>]) end, BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4], LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_ModifyDNRequest'(Tlv) -> 'dec_ModifyDNRequest'(Tlv, [65548]). 'dec_ModifyDNRequest'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute entry(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute newrdn(2) with type OCTET STRING %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = decode_restricted_string(V2,[4]), %%------------------------------------------------- %% attribute deleteoldrdn(3) with type BOOLEAN %%------------------------------------------------- [V3|Tlv4] = Tlv3, Term3 = decode_boolean(V3,[1]), %%------------------------------------------------- %% attribute newSuperior(4) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term4,Tlv5} = case Tlv4 of [{131072,V4}|TempTlv5] -> {decode_restricted_string(V4,[]), TempTlv5}; _ -> { asn1_NOVALUE, Tlv4} end, case Tlv5 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv5}}}) % extra fields not allowed end, {'ModifyDNRequest', Term1, Term2, Term3, Term4}. %%================================ %% ModifyDNResponse %%================================ 'enc_ModifyDNResponse'(Val) -> 'enc_ModifyDNResponse'(Val, [<<109>>]). 'enc_ModifyDNResponse'(Val, TagIn) -> 'enc_LDAPResult'(Val, TagIn). 'dec_ModifyDNResponse'(Tlv) -> 'dec_ModifyDNResponse'(Tlv, [65549]). 'dec_ModifyDNResponse'(Tlv, TagIn) -> 'dec_LDAPResult'(Tlv, TagIn). %%================================ %% CompareRequest %%================================ 'enc_CompareRequest'(Val) -> 'enc_CompareRequest'(Val, [<<110>>]). 'enc_CompareRequest'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute entry(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<4>>]), %%------------------------------------------------- %% attribute ava(2) External ELDAPv3:AttributeValueAssertion %%------------------------------------------------- {EncBytes2,EncLen2} = 'enc_AttributeValueAssertion'(Cindex2, [<<48>>]), BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_CompareRequest'(Tlv) -> 'dec_CompareRequest'(Tlv, [65550]). 'dec_CompareRequest'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute entry(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[4]), %%------------------------------------------------- %% attribute ava(2) External ELDAPv3:AttributeValueAssertion %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = 'dec_AttributeValueAssertion'(V2, [16]), case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'CompareRequest', Term1, Term2}. %%================================ %% CompareResponse %%================================ 'enc_CompareResponse'(Val) -> 'enc_CompareResponse'(Val, [<<111>>]). 'enc_CompareResponse'(Val, TagIn) -> 'enc_LDAPResult'(Val, TagIn). 'dec_CompareResponse'(Tlv) -> 'dec_CompareResponse'(Tlv, [65551]). 'dec_CompareResponse'(Tlv, TagIn) -> 'dec_LDAPResult'(Tlv, TagIn). %%================================ %% AbandonRequest %%================================ 'enc_AbandonRequest'(Val) -> 'enc_AbandonRequest'(Val, [<<80>>]). 'enc_AbandonRequest'(Val, TagIn) -> encode_integer(Val, TagIn). 'dec_AbandonRequest'(Tlv) -> 'dec_AbandonRequest'(Tlv, [65552]). 'dec_AbandonRequest'(Tlv, TagIn) -> decode_integer(Tlv,{0,2147483647},TagIn). %%================================ %% ExtendedRequest %%================================ 'enc_ExtendedRequest'(Val) -> 'enc_ExtendedRequest'(Val, [<<119>>]). 'enc_ExtendedRequest'(Val, TagIn) -> {_,Cindex1, Cindex2} = Val, %%------------------------------------------------- %% attribute requestName(1) with type OCTET STRING %%------------------------------------------------- {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]), %%------------------------------------------------- %% attribute requestValue(2) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes2,EncLen2} = case Cindex2 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex2, [<<129>>]) end, BytesSoFar = [EncBytes1, EncBytes2], LenSoFar = EncLen1 + EncLen2, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_ExtendedRequest'(Tlv) -> 'dec_ExtendedRequest'(Tlv, [65559]). 'dec_ExtendedRequest'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute requestName(1) with type OCTET STRING %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_restricted_string(V1,[131072]), %%------------------------------------------------- %% attribute requestValue(2) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term2,Tlv3} = case Tlv2 of [{131073,V2}|TempTlv3] -> {decode_restricted_string(V2,[]), TempTlv3}; _ -> { asn1_NOVALUE, Tlv2} end, case Tlv3 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed end, {'ExtendedRequest', Term1, Term2}. %%================================ %% ExtendedResponse %%================================ 'enc_ExtendedResponse'(Val) -> 'enc_ExtendedResponse'(Val, [<<120>>]). 'enc_ExtendedResponse'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3, Cindex4, Cindex5, Cindex6} = Val, %%------------------------------------------------- %% attribute resultCode(1) with type ENUMERATED %%------------------------------------------------- {EncBytes1,EncLen1} = case Cindex1 of success -> encode_enumerated(0, [<<10>>]); operationsError -> encode_enumerated(1, [<<10>>]); protocolError -> encode_enumerated(2, [<<10>>]); timeLimitExceeded -> encode_enumerated(3, [<<10>>]); sizeLimitExceeded -> encode_enumerated(4, [<<10>>]); compareFalse -> encode_enumerated(5, [<<10>>]); compareTrue -> encode_enumerated(6, [<<10>>]); authMethodNotSupported -> encode_enumerated(7, [<<10>>]); strongAuthRequired -> encode_enumerated(8, [<<10>>]); referral -> encode_enumerated(10, [<<10>>]); adminLimitExceeded -> encode_enumerated(11, [<<10>>]); unavailableCriticalExtension -> encode_enumerated(12, [<<10>>]); confidentialityRequired -> encode_enumerated(13, [<<10>>]); saslBindInProgress -> encode_enumerated(14, [<<10>>]); noSuchAttribute -> encode_enumerated(16, [<<10>>]); undefinedAttributeType -> encode_enumerated(17, [<<10>>]); inappropriateMatching -> encode_enumerated(18, [<<10>>]); constraintViolation -> encode_enumerated(19, [<<10>>]); attributeOrValueExists -> encode_enumerated(20, [<<10>>]); invalidAttributeSyntax -> encode_enumerated(21, [<<10>>]); noSuchObject -> encode_enumerated(32, [<<10>>]); aliasProblem -> encode_enumerated(33, [<<10>>]); invalidDNSyntax -> encode_enumerated(34, [<<10>>]); aliasDereferencingProblem -> encode_enumerated(36, [<<10>>]); inappropriateAuthentication -> encode_enumerated(48, [<<10>>]); invalidCredentials -> encode_enumerated(49, [<<10>>]); insufficientAccessRights -> encode_enumerated(50, [<<10>>]); busy -> encode_enumerated(51, [<<10>>]); unavailable -> encode_enumerated(52, [<<10>>]); unwillingToPerform -> encode_enumerated(53, [<<10>>]); loopDetect -> encode_enumerated(54, [<<10>>]); namingViolation -> encode_enumerated(64, [<<10>>]); objectClassViolation -> encode_enumerated(65, [<<10>>]); notAllowedOnNonLeaf -> encode_enumerated(66, [<<10>>]); notAllowedOnRDN -> encode_enumerated(67, [<<10>>]); entryAlreadyExists -> encode_enumerated(68, [<<10>>]); objectClassModsProhibited -> encode_enumerated(69, [<<10>>]); affectsMultipleDSAs -> encode_enumerated(71, [<<10>>]); other -> encode_enumerated(80, [<<10>>]); Enumval1 -> exit({error,{asn1, {enumerated_not_in_range,Enumval1}}}) end, %%------------------------------------------------- %% attribute matchedDN(2) with type OCTET STRING %%------------------------------------------------- {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<4>>]), %%------------------------------------------------- %% attribute errorMessage(3) with type OCTET STRING %%------------------------------------------------- {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<4>>]), %%------------------------------------------------- %% attribute referral(4) External ELDAPv3:Referral OPTIONAL %%------------------------------------------------- {EncBytes4,EncLen4} = case Cindex4 of asn1_NOVALUE -> {<<>>,0}; _ -> 'enc_Referral'(Cindex4, [<<163>>]) end, %%------------------------------------------------- %% attribute responseName(5) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes5,EncLen5} = case Cindex5 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex5, [<<138>>]) end, %%------------------------------------------------- %% attribute response(6) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes6,EncLen6} = case Cindex6 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex6, [<<139>>]) end, BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5, EncBytes6], LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5 + EncLen6, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_ExtendedResponse'(Tlv) -> 'dec_ExtendedResponse'(Tlv, [65560]). 'dec_ExtendedResponse'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute resultCode(1) with type ENUMERATED %%------------------------------------------------- [V1|Tlv2] = Tlv1, Term1 = decode_enumerated(V1,[{success,0},{operationsError,1},{protocolError,2},{timeLimitExceeded,3},{sizeLimitExceeded,4},{compareFalse,5},{compareTrue,6},{authMethodNotSupported,7},{strongAuthRequired,8},{referral,10},{adminLimitExceeded,11},{unavailableCriticalExtension,12},{confidentialityRequired,13},{saslBindInProgress,14},{noSuchAttribute,16},{undefinedAttributeType,17},{inappropriateMatching,18},{constraintViolation,19},{attributeOrValueExists,20},{invalidAttributeSyntax,21},{noSuchObject,32},{aliasProblem,33},{invalidDNSyntax,34},{aliasDereferencingProblem,36},{inappropriateAuthentication,48},{invalidCredentials,49},{insufficientAccessRights,50},{busy,51},{unavailable,52},{unwillingToPerform,53},{loopDetect,54},{namingViolation,64},{objectClassViolation,65},{notAllowedOnNonLeaf,66},{notAllowedOnRDN,67},{entryAlreadyExists,68},{objectClassModsProhibited,69},{affectsMultipleDSAs,71},{other,80}],[10]), %%------------------------------------------------- %% attribute matchedDN(2) with type OCTET STRING %%------------------------------------------------- [V2|Tlv3] = Tlv2, Term2 = decode_restricted_string(V2,[4]), %%------------------------------------------------- %% attribute errorMessage(3) with type OCTET STRING %%------------------------------------------------- [V3|Tlv4] = Tlv3, Term3 = decode_restricted_string(V3,[4]), %%------------------------------------------------- %% attribute referral(4) External ELDAPv3:Referral OPTIONAL %%------------------------------------------------- {Term4,Tlv5} = case Tlv4 of [{131075,V4}|TempTlv5] -> {'dec_Referral'(V4, []), TempTlv5}; _ -> { asn1_NOVALUE, Tlv4} end, %%------------------------------------------------- %% attribute responseName(5) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term5,Tlv6} = case Tlv5 of [{131082,V5}|TempTlv6] -> {decode_restricted_string(V5,[]), TempTlv6}; _ -> { asn1_NOVALUE, Tlv5} end, %%------------------------------------------------- %% attribute response(6) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term6,Tlv7} = case Tlv6 of [{131083,V6}|TempTlv7] -> {decode_restricted_string(V6,[]), TempTlv7}; _ -> { asn1_NOVALUE, Tlv6} end, case Tlv7 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv7}}}) % extra fields not allowed end, {'ExtendedResponse', Term1, Term2, Term3, Term4, Term5, Term6}. %%================================ %% PasswdModifyRequestValue %%================================ 'enc_PasswdModifyRequestValue'(Val) -> 'enc_PasswdModifyRequestValue'(Val, [<<48>>]). 'enc_PasswdModifyRequestValue'(Val, TagIn) -> {_,Cindex1, Cindex2, Cindex3} = Val, %%------------------------------------------------- %% attribute userIdentity(1) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes1,EncLen1} = case Cindex1 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex1, [<<128>>]) end, %%------------------------------------------------- %% attribute oldPasswd(2) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes2,EncLen2} = case Cindex2 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex2, [<<129>>]) end, %%------------------------------------------------- %% attribute newPasswd(3) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes3,EncLen3} = case Cindex3 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex3, [<<130>>]) end, BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], LenSoFar = EncLen1 + EncLen2 + EncLen3, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_PasswdModifyRequestValue'(Tlv) -> 'dec_PasswdModifyRequestValue'(Tlv, [16]). 'dec_PasswdModifyRequestValue'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute userIdentity(1) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term1,Tlv2} = case Tlv1 of [{131072,V1}|TempTlv2] -> {decode_restricted_string(V1,[]), TempTlv2}; _ -> { asn1_NOVALUE, Tlv1} end, %%------------------------------------------------- %% attribute oldPasswd(2) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term2,Tlv3} = case Tlv2 of [{131073,V2}|TempTlv3] -> {decode_restricted_string(V2,[]), TempTlv3}; _ -> { asn1_NOVALUE, Tlv2} end, %%------------------------------------------------- %% attribute newPasswd(3) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term3,Tlv4} = case Tlv3 of [{131074,V3}|TempTlv4] -> {decode_restricted_string(V3,[]), TempTlv4}; _ -> { asn1_NOVALUE, Tlv3} end, case Tlv4 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed end, {'PasswdModifyRequestValue', Term1, Term2, Term3}. %%================================ %% PasswdModifyResponseValue %%================================ 'enc_PasswdModifyResponseValue'(Val) -> 'enc_PasswdModifyResponseValue'(Val, [<<48>>]). 'enc_PasswdModifyResponseValue'(Val, TagIn) -> {_,Cindex1} = Val, %%------------------------------------------------- %% attribute genPasswd(1) with type OCTET STRING OPTIONAL %%------------------------------------------------- {EncBytes1,EncLen1} = case Cindex1 of asn1_NOVALUE -> {<<>>,0}; _ -> encode_restricted_string(Cindex1, [<<128>>]) end, BytesSoFar = [EncBytes1], LenSoFar = EncLen1, encode_tags(TagIn, BytesSoFar, LenSoFar). 'dec_PasswdModifyResponseValue'(Tlv) -> 'dec_PasswdModifyResponseValue'(Tlv, [16]). 'dec_PasswdModifyResponseValue'(Tlv, TagIn) -> %%------------------------------------------------- %% decode tag and length %%------------------------------------------------- Tlv1 = match_tags(Tlv, TagIn), %%------------------------------------------------- %% attribute genPasswd(1) with type OCTET STRING OPTIONAL %%------------------------------------------------- {Term1,Tlv2} = case Tlv1 of [{131072,V1}|TempTlv2] -> {decode_restricted_string(V1,[]), TempTlv2}; _ -> { asn1_NOVALUE, Tlv1} end, case Tlv2 of [] -> true;_ -> exit({error,{asn1, {unexpected,Tlv2}}}) % extra fields not allowed end, {'PasswdModifyResponseValue', Term1}. 'maxInt'() -> 2147483647. 'passwdModifyOID'() -> [49,46,51,46,54,46,49,46,52,46,49,46,52,50,48,51,46,49,46,49,49,46,49]. %%% %%% Run-time functions. %%% ber_decode_nif(B) -> asn1rt_nif:decode_ber_tlv(B). collect_parts(TlvList) -> collect_parts(TlvList, []). collect_parts([{_,L}|Rest], Acc) when is_list(L) -> collect_parts(Rest, [collect_parts(L)|Acc]); collect_parts([{3,<>}|Rest], _Acc) -> collect_parts_bit(Rest, [Bits], Unused); collect_parts([{_T,V}|Rest], Acc) -> collect_parts(Rest, [V|Acc]); collect_parts([], Acc) -> list_to_binary(lists:reverse(Acc)). collect_parts_bit([{3,<>}|Rest], Acc, Uacc) -> collect_parts_bit(Rest, [Bits|Acc], Unused + Uacc); collect_parts_bit([], Acc, Uacc) -> list_to_binary([Uacc|lists:reverse(Acc)]). decode_boolean(Tlv, TagIn) -> Val = match_tags(Tlv, TagIn), case Val of <<0:8>> -> false; <<_:8>> -> true; _ -> exit({error,{asn1,{decode_boolean,Val}}}) end. decode_enumerated(Tlv, NamedNumberList, Tags) -> Buffer = match_tags(Tlv, Tags), decode_enumerated_notag(Buffer, NamedNumberList, Tags). decode_enumerated1(Val, NamedNumberList) -> case lists:keyfind(Val, 2, NamedNumberList) of {NamedVal,_} -> NamedVal; _ -> {asn1_enum,Val} end. decode_enumerated_notag(Buffer, {NamedNumberList,ExtList}, _Tags) -> IVal = decode_integer(Buffer), case decode_enumerated1(IVal, NamedNumberList) of {asn1_enum,IVal} -> decode_enumerated1(IVal, ExtList); EVal -> EVal end; decode_enumerated_notag(Buffer, NNList, _Tags) -> IVal = decode_integer(Buffer), case decode_enumerated1(IVal, NNList) of {asn1_enum,_} -> exit({error,{asn1,{illegal_enumerated,IVal}}}); EVal -> EVal end. decode_integer(Bin) -> Len = byte_size(Bin), <> = Bin, Int. decode_integer(Tlv, Range, TagIn) -> V = match_tags(Tlv, TagIn), Int = decode_integer(V), range_check_integer(Int, Range). decode_null(Tlv, Tags) -> Val = match_tags(Tlv, Tags), case Val of <<>> -> 'NULL'; _ -> exit({error,{asn1,{decode_null,Val}}}) end. decode_restricted_string(Tlv, TagsIn) -> Bin = match_and_collect(Tlv, TagsIn), Bin. encode_boolean(true, TagIn) -> encode_tags(TagIn, [255], 1); encode_boolean(false, TagIn) -> encode_tags(TagIn, [0], 1); encode_boolean(X, _) -> exit({error,{asn1,{encode_boolean,X}}}). encode_enumerated(Val, TagIn) when is_integer(Val) -> encode_tags(TagIn, encode_integer(Val)). encode_integer(Val) -> Bytes = if Val >= 0 -> encode_integer_pos(Val, []); true -> encode_integer_neg(Val, []) end, {Bytes,length(Bytes)}. encode_integer(Val, Tag) when is_integer(Val) -> encode_tags(Tag, encode_integer(Val)); encode_integer(Val, _Tag) -> exit({error,{asn1,{encode_integer,Val}}}). encode_integer_neg(- 1, [B1|_T] = L) when B1 > 127 -> L; encode_integer_neg(N, Acc) -> encode_integer_neg(N bsr 8, [N band 255|Acc]). encode_integer_pos(0, [B|_Acc] = L) when B < 128 -> L; encode_integer_pos(N, Acc) -> encode_integer_pos(N bsr 8, [N band 255|Acc]). encode_length(L) when L =< 127 -> {[L],1}; encode_length(L) -> Oct = minimum_octets(L), Len = length(Oct), if Len =< 126 -> {[128 bor Len|Oct],Len + 1}; true -> exit({error,{asn1,too_long_length_oct,Len}}) end. encode_null(_Val, TagIn) -> encode_tags(TagIn, [], 0). encode_restricted_string(OctetList, TagIn) when is_binary(OctetList) -> encode_tags(TagIn, OctetList, byte_size(OctetList)); encode_restricted_string(OctetList, TagIn) when is_list(OctetList) -> encode_tags(TagIn, OctetList, length(OctetList)). encode_tags(TagIn, {BytesSoFar,LenSoFar}) -> encode_tags(TagIn, BytesSoFar, LenSoFar). encode_tags([Tag|Trest], BytesSoFar, LenSoFar) -> {Bytes2,L2} = encode_length(LenSoFar), encode_tags(Trest, [Tag,Bytes2|BytesSoFar], LenSoFar + byte_size(Tag) + L2); encode_tags([], BytesSoFar, LenSoFar) -> {BytesSoFar,LenSoFar}. match_and_collect(Tlv, TagsIn) -> Val = match_tags(Tlv, TagsIn), case Val of [_|_] = PartList -> collect_parts(PartList); Bin when is_binary(Bin) -> Bin end. match_tags({T,V}, [T]) -> V; match_tags({T,V}, [T|Tt]) -> match_tags(V, Tt); match_tags([{T,V}], [T|Tt]) -> match_tags(V, Tt); match_tags([{T,_V}|_] = Vlist, [T]) -> Vlist; match_tags(Tlv, []) -> Tlv; match_tags({Tag,_V} = Tlv, [T|_Tt]) -> exit({error,{asn1,{wrong_tag,{{expected,T},{got,Tag,Tlv}}}}}). minimum_octets(0, Acc) -> Acc; minimum_octets(Val, Acc) -> minimum_octets(Val bsr 8, [Val band 255|Acc]). minimum_octets(Val) -> minimum_octets(Val, []). range_check_integer(Int, Range) -> case Range of [] -> Int; {Lb,Ub} when Int >= Lb, Ub >= Int -> Int; {_,_} -> exit({error,{asn1,{integer_range,Range,Int}}}); Int -> Int; SingleValue when is_integer(SingleValue) -> exit({error,{asn1,{integer_range,Range,Int}}}); _ -> Int end. ejabberd-16.01/src/extauth.erl0000644000232200023220000001170312645157216016615 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : extauth.erl %%% Author : Leif Johansson %%% Purpose : External authentication using a simple port-driver %%% Created : 30 Jul 2004 by Leif Johansson %%% %%% %%% 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(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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -define(INIT_TIMEOUT, 60000). -define(CALL_TIMEOUT, 10000). start(Host, ExtPrg) -> lists:foreach(fun (This) -> start_instance(get_process_name(Host, This), ExtPrg) end, lists:seq(0, get_instances(Host) - 1)). start_instance(ProcessName, ExtPrg) -> spawn(?MODULE, init, [ProcessName, ExtPrg]). restart_instance(ProcessName, ExtPrg) -> unregister(ProcessName), start_instance(ProcessName, ExtPrg). init(ProcessName, ExtPrg) -> register(ProcessName, self()), process_flag(trap_exit, true), Port = open_port({spawn, ExtPrg}, [{packet, 2}]), loop(Port, ?INIT_TIMEOUT, ProcessName, ExtPrg). stop(Host) -> lists:foreach(fun (This) -> get_process_name(Host, This) ! stop end, lists:seq(0, get_instances(Host) - 1)). get_process_name(Host, Integer) -> gen_mod:get_module_proc(iolist_to_binary([Host, integer_to_list(Integer)]), eauth). check_password(User, Server, Password) -> call_port(Server, [<<"auth">>, User, Server, Password]). is_user_exists(User, Server) -> call_port(Server, [<<"isuser">>, User, Server]). set_password(User, Server, Password) -> call_port(Server, [<<"setpass">>, User, Server, Password]). try_register(User, Server, Password) -> case call_port(Server, [<<"tryregister">>, User, Server, Password]) of true -> {atomic, ok}; false -> {error, not_allowed} end. remove_user(User, Server) -> call_port(Server, [<<"removeuser">>, User, Server]). remove_user(User, Server, Password) -> call_port(Server, [<<"removeuser3">>, User, Server, Password]). call_port(Server, Msg) -> LServer = jid:nameprep(Server), ProcessName = get_process_name(LServer, random_instance(get_instances(LServer))), ProcessName ! {call, self(), Msg}, receive {eauth, Result} -> Result end. random_instance(MaxNum) -> random:seed(p1_time_compat:timestamp()), random:uniform(MaxNum) - 1. get_instances(Server) -> ejabberd_config:get_option( {extauth_instances, Server}, fun(V) when is_integer(V), V > 0 -> V end, 1). loop(Port, Timeout, ProcessName, ExtPrg) -> receive {call, Caller, Msg} -> port_command(Port, encode(Msg)), receive {Port, {data, Data}} -> ?DEBUG("extauth call '~p' received data response:~n~p", [Msg, Data]), Caller ! {eauth, decode(Data)}, loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg); {Port, Other} -> ?ERROR_MSG("extauth call '~p' received strange response:~n~p", [Msg, Other]), Caller ! {eauth, false}, loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg) after Timeout -> ?ERROR_MSG("extauth call '~p' didn't receive response", [Msg]), Caller ! {eauth, false}, Pid = restart_instance(ProcessName, ExtPrg), flush_buffer_and_forward_messages(Pid), exit(port_terminated) end; stop -> Port ! {self(), close}, receive {Port, closed} -> exit(normal) end; {'EXIT', Port, Reason} -> ?CRITICAL_MSG("extauth script has exitted abruptly " "with reason '~p'", [Reason]), Pid = restart_instance(ProcessName, ExtPrg), flush_buffer_and_forward_messages(Pid), exit(port_terminated) end. flush_buffer_and_forward_messages(Pid) -> receive Message -> Pid ! Message, flush_buffer_and_forward_messages(Pid) after 0 -> true end. 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]. ejabberd-16.01/src/acl.erl0000644000232200023220000004054512645157216015700 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : acl.erl %%% Author : Alexey Shchepin %%% Purpose : ACL support %%% Created : 18 Jan 2003 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(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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -record(acl, {aclname, aclspec}). -record(access, {name :: aclname(), rules = [] :: [access_rule()]}). -type regexp() :: binary(). -type glob() :: binary(). -type access_name() :: atom(). -type access_rule() :: {atom(), any()}. -type host() :: binary(). -type aclname() :: {atom(), binary() | global}. -type aclspec() :: all | none | {user, {binary(), host()} | binary()} | {server, binary()} | {resource, binary()} | {user_regexp, {regexp(), host()} | regexp()} | {shared_group, {binary(), host()} | binary()} | {user_regexp, {regexp(), host()} | regexp()} | {server_regexp, regexp()} | {resource_regexp, regexp()} | {node_regexp, {regexp(), regexp()}} | {user_glob, {glob(), host()} | glob()} | {server_glob, glob()} | {resource_glob, glob()} | {ip, {inet:ip_address(), integer()}} | {node_glob, {glob(), glob()}}. -type acl() :: #acl{aclname :: aclname(), aclspec :: aclspec()}. -export_type([acl/0]). start() -> case catch mnesia:table_info(acl, storage_type) of disc_copies -> mnesia:delete_table(acl); _ -> ok end, mnesia:create_table(acl, [{ram_copies, [node()]}, {type, bag}, {local_content, true}, {attributes, record_info(fields, acl)}]), mnesia:create_table(access, [{ram_copies, [node()]}, {local_content, true}, {attributes, record_info(fields, access)}]), mnesia:add_table_copy(acl, node(), ram_copies), mnesia:add_table_copy(access, node(), ram_copies), load_from_config(), ok. -spec to_record(binary(), atom(), aclspec()) -> acl(). to_record(Host, ACLName, ACLSpec) -> #acl{aclname = {ACLName, Host}, aclspec = normalize_spec(ACLSpec)}. -spec add(binary(), aclname(), aclspec()) -> ok | {error, any()}. add(Host, ACLName, ACLSpec) -> {ResL, BadNodes} = ejabberd_cluster:multicall( ?MODULE, add_local, [Host, ACLName, ACLSpec]), case lists:keyfind(aborted, 1, ResL) of false when BadNodes == [] -> ok; false -> {error, {failed_nodes, BadNodes}}; Err -> {error, Err} end. add_local(Host, ACLName, ACLSpec) -> F = fun () -> mnesia:write(#acl{aclname = {ACLName, Host}, aclspec = normalize_spec(ACLSpec)}) end, case mnesia:transaction(F) of {atomic, ok} -> ok; Err -> Err end. -spec add_list(binary(), [acl()], boolean()) -> ok | {error, any()}. add_list(Host, ACLs, Clear) -> {ResL, BadNodes} = ejabberd_cluster:multicall( ?MODULE, add_list_local, [Host, ACLs, Clear]), case lists:keyfind(aborted, 1, ResL) of false when BadNodes == [] -> ok; false -> {error, {failed_nodes, BadNodes}}; Err -> {error, Err} end. add_list_local(Host, ACLs, Clear) -> F = fun () -> if Clear -> Ks = mnesia:select(acl, [{{acl, {'$1', Host}, '$2'}, [], ['$1']}]), lists:foreach(fun (K) -> mnesia:delete({acl, {K, Host}}) end, Ks); true -> ok end, lists:foreach(fun (ACL) -> case ACL of #acl{aclname = ACLName, aclspec = ACLSpec} -> mnesia:write(#acl{aclname = {ACLName, Host}, aclspec = normalize_spec(ACLSpec)}) end end, ACLs) end, mnesia:transaction(F). -spec add_access(binary() | global, access_name(), [access_rule()]) -> ok | {error, any()}. add_access(Host, Access, Rules) -> 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. load_from_config() -> Hosts = [global|?MYHOSTS], lists:foreach( fun(Host) -> ACLs = ejabberd_config:get_option( {acl, Host}, fun(V) -> V end, []), AccessRules = ejabberd_config:get_option( {access, Host}, fun(V) -> V end, []), lists:foreach( fun({ACLName, SpecList}) -> lists:foreach( fun({ACLType, ACLSpecs}) when is_list(ACLSpecs) -> lists:foreach( fun(ACLSpec) -> add(Host, ACLName, {ACLType, ACLSpec}) end, lists:flatten(ACLSpecs)); ({ACLType, ACLSpecs}) -> add(Host, ACLName, {ACLType, ACLSpecs}) end, lists:flatten(SpecList)) end, ACLs), lists:foreach( fun({Access, Rules}) -> add_access(Host, Access, Rules) end, AccessRules) end, Hosts). b(S) -> iolist_to_binary(S). nodeprep(S) -> jid:nodeprep(b(S)). nameprep(S) -> jid:nameprep(b(S)). resourceprep(S) -> jid:resourceprep(b(S)). normalize_spec(Spec) -> case Spec of all -> all; none -> none; {user, {U, S}} -> {user, {nodeprep(U), nameprep(S)}}; {user, U} -> {user, nodeprep(U)}; {shared_group, {G, H}} -> {shared_group, {b(G), nameprep(H)}}; {shared_group, G} -> {shared_group, b(G)}; {user_regexp, {UR, S}} -> {user_regexp, {b(UR), nameprep(S)}}; {user_regexp, UR} -> {user_regexp, b(UR)}; {node_regexp, {UR, SR}} -> {node_regexp, {b(UR), b(SR)}}; {user_glob, {UR, S}} -> {user_glob, {b(UR), nameprep(S)}}; {user_glob, UR} -> {user_glob, b(UR)}; {node_glob, {UR, SR}} -> {node_glob, {b(UR), b(SR)}}; {server, S} -> {server, nameprep(S)}; {resource, R} -> {resource, resourceprep(R)}; {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, S} -> case parse_ip_netmask(b(S)) of {ok, Net, Mask} -> {ip, {Net, Mask}}; error -> ?INFO_MSG("Invalid network address: ~p", [S]), none end end. -spec match_rule(global | binary(), access_name(), jid() | ljid() | inet:ip_address()) -> any(). match_rule(_Host, all, _JID) -> allow; match_rule(_Host, none, _JID) -> deny; match_rule(Host, Access, JID) -> GAccess = ets:lookup(access, {Access, global}), LAccess = if Host /= global -> ets:lookup(access, {Access, Host}); true -> [] end, case GAccess ++ LAccess of [] -> deny; AccessList -> Rules = lists:flatmap( fun(#access{rules = Rs}) -> Rs end, AccessList), match_acls(Rules, JID, Host) end. match_acls([], _, _Host) -> deny; match_acls([{ACL, Access} | ACLs], JID, Host) -> case match_acl(ACL, JID, Host) of true -> Access; _ -> match_acls(ACLs, JID, Host) end. -spec match_acl(atom(), jid() | ljid() | inet:ip_address(), binary()) -> boolean(). match_acl(all, _JID, _Host) -> true; match_acl(none, _JID, _Host) -> false; match_acl(ACL, IP, Host) when tuple_size(IP) == 4; tuple_size(IP) == 8 -> lists:any( fun(#acl{aclspec = {ip, {Net, Mask}}}) -> is_ip_match(IP, Net, Mask); (_) -> false end, get_aclspecs(ACL, Host)); match_acl(ACL, JID, Host) -> {User, Server, Resource} = jid:tolower(JID), lists:any( fun(#acl{aclspec = Spec}) -> case Spec of all -> true; {user, {U, S}} -> U == User andalso S == Server; {user, U} -> U == User andalso lists:member(Server, ?MYHOSTS); {server, S} -> S == Server; {resource, R} -> R == Resource; {shared_group, {G, H}} -> Mod = loaded_shared_roster_module(H), Mod:is_user_in_group({User, Server}, G, H); {shared_group, G} -> Mod = loaded_shared_roster_module(Host), Mod:is_user_in_group({User, Server}, G, Host); {user_regexp, {UR, S}} -> S == Server andalso is_regexp_match(User, UR); {user_regexp, UR} -> lists:member(Server, ?MYHOSTS) andalso is_regexp_match(User, UR); {server_regexp, SR} -> is_regexp_match(Server, SR); {resource_regexp, RR} -> is_regexp_match(Resource, RR); {node_regexp, {UR, SR}} -> is_regexp_match(Server, SR) andalso is_regexp_match(User, UR); {user_glob, {UR, S}} -> S == Server andalso is_glob_match(User, UR); {user_glob, UR} -> lists:member(Server, ?MYHOSTS) andalso is_glob_match(User, UR); {server_glob, SR} -> is_glob_match(Server, SR); {resource_glob, RR} -> is_glob_match(Resource, RR); {node_glob, {UR, SR}} -> is_glob_match(Server, SR) andalso is_glob_match(User, UR); WrongSpec -> ?ERROR_MSG("Wrong ACL expression: ~p~nCheck your " "config file and reload it with the override_a" "cls option enabled", [WrongSpec]), false end end, get_aclspecs(ACL, Host)). get_aclspecs(ACL, Host) -> ets:lookup(acl, {ACL, Host}) ++ ets:lookup(acl, {ACL, global}). is_regexp_match(String, RegExp) -> case ejabberd_regexp:run(String, RegExp) of nomatch -> false; match -> true; {error, ErrDesc} -> ?ERROR_MSG("Wrong regexp ~p in ACL: ~p", [RegExp, ErrDesc]), false end. is_glob_match(String, Glob) -> is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)). is_ip_match({_, _, _, _} = IP, {_, _, _, _} = Net, Mask) -> IPInt = ip_to_integer(IP), NetInt = ip_to_integer(Net), M = bnot (1 bsl (32 - Mask) - 1), IPInt band M =:= NetInt band M; is_ip_match({_, _, _, _, _, _, _, _} = IP, {_, _, _, _, _, _, _, _} = Net, Mask) -> IPInt = ip_to_integer(IP), NetInt = ip_to_integer(Net), M = bnot (1 bsl (128 - Mask) - 1), IPInt band M =:= NetInt band M; is_ip_match(_, _, _) -> false. ip_to_integer({IP1, IP2, IP3, IP4}) -> IP1 bsl 8 bor IP2 bsl 8 bor IP3 bsl 8 bor IP4; ip_to_integer({IP1, IP2, IP3, IP4, IP5, IP6, IP7, IP8}) -> IP1 bsl 16 bor IP2 bsl 16 bor IP3 bsl 16 bor IP4 bsl 16 bor IP5 bsl 16 bor IP6 bsl 16 bor IP7 bsl 16 bor IP8. loaded_shared_roster_module(Host) -> case gen_mod:is_loaded(Host, mod_shared_roster_ldap) of true -> mod_shared_roster_ldap; false -> mod_shared_roster end. parse_ip_netmask(S) -> case str:tokens(S, <<"/">>) of [IPStr] -> case inet_parse:address(binary_to_list(IPStr)) of {ok, {_, _, _, _} = IP} -> {ok, IP, 32}; {ok, {_, _, _, _, _, _, _, _} = IP} -> {ok, IP, 128}; _ -> error end; [IPStr, MaskStr] -> case catch jlib:binary_to_integer(MaskStr) of Mask when is_integer(Mask), Mask >= 0 -> case inet_parse:address(binary_to_list(IPStr)) of {ok, {_, _, _, _} = IP} when Mask =< 32 -> {ok, IP, Mask}; {ok, {_, _, _, _, _, _, _, _} = IP} when Mask =< 128 -> {ok, IP, Mask}; _ -> error end; _ -> error end; _ -> error end. transform_options(Opts) -> Opts1 = lists:foldl(fun transform_options/2, [], Opts), {ACLOpts, Opts2} = lists:mapfoldl( fun({acl, Os}, Acc) -> {Os, Acc}; (O, Acc) -> {[], [O|Acc]} end, [], Opts1), {AccessOpts, Opts3} = lists:mapfoldl( fun({access, Os}, Acc) -> {Os, Acc}; (O, Acc) -> {[], [O|Acc]} end, [], Opts2), ACLOpts1 = ejabberd_config:collect_options(lists:flatten(ACLOpts)), AccessOpts1 = case ejabberd_config:collect_options( lists:flatten(AccessOpts)) of [] -> []; L1 -> [{access, L1}] end, ACLOpts2 = case lists:map( fun({ACLName, Os}) -> {ACLName, ejabberd_config:collect_options(Os)} end, ACLOpts1) of [] -> []; L2 -> [{acl, L2}] end, ACLOpts2 ++ AccessOpts1 ++ Opts3. transform_options({acl, Name, Type}, Opts) -> T = case Type of all -> all; none -> none; {user, U} -> {user, [b(U)]}; {user, U, S} -> {user, [[{b(U), b(S)}]]}; {shared_group, G} -> {shared_group, [b(G)]}; {shared_group, G, H} -> {shared_group, [[{b(G), b(H)}]]}; {user_regexp, UR} -> {user_regexp, [b(UR)]}; {user_regexp, UR, S} -> {user_regexp, [[{b(UR), b(S)}]]}; {node_regexp, UR, SR} -> {node_regexp, [[{b(UR), b(SR)}]]}; {user_glob, UR} -> {user_glob, [b(UR)]}; {user_glob, UR, S} -> {user_glob, [[{b(UR), b(S)}]]}; {node_glob, UR, SR} -> {node_glob, [[{b(UR), b(SR)}]]}; {server, S} -> {server, [b(S)]}; {resource, R} -> {resource, [b(R)]}; {server_regexp, SR} -> {server_regexp, [b(SR)]}; {server_glob, S} -> {server_glob, [b(S)]}; {ip, S} -> {ip, [b(S)]}; {resource_glob, R} -> {resource_glob, [b(R)]} end, [{acl, [{Name, [T]}]}|Opts]; transform_options({access, Name, Rules}, Opts) -> NewRules = [{ACL, Action} || {Action, ACL} <- Rules], [{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]. ejabberd-16.01/src/nodetree_virtual.erl0000644000232200023220000000763512645157216020517 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : nodetree_virtual.erl %%% Author : Christophe Romain %%% Purpose : Standard node tree plugin using no storage backend %%% Created : 1 Dec 2007 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. %%% %%%---------------------------------------------------------------------- %%% @doc The module {@module} is the PubSub node tree plugin that %%% 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"). -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]). 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) -> Nidx = nodeidx(Host, Node), node_record(Host, Node, Nidx). get_node(Nidx) -> {Host, Node} = nodeid(Nidx), node_record(Host, Node, Nidx). get_nodes(Host, _From) -> get_nodes(Host). get_nodes(_Host) -> []. get_parentnodes(_Host, _Node, _From) -> []. get_parentnodes_tree(Host, Node, From) -> [{0, [get_node(Host, Node, From)]}]. get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). get_subnodes(_Host, _Node) -> []. get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node). get_subnodes_tree(_Host, _Node) -> []. create_node(Host, Node, _Type, _Owner, _Options, _Parents) -> {error, {virtual, nodeidx(Host, Node)}}. delete_node(Host, Node) -> [get_node(Host, Node)]. %% internal helper 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. ejabberd-16.01/src/mod_adhoc.erl0000644000232200023220000002270212645157216017051 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_adhoc.erl %%% Author : Magnus Henoch %%% Purpose : Handle incoming ad-doc requests (XEP-0050) %%% Created : 15 Nov 2005 by Magnus Henoch %%% %%% %%% 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_adhoc). -author('henoch@dtek.chalmers.se'). -protocol({xep, 50, '1.2'}). -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, 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, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("adhoc.hrl"). 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_COMMANDS, ?MODULE, process_local_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_COMMANDS, ?MODULE, process_sm_iq, IQDisc), ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, get_local_identity, 99), ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 99), ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_local_commands, 99), ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 99), ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 99), ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_commands, 99), ejabberd_hooks:add(adhoc_local_items, Host, ?MODULE, ping_item, 100), ejabberd_hooks:add(adhoc_local_commands, Host, ?MODULE, ping_command, 100). stop(Host) -> ejabberd_hooks:delete(adhoc_local_commands, Host, ?MODULE, ping_command, 100), ejabberd_hooks:delete(adhoc_local_items, Host, ?MODULE, ping_item, 100), ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_commands, 99), ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 99), ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 99), ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_local_commands, 99), ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 99), ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, get_local_identity, 99), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_COMMANDS), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_COMMANDS). %------------------------------------------------------------------------- get_local_commands(Acc, _From, #jid{server = Server, lserver = LServer} = _To, <<"">>, Lang) -> Display = gen_mod:get_module_opt(LServer, ?MODULE, report_commands_node, fun(B) when is_boolean(B) -> B end, false), case Display of false -> Acc; _ -> Items = case Acc of {result, I} -> I; _ -> [] end, Nodes = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, Server}, {<<"node">>, ?NS_COMMANDS}, {<<"name">>, translate:translate(Lang, <<"Commands">>)}], children = []}], {result, Items ++ Nodes} end; get_local_commands(_Acc, From, #jid{lserver = LServer} = To, ?NS_COMMANDS, Lang) -> ejabberd_hooks:run_fold(adhoc_local_items, LServer, {result, []}, [From, To, Lang]); get_local_commands(_Acc, _From, _To, <<"ping">>, _Lang) -> {result, []}; get_local_commands(Acc, _From, _To, _Node, _Lang) -> Acc. %------------------------------------------------------------------------- get_sm_commands(Acc, _From, #jid{lserver = LServer} = To, <<"">>, Lang) -> Display = gen_mod:get_module_opt(LServer, ?MODULE, report_commands_node, fun(B) when is_boolean(B) -> B end, false), case Display of false -> Acc; _ -> Items = case Acc of {result, I} -> I; _ -> [] end, Nodes = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string(To)}, {<<"node">>, ?NS_COMMANDS}, {<<"name">>, translate:translate(Lang, <<"Commands">>)}], children = []}], {result, Items ++ Nodes} end; get_sm_commands(_Acc, From, #jid{lserver = LServer} = To, ?NS_COMMANDS, Lang) -> ejabberd_hooks:run_fold(adhoc_sm_items, LServer, {result, []}, [From, To, Lang]); get_sm_commands(Acc, _From, _To, _Node, _Lang) -> Acc. %------------------------------------------------------------------------- %% On disco info request to the ad-hoc node, return automation/command-list. get_local_identity(Acc, _From, _To, ?NS_COMMANDS, Lang) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"automation">>}, {<<"type">>, <<"command-list">>}, {<<"name">>, translate:translate(Lang, <<"Commands">>)}], children = []} | Acc]; get_local_identity(Acc, _From, _To, <<"ping">>, Lang) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"automation">>}, {<<"type">>, <<"command-node">>}, {<<"name">>, translate:translate(Lang, <<"Ping">>)}], children = []} | Acc]; get_local_identity(Acc, _From, _To, _Node, _Lang) -> Acc. %------------------------------------------------------------------------- %% On disco info request to the ad-hoc node, return automation/command-list. get_sm_identity(Acc, _From, _To, ?NS_COMMANDS, Lang) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"automation">>}, {<<"type">>, <<"command-list">>}, {<<"name">>, translate:translate(Lang, <<"Commands">>)}], children = []} | Acc]; get_sm_identity(Acc, _From, _To, _Node, _Lang) -> Acc. %------------------------------------------------------------------------- get_local_features(Acc, _From, _To, <<"">>, _Lang) -> Feats = case Acc of {result, I} -> I; _ -> [] end, {result, Feats ++ [?NS_COMMANDS]}; get_local_features(_Acc, _From, _To, ?NS_COMMANDS, _Lang) -> {result, []}; get_local_features(_Acc, _From, _To, <<"ping">>, _Lang) -> {result, [?NS_COMMANDS]}; get_local_features(Acc, _From, _To, _Node, _Lang) -> Acc. %------------------------------------------------------------------------- get_sm_features(Acc, _From, _To, <<"">>, _Lang) -> Feats = case Acc of {result, I} -> I; _ -> [] end, {result, Feats ++ [?NS_COMMANDS]}; get_sm_features(_Acc, _From, _To, ?NS_COMMANDS, _Lang) -> {result, []}; get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. %------------------------------------------------------------------------- process_local_iq(From, To, IQ) -> process_adhoc_request(From, To, IQ, adhoc_local_commands). process_sm_iq(From, To, IQ) -> process_adhoc_request(From, To, IQ, adhoc_sm_commands). process_adhoc_request(From, To, #iq{sub_el = SubEl} = IQ, Hook) -> ?DEBUG("About to parse ~p...", [IQ]), case adhoc:parse_request(IQ) of {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]}; #adhoc_request{} = AdhocRequest -> Host = To#jid.lserver, case ejabberd_hooks:run_fold(Hook, Host, empty, [From, To, AdhocRequest]) of ignore -> ignore; empty -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]}; Command -> IQ#iq{type = result, sub_el = [Command]} end end. ping_item(Acc, _From, #jid{server = Server} = _To, Lang) -> Items = case Acc of {result, I} -> I; _ -> [] end, Nodes = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, Server}, {<<"node">>, <<"ping">>}, {<<"name">>, translate:translate(Lang, <<"Ping">>)}], children = []}], {result, Items ++ Nodes}. ping_command(_Acc, _From, _To, #adhoc_request{lang = Lang, node = <<"ping">>, sessionid = _Sessionid, action = Action} = Request) -> if Action == <<"">>; Action == <<"execute">> -> adhoc:produce_response(Request, #adhoc_response{status = completed, notes = [{<<"info">>, translate:translate(Lang, <<"Pong">>)}]}); 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]. ejabberd-16.01/src/nodetree_dag.erl0000644000232200023220000001677612645157216017572 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : nodetree_dag.erl %%% Author : Brian Cully %%% Purpose : experimental support of XEP-248 %%% Created : 15 Jun 2009 by Brian Cully %%% %%% %%% 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). -author('bjc@kublai.com'). -include_lib("stdlib/include/qlc.hrl"). -include("pubsub.hrl"). -include("jlib.hrl"). -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_PARENTS, []). -define(DEFAULT_CHILDREN, []). init(Host, ServerHost, Opts) -> nodetree_tree:init(Host, ServerHost, Opts). terminate(Host, ServerHost) -> nodetree_tree:terminate(Host, ServerHost). 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 end. create_node(Key, Node, Type, Owner, Options, Parents) -> OwnerJID = jid:tolower(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. 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. options() -> nodetree_tree:options(). 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. get_node(Node) -> nodetree_tree:get_node(Node). get_nodes(Key, From) -> nodetree_tree:get_nodes(Key, From). get_nodes(Key) -> nodetree_tree:get_nodes(Key). 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) 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, [Node]). get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). get_subnodes(Host, <<>>) -> get_subnodes_helper(Host, <<>>); get_subnodes(Host, Node) -> case find_node(Host, Node) of false -> {error, ?ERR_ITEM_NOT_FOUND}; _ -> get_subnodes_helper(Host, Node) end. 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, Node, From) -> Pred = fun (NID, #pubsub_node{parents = Parents}) -> lists:member(NID, Parents) end, Tr = fun (#pubsub_node{nodeid = {_, N}}) -> [N] end, traversal_helper(Pred, Tr, 1, Host, [Node], [{0, [get_node(Host, Node, From)]}]). %%==================================================================== %% Internal functions %%==================================================================== oid(Key, Name) -> {Key, Name}. %% Key = jlib:jid() | host() %% Node = string() -spec(find_node/2 :: ( Key :: mod_pubsub:hostPubsub(), Node :: mod_pubsub:nodeId()) -> mod_pubsub:pubsubNode() | false ). find_node(Key, Node) -> case mnesia:read(pubsub_node, oid(Key, Node), read) of [] -> false; [Node] -> Node end. %% Key = jlib:jid() | host() %% Default = term() %% Options = [{Key = atom(), Value = term()}] find_opt(Key, Default, Options) -> case lists:keysearch(Key, 1, Options) of {value, {Key, Val}} -> Val; _ -> Default end. -spec(traversal_helper/4 :: ( 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, 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]). remove_config_parent(Node, Options) -> remove_config_parent(Node, Options, []). remove_config_parent(_Node, [], Acc) -> lists:reverse(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_Nodes :: [mod_pubsub:nodeId()]) -> 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. ejabberd-16.01/src/pubsub_db_odbc.erl0000644000232200023220000001221712645157216020070 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : pubsub_db_odbc.erl %%% Author : Pablo Polvorin %%% Purpose : Provide helpers for PubSub ODBC backend %%% Created : 7 Aug 2009 by Pablo Polvorin %%% %%% %%% 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(pubsub_db_odbc). -author("pablo.polvorin@process-one.net"). -include("pubsub.hrl"). -export([add_subscription/1, read_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)}} end. %% -spec delete_subscription(SubID :: string()) -> ok. delete_subscription(SubID) -> %% -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), <<"'">>]), ok. update_subscription(#pubsub_subscription{subid = SubId} = Sub) -> delete_subscription(SubId), add_subscription(Sub). 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), 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}) -> {digest_frequency, odbc_to_integer(Value)}; subscription_opt_from_odbc({<<"EXPIRE">>, Value}) -> {expire, odbc_to_timestamp(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}) -> {show_values, 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}) -> {subscription_depth, case Value of <<"all">> -> all; N -> odbc_to_integer(N) end}. subscription_opt_to_odbc({deliver, Bool}) -> {<<"DELIVER">>, boolean_to_odbc(Bool)}; subscription_opt_to_odbc({digest, Bool}) -> {<<"DIGEST">>, boolean_to_odbc(Bool)}; subscription_opt_to_odbc({digest_frequency, Int}) -> {<<"DIGEST_FREQUENCY">>, integer_to_odbc(Int)}; subscription_opt_to_odbc({expire, Timestamp}) -> {<<"EXPIRE">>, timestamp_to_odbc(Timestamp)}; subscription_opt_to_odbc({include_body, Bool}) -> {<<"INCLUDE_BODY">>, boolean_to_odbc(Bool)}; 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}; subscription_opt_to_odbc({subscription_depth, Depth}) -> {<<"SUBSCRIPTION_DEPTH">>, case Depth of all -> <<"all">>; N -> integer_to_odbc(N) end}. integer_to_odbc(N) -> iolist_to_binary(integer_to_list(N)). boolean_to_odbc(true) -> <<"1">>; boolean_to_odbc(false) -> <<"0">>. timestamp_to_odbc(T) -> jlib:now_to_utc_string(T). 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). ejabberd-16.01/src/eldap_pool.erl0000644000232200023220000000547312645157216017260 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% File : eldap_pool.erl %%% Author : Evgeniy Khramtsov %%% Purpose : LDAP connections pool %%% Created : 12 Nov 2006 by Evgeniy 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(eldap_pool). -author('xram@jabber.ru'). %% API -export([start_link/7, bind/3, search/2, modify_passwd/3]). -include("ejabberd.hrl"). -include("logger.hrl"). %%==================================================================== %% API %%==================================================================== bind(PoolName, DN, Passwd) -> do_request(PoolName, {bind, [DN, Passwd]}). search(PoolName, Opts) -> do_request(PoolName, {search, [Opts]}). modify_passwd(PoolName, DN, Passwd) -> do_request(PoolName, {modify_passwd, [DN, Passwd]}). start_link(Name, Hosts, Backups, Port, Rootdn, Passwd, Opts) -> PoolName = make_id(Name), pg2:create(PoolName), lists:foreach(fun (Host) -> ID = list_to_binary(erlang:ref_to_list(make_ref())), case catch eldap:start_link(ID, [Host | Backups], Port, Rootdn, Passwd, Opts) of {ok, Pid} -> pg2:join(PoolName, Pid); Err -> ?INFO_MSG("Err = ~p", [Err]), error end end, Hosts). %%==================================================================== %% Internal functions %%==================================================================== do_request(Name, {F, Args}) -> case pg2:get_closest_pid(make_id(Name)) of Pid when is_pid(Pid) -> case catch apply(eldap, F, [Pid | Args]) of {'EXIT', {timeout, _}} -> ?ERROR_MSG("LDAP request failed: timed out", []); {'EXIT', Reason} -> ?ERROR_MSG("LDAP request failed: eldap:~p(~p)~nReason: ~p", [F, Args, Reason]), {error, Reason}; Reply -> Reply end; Err -> Err end. make_id(Name) -> jlib:binary_to_atom(<<"eldap_pool_", Name/binary>>). ejabberd-16.01/src/ejabberd_s2s_in.erl0000644000232200023220000005775112645157216020163 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_s2s_in.erl %%% Author : Alexey Shchepin %%% Purpose : Serve incoming s2s connection %%% Created : 6 Dec 2002 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_s2s_in). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(p1_fsm). %% External exports -export([start/2, start_link/2, socket_type/0]). -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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -define(DICT, dict). -record(state, {socket :: ejabberd_socket:socket_state(), sockmod = ejabberd_socket :: ejabberd_socket | ejabberd_frontend_socket, streamid = <<"">> :: binary(), shaper = none :: shaper:shaper(), tls = false :: boolean(), tls_enabled = false :: boolean(), tls_required = false :: boolean(), tls_certverify = false :: boolean(), tls_options = [] :: list(), server = <<"">> :: binary(), authenticated = false :: boolean(), auth_domain = <<"">> :: binary(), connections = (?DICT):new() :: ?TDICT, timer = make_ref() :: reference()}). %-define(DBGFSM, true). -ifdef(DBGFSM). -define(FSMOPTS, [{debug, [trace]}]). -else. -define(FSMOPTS, []). -endif. -define(STREAM_HEADER(Version), <<"">>). -define(STREAM_TRAILER, <<"">>). -define(INVALID_NAMESPACE_ERR, xml:element_to_binary(?SERR_INVALID_NAMESPACE)). -define(HOST_UNKNOWN_ERR, xml:element_to_binary(?SERR_HOST_UNKNOWN)). -define(INVALID_FROM_ERR, xml:element_to_binary(?SERR_INVALID_FROM)). -define(INVALID_XML_ERR, xml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). start(SockData, Opts) -> supervisor:start_child(ejabberd_s2s_in_sup, [SockData, Opts]). start_link(SockData, Opts) -> p1_fsm:start_link(ejabberd_s2s_in, [SockData, Opts], ?FSMOPTS ++ fsm_limit_opts(Opts)). socket_type() -> xml_stream. %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- init([{SockMod, Socket}, Opts]) -> ?DEBUG("started: ~p", [{SockMod, Socket}]), Shaper = case lists:keysearch(shaper, 1, Opts) of {value, {_, S}} -> S; _ -> none end, {StartTLS, TLSRequired, TLSCertverify} = case ejabberd_config:get_option( s2s_use_starttls, fun(false) -> false; (true) -> true; (optional) -> optional; (required) -> required; (required_trusted) -> required_trusted end, false) of UseTls when (UseTls == undefined) or (UseTls == false) -> {false, false, false}; UseTls when (UseTls == true) or (UseTls == optional) -> {true, false, false}; required -> {true, true, false}; required_trusted -> {true, true, true} end, TLSOpts1 = case ejabberd_config:get_option( s2s_certfile, fun iolist_to_binary/1) of undefined -> []; CertFile -> [{certfile, CertFile}] end, TLSOpts2 = case ejabberd_config:get_option( s2s_ciphers, fun iolist_to_binary/1) of undefined -> TLSOpts1; Ciphers -> [{ciphers, Ciphers} | TLSOpts1] end, TLSOpts3 = case ejabberd_config:get_option( 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) of 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 | TLSOpts4]; true -> TLSOpts4 end, Timer = erlang:start_timer(?S2STIMEOUT, self(), []), {ok, wait_for_stream, #state{socket = Socket, sockmod = SockMod, streamid = new_id(), shaper = Shaper, tls = StartTLS, tls_enabled = false, tls_required = TLSRequired, tls_certverify = TLSCertverify, tls_options = TLSOpts, timer = Timer}}. %%---------------------------------------------------------------------- %% Func: StateName/2 %% Returns: {next_state, NextStateName, NextStateData} | %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- 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">>} of {<<"jabber:server">>, _, Server, true} when StateData#state.tls and not StateData#state.authenticated -> send_text(StateData, ?STREAM_HEADER(<<" version='1.0'">>)), Auth = if StateData#state.tls_enabled -> 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, StateData#state.socket, From), {Result, From, Message}; _ -> {error, <<"(unknown)">>, <<"Got no valid 'from' attribute">>} end; true -> {no_verify, <<"(unknown)">>, <<"TLS not (yet) enabled">>} end, StartTLS = if StateData#state.tls_enabled -> []; not StateData#state.tls_enabled and not StateData#state.tls_required -> [#xmlel{name = <<"starttls">>, attrs = [{<<"xmlns">>, ?NS_TLS}], children = []}]; not StateData#state.tls_enabled and StateData#state.tls_required -> [#xmlel{name = <<"starttls">>, attrs = [{<<"xmlns">>, ?NS_TLS}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}] end, case Auth of {error, RemoteServer, CertError} when StateData#state.tls_certverify -> ?INFO_MSG("Closing s2s connection: ~s <--> ~s (~s)", [StateData#state.server, RemoteServer, CertError]), send_text(StateData, <<(xml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>, CertError)))/binary, (?STREAM_TRAILER)/binary>>), {stop, normal, StateData}; {VerifyResult, RemoteServer, Msg} -> {SASL, NewStateData} = case VerifyResult of ok -> {[#xmlel{name = <<"mechanisms">>, attrs = [{<<"xmlns">>, ?NS_SASL}], children = [#xmlel{name = <<"mechanism">>, attrs = [], children = [{xmlcdata, <<"EXTERNAL">>}]}]}], StateData#state{auth_domain = RemoteServer}}; error -> ?DEBUG("Won't accept certificate of ~s: ~s", [RemoteServer, Msg]), {[], StateData}; no_verify -> {[], StateData} end, send_element(NewStateData, #xmlel{name = <<"stream:features">>, attrs = [], children = SASL ++ StartTLS ++ ejabberd_hooks:run_fold(s2s_stream_features, Server, [], [Server])}), {next_state, wait_for_feature_request, NewStateData#state{server = Server}} end; {<<"jabber:server">>, _, Server, true} when StateData#state.authenticated -> send_text(StateData, ?STREAM_HEADER(<<" version='1.0'">>)), send_element(StateData, #xmlel{name = <<"stream:features">>, attrs = [], children = ejabberd_hooks:run_fold(s2s_stream_features, Server, [], [Server])}), {next_state, stream_established, StateData}; {<<"jabber:server">>, <<"jabber:server:dialback">>, _Server, _} when (StateData#state.tls_required and StateData#state.tls_enabled) or (not StateData#state.tls_required) -> send_text(StateData, ?STREAM_HEADER(<<"">>)), {next_state, stream_established, StateData}; _ -> send_text(StateData, ?INVALID_NAMESPACE_ERR), {stop, normal, StateData} end; wait_for_stream({xmlstreamerror, _}, StateData) -> send_text(StateData, <<(?STREAM_HEADER(<<"">>))/binary, (?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), {stop, normal, StateData}; wait_for_stream(timeout, StateData) -> {stop, normal, StateData}; wait_for_stream(closed, StateData) -> {stop, normal, StateData}. wait_for_feature_request({xmlstreamelement, El}, StateData) -> #xmlel{name = Name, attrs = Attrs} = El, TLS = StateData#state.tls, TLSEnabled = StateData#state.tls_enabled, SockMod = (StateData#state.sockmod):get_sockmod(StateData#state.socket), case {xml:get_attr_s(<<"xmlns">>, Attrs), Name} of {?NS_TLS, <<"starttls">>} when TLS == true, TLSEnabled == false, SockMod == gen_tcp -> ?DEBUG("starttls", []), Socket = StateData#state.socket, TLSOpts1 = case ejabberd_config:get_option( {domain_certfile, StateData#state.server}, fun iolist_to_binary/1) of undefined -> StateData#state.tls_options; CertFile -> [{certfile, CertFile} | lists:keydelete(certfile, 1, StateData#state.tls_options)] end, TLSOpts = case ejabberd_config:get_option( {s2s_tls_compression, StateData#state.server}, fun(true) -> true; (false) -> false end, true) of true -> lists:delete(compression_none, TLSOpts1); false -> [compression_none | TLSOpts1] end, TLSSocket = (StateData#state.sockmod):starttls(Socket, TLSOpts, xml:element_to_binary(#xmlel{name = <<"proceed">>, attrs = [{<<"xmlns">>, ?NS_TLS}], children = []})), {next_state, wait_for_stream, 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), case Mech of <<"EXTERNAL">> when StateData#state.auth_domain /= <<"">> -> AuthDomain = StateData#state.auth_domain, AllowRemoteHost = ejabberd_s2s:allow_host(<<"">>, AuthDomain), if AllowRemoteHost -> (StateData#state.sockmod):reset_stream(StateData#state.socket), send_element(StateData, #xmlel{name = <<"success">>, attrs = [{<<"xmlns">>, ?NS_SASL}], children = []}), ?INFO_MSG("Accepted s2s EXTERNAL authentication for ~s (TLS=~p)", [AuthDomain, StateData#state.tls_enabled]), change_shaper(StateData, <<"">>, jid:make(<<"">>, AuthDomain, <<"">>)), {next_state, wait_for_stream, StateData#state{streamid = new_id(), authenticated = true}}; true -> send_element(StateData, #xmlel{name = <<"failure">>, attrs = [{<<"xmlns">>, ?NS_SASL}], children = []}), send_text(StateData, ?STREAM_TRAILER), {stop, normal, StateData} end; _ -> send_element(StateData, #xmlel{name = <<"failure">>, attrs = [{<<"xmlns">>, ?NS_SASL}], children = [#xmlel{name = <<"invalid-mechanism">>, attrs = [], children = []}]}), {stop, normal, StateData} end; _ -> stream_established({xmlstreamelement, El}, StateData) end; wait_for_feature_request({xmlstreamend, _Name}, StateData) -> send_text(StateData, ?STREAM_TRAILER), {stop, normal, StateData}; wait_for_feature_request({xmlstreamerror, _}, StateData) -> send_text(StateData, <<(?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), {stop, normal, StateData}; wait_for_feature_request(closed, StateData) -> {stop, normal, StateData}. stream_established({xmlstreamelement, El}, StateData) -> cancel_timer(StateData#state.timer), Timer = erlang:start_timer(?S2STIMEOUT, self(), []), case is_key_packet(El) of {key, To, From, Id, Key} -> ?DEBUG("GET KEY: ~p", [{To, From, Id, Key}]), LTo = jid:nameprep(To), LFrom = jid:nameprep(From), case {ejabberd_s2s:allow_host(LTo, LFrom), lists:member(LTo, ejabberd_router:dirty_get_all_domains())} of {true, true} -> ejabberd_s2s_out:terminate_if_waiting_delay(LTo, LFrom), ejabberd_s2s_out:start(LTo, LFrom, {verify, self(), Key, StateData#state.streamid}), Conns = (?DICT):store({LFrom, LTo}, wait_for_verification, StateData#state.connections), change_shaper(StateData, LTo, jid:make(<<"">>, LFrom, <<"">>)), {next_state, stream_established, StateData#state{connections = Conns, timer = Timer}}; {_, false} -> send_text(StateData, ?HOST_UNKNOWN_ERR), {stop, normal, StateData}; {false, _} -> send_text(StateData, ?INVALID_FROM_ERR), {stop, normal, StateData} end; {verify, To, From, Id, Key} -> ?DEBUG("VERIFY KEY: ~p", [{To, From, Id, Key}]), LTo = jid:nameprep(To), LFrom = jid:nameprep(From), Type = case ejabberd_s2s:make_key({LTo, LFrom}, Id) of Key -> <<"valid">>; _ -> <<"invalid">> end, send_element(StateData, #xmlel{name = <<"db:verify">>, attrs = [{<<"from">>, To}, {<<"to">>, From}, {<<"id">>, Id}, {<<"type">>, Type}], children = []}), {next_state, stream_established, StateData#state{timer = Timer}}; _ -> NewEl = jlib:remove_attr(<<"xmlns">>, El), #xmlel{name = Name, attrs = Attrs} = NewEl, From_s = xml:get_attr_s(<<"from">>, Attrs), From = jid:from_string(From_s), To_s = xml:get_attr_s(<<"to">>, Attrs), To = jid:from_string(To_s), if (To /= error) and (From /= error) -> LFrom = From#jid.lserver, LTo = To#jid.lserver, if StateData#state.authenticated -> case LFrom == StateData#state.auth_domain andalso lists:member(LTo, ejabberd_router:dirty_get_all_domains()) of true -> if (Name == <<"iq">>) or (Name == <<"message">>) or (Name == <<"presence">>) -> ejabberd_hooks:run(s2s_receive_packet, LTo, [From, To, NewEl]), ejabberd_router:route(From, To, NewEl); true -> error end; false -> error end; true -> case (?DICT):find({LFrom, LTo}, StateData#state.connections) of {ok, established} -> if (Name == <<"iq">>) or (Name == <<"message">>) or (Name == <<"presence">>) -> ejabberd_hooks:run(s2s_receive_packet, LTo, [From, To, NewEl]), ejabberd_router:route(From, To, NewEl); true -> error end; _ -> error end end; true -> error end, ejabberd_hooks:run(s2s_loop_debug, [{xmlstreamelement, El}]), {next_state, stream_established, StateData#state{timer = Timer}} end; stream_established({valid, From, To}, StateData) -> send_element(StateData, #xmlel{name = <<"db:result">>, attrs = [{<<"from">>, To}, {<<"to">>, From}, {<<"type">>, <<"valid">>}], children = []}), ?INFO_MSG("Accepted s2s dialback authentication for ~s (TLS=~p)", [From, StateData#state.tls_enabled]), LFrom = jid:nameprep(From), LTo = jid:nameprep(To), NSD = StateData#state{connections = (?DICT):store({LFrom, LTo}, established, StateData#state.connections)}, {next_state, stream_established, NSD}; stream_established({invalid, From, To}, StateData) -> send_element(StateData, #xmlel{name = <<"db:result">>, attrs = [{<<"from">>, To}, {<<"to">>, From}, {<<"type">>, <<"invalid">>}], children = []}), LFrom = jid:nameprep(From), LTo = jid:nameprep(To), NSD = StateData#state{connections = (?DICT):erase({LFrom, LTo}, StateData#state.connections)}, {next_state, stream_established, NSD}; stream_established({xmlstreamend, _Name}, StateData) -> {stop, normal, StateData}; stream_established({xmlstreamerror, _}, StateData) -> send_text(StateData, <<(?INVALID_XML_ERR)/binary, (?STREAM_TRAILER)/binary>>), {stop, normal, StateData}; stream_established(timeout, StateData) -> {stop, normal, StateData}; stream_established(closed, StateData) -> {stop, normal, 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}. handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. handle_sync_event(get_state_infos, _From, StateName, StateData) -> SockMod = StateData#state.sockmod, {Addr, Port} = try SockMod:peername(StateData#state.socket) of {ok, {A, P}} -> {A, P}; {error, _} -> {unknown, unknown} catch _:_ -> {unknown, unknown} end, Domains = get_external_hosts(StateData), Infos = [{direction, in}, {statename, StateName}, {addr, Addr}, {port, Port}, {streamid, StateData#state.streamid}, {tls, StateData#state.tls}, {tls_enabled, StateData#state.tls_enabled}, {tls_options, StateData#state.tls_options}, {authenticated, StateData#state.authenticated}, {shaper, StateData#state.shaper}, {sockmod, SockMod}, {domains, Domains}], Reply = {state_infos, Infos}, {reply, Reply, 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(_Event, _From, StateName, StateData) -> Reply = ok, {reply, Reply, StateName, StateData}. code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. handle_info({send_text, Text}, StateName, StateData) -> send_text(StateData, Text), {next_state, StateName, StateData}; handle_info({timeout, Timer, _}, _StateName, #state{timer = Timer} = StateData) -> {stop, normal, StateData}; handle_info(_, StateName, StateData) -> {next_state, StateName, StateData}. terminate(Reason, _StateName, StateData) -> ?DEBUG("terminated: ~p", [Reason]), case Reason of {process_limit, _} -> [ejabberd_s2s:external_host_overloaded(Host) || Host <- get_external_hosts(StateData)]; _ -> ok end, (StateData#state.sockmod):close(StateData#state.socket), ok. get_external_hosts(StateData) -> case StateData#state.authenticated of true -> [StateData#state.auth_domain]; false -> Connections = StateData#state.connections, [D || {{D, _}, established} <- dict:to_list(Connections)] end. print_state(State) -> State. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- send_text(StateData, Text) -> (StateData#state.sockmod):send(StateData#state.socket, Text). send_element(StateData, El) -> send_text(StateData, xml:element_to_binary(El)). change_shaper(StateData, Host, JID) -> Shaper = acl:match_rule(Host, StateData#state.shaper, JID), (StateData#state.sockmod):change_shaper(StateData#state.socket, Shaper). new_id() -> randoms:get_string(). cancel_timer(Timer) -> erlang:cancel_timer(Timer), receive {timeout, Timer, _} -> ok after 0 -> ok end. 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)}; 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)}; is_key_packet(_) -> false. fsm_limit_opts(Opts) -> case lists:keysearch(max_fsm_queue, 1, Opts) of {value, {_, N}} when is_integer(N) -> [{max_queue, N}]; _ -> case ejabberd_config:get_option( max_fsm_queue, fun(I) when is_integer(I), I > 0 -> I end) of undefined -> []; 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_dhfile) -> 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_dhfile, s2s_protocol_options, s2s_tls_compression, s2s_use_starttls]. ejabberd-16.01/src/ejabberd_auth_odbc.erl0000644000232200023220000004433612645157216020711 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_auth_odbc.erl %%% Author : Alexey Shchepin %%% Purpose : Authentification via ODBC %%% Created : 12 Dec 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_auth_odbc). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(ejabberd_auth). -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, convert_to_scram/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -define(SALT_LENGTH, 16). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start(_Host) -> ok. plain_password_required() -> case is_scrammed() of false -> false; true -> true end. store_type() -> case is_scrammed() of false -> plain; %% allows: PLAIN DIGEST-MD5 SCRAM true -> scram %% allows: PLAIN SCRAM end. %% @spec (User, Server, Password) -> true | false | {error, Error} check_password(User, Server, Password) -> LServer = jid:nameprep(Server), LUser = jid: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 = 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. %% @spec (User, Server, Password, Digest, DigestGen) -> true | false | {error, Error} check_password(User, Server, Password, Digest, DigestGen) -> LServer = jid:nameprep(Server), LUser = jid: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. %% @spec (User::string(), Server::string(), Password::string()) -> %% ok | {error, invalid_jid} set_password(User, Server, Password) -> LServer = jid:nameprep(Server), LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> {error, invalid_jid}; (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) ) of {atomic, ok} -> ok; Other -> {error, Other} end; false -> Pass = ejabberd_odbc:escape(Password), case catch odbc_queries:set_password_t(LServer, Username, Pass) of {atomic, ok} -> ok; Other -> {error, Other} end end end. %% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} try_register(User, Server, Password) -> LServer = jid:nameprep(Server), LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> {error, invalid_jid}; (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) ) of {updated, 1} -> {atomic, ok}; _ -> {atomic, exists} end; false -> Pass = ejabberd_odbc:escape(Password), case catch odbc_queries:add_user(LServer, Username, Pass) of {updated, 1} -> {atomic, ok}; _ -> {atomic, exists} end end end. dirty_get_registered_users() -> Servers = ejabberd_config:get_vh_by_auth_method(odbc), lists:flatmap(fun (Server) -> get_vh_registered_users(Server) end, 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]; _ -> [] 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]; _ -> [] 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 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 end. get_password(User, Server) -> LServer = jid:nameprep(Server), LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> false; (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]]} -> {jlib:decode_base64(StoredKey), jlib:decode_base64(ServerKey), jlib:decode_base64(Salt), binary_to_integer(IterationCount)}; _ -> false end; false -> case catch odbc_queries:get_password(LServer, Username) of {selected, [<<"password">>], [[Password]]} -> Password; _ -> false end end end. get_password_s(User, Server) -> LServer = jid:nameprep(Server), LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> <<"">>; (LUser == <<>>) or (LServer == <<>>) -> <<"">>; true -> case is_scrammed() of false -> Username = ejabberd_odbc:escape(LUser), case catch odbc_queries:get_password(LServer, Username) of {selected, [<<"password">>], [[Password]]} -> Password; _ -> <<"">> end; true -> <<"">> end end. %% @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]]} -> true; %% Account exists {selected, [<<"password">>], []} -> false; %% Account does not exist {error, Error} -> {error, Error} catch _:B -> {error, B} end end. %% @spec (User, Server) -> ok | error %% @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), ok end. %% @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 = jid:nameprep(Server), LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> error; (LUser == <<>>) or (LServer == <<>>) -> error; true -> case is_scrammed() of true -> case check_password(User, Server, Password) of true -> remove_user(User, Server), ok; 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), case Result of {selected, [<<"password">>], [[Password]]} -> ok; {selected, [<<"password">>], []} -> not_exists; _ -> not_allowed end end, {atomic, Result} = odbc_queries:sql_transaction( LServer, F), Result end end. %%% %%% SCRAM %%% is_scrammed() -> scram == ejabberd_config:get_option({auth_password_format, ?MYNAME}, fun(V) -> V end). password_to_scram(Password) -> password_to_scram(Password, ?SCRAM_DEFAULT_ITERATION_COUNT). password_to_scram(Password, IterationCount) -> Salt = crypto:rand_bytes(?SALT_LENGTH), SaltedPassword = scram:salted_password(Password, Salt, IterationCount), StoredKey = scram:stored_key(scram:client_key(SaltedPassword)), ServerKey = scram:server_key(SaltedPassword), #scram{storedkey = jlib:encode_base64(StoredKey), serverkey = jlib:encode_base64(ServerKey), salt = jlib:encode_base64(Salt), iterationcount = IterationCount}. is_password_scram_valid(Password, Scram) -> IterationCount = Scram#scram.iterationcount, Salt = jlib:decode_base64(Scram#scram.salt), SaltedPassword = scram:salted_password(Password, Salt, IterationCount), StoredKey = scram:stored_key(scram:client_key(SaltedPassword)), jlib:decode_base64(Scram#scram.storedkey) == StoredKey. -define(BATCH_SIZE, 1000). set_password_scram_t(Username, StoredKey, ServerKey, Salt, IterationCount) -> odbc_queries:update_t(<<"users">>, [<<"username">>, <<"password">>, <<"serverkey">>, <<"salt">>, <<"iterationcount">>], [Username, StoredKey, ServerKey, Salt, IterationCount], [<<"username='">>, Username, <<"'">>]). convert_to_scram(Server) -> LServer = jid:nameprep(Server), if LServer == error; LServer == <<>> -> {error, {incorrect_server_name, Server}}; true -> F = fun () -> case ejabberd_odbc:sql_query_t( [<<"select username, password from users where " "iterationcount=0 limit ">>, integer_to_binary(?BATCH_SIZE), <<";">>]) of {selected, [<<"username">>, <<"password">>], []} -> ok; {selected, [<<"username">>, <<"password">>], Rs} -> lists:foreach( fun([LUser, Password]) -> Username = ejabberd_odbc:escape(LUser), Scram = password_to_scram(Password), set_password_scram_t( 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) ) end, Rs), continue; Err -> {bad_reply, Err} end end, case odbc_queries:sql_transaction(LServer, F) of {atomic, ok} -> ok; {atomic, continue} -> convert_to_scram(Server); {atomic, Error} -> {error, Error}; Error -> Error end end. opt_type(auth_password_format) -> fun (V) -> V end; opt_type(_) -> [auth_password_format]. ejabberd-16.01/src/ejabberd_app.erl0000644000232200023220000001727412645157216017542 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_app.erl %%% Author : Alexey Shchepin %%% Purpose : ejabberd's application callback module %%% Created : 31 Jan 2003 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_app). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(application). -export([start_modules/0, start/2, prep_stop/1, stop/1, init/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). %%% %%% Application API %%% start(normal, _Args) -> ejabberd_logger:start(), write_pid_file(), jid:start(), start_apps(), ejabberd:check_app(ejabberd), randoms:start(), db_init(), start(), translate:start(), ejabberd_ctl:init(), ejabberd_commands:init(), ejabberd_admin:start(), gen_mod:start(), ext_mod:start(), ejabberd_config:start(), set_settings_from_config(), acl:start(), shaper:start(), connect_nodes(), Sup = ejabberd_sup:start_link(), ejabberd_rdbms:start(), ejabberd_riak_sup:start(), ejabberd_sm:start(), cyrsasl:start(), % Profiling %ejabberd_debug:eprof_start(), %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()]), Sup; start(_, _) -> {error, badarg}. %% Prepare the application for termination. %% This function is called when an application is about to be stopped, %% before shutting down the processes of the application. prep_stop(State) -> ejabberd_listener:stop_listeners(), stop_modules(), ejabberd_admin:stop(), broadcast_c2s_shutdown(), timer:sleep(5000), State. %% All the processes were killed when this function is called stop(_State) -> ?INFO_MSG("ejabberd ~s is stopped in the node ~p", [?VERSION, node()]), delete_pid_file(), %%ejabberd_debug:stop(), ok. %%% %%% Internal functions %%% start() -> spawn_link(?MODULE, init, []). init() -> register(ejabberd, self()), loop(). loop() -> receive _ -> loop() end. db_init() -> ejabberd_config:env_binary_to_list(mnesia, dir), MyNode = node(), DbNodes = mnesia:system_info(db_nodes), case lists:member(MyNode, DbNodes) of true -> ok; false -> ?CRITICAL_MSG("Node name mismatch: I'm [~s], " "the database is owned by ~p", [MyNode, DbNodes]), ?CRITICAL_MSG("Either set ERLANG_NODE in ejabberdctl.cfg " "or change node name in Mnesia", []), erlang:error(node_name_mismatch) end, case mnesia:system_info(extra_db_nodes) of [] -> mnesia:create_schema([node()]); _ -> ok end, ejabberd:start_app(mnesia, permanent), mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity). %% Start all the modules in all the hosts start_modules() -> lists:foreach( fun(Host) -> Modules = ejabberd_config:get_option( {modules, Host}, fun(Mods) -> lists:map( fun({M, A}) when is_atom(M), is_list(A) -> {M, A} end, Mods) end, []), lists:foreach( fun({Module, Args}) -> gen_mod:start_module(Host, Module, Args) end, Modules) end, ?MYHOSTS). %% Stop all the modules in all the hosts stop_modules() -> lists:foreach( fun(Host) -> Modules = ejabberd_config:get_option( {modules, Host}, fun(Mods) -> lists:map( fun({M, A}) when is_atom(M), is_list(A) -> {M, A} end, Mods) end, []), lists:foreach( fun({Module, _Args}) -> gen_mod:stop_module_keep_config(Host, Module) end, Modules) end, ?MYHOSTS). connect_nodes() -> Nodes = ejabberd_config:get_option( cluster_nodes, fun(Ns) -> true = lists:all(fun is_atom/1, Ns), Ns end, []), lists:foreach(fun(Node) -> net_kernel:connect_node(Node) end, Nodes). %% If ejabberd is running on some Windows machine, get nameservers and add to Erlang maybe_add_nameservers() -> case os:type() of {win32, _} -> add_windows_nameservers(); _ -> ok end. add_windows_nameservers() -> IPTs = win32_dns:get_nameservers(), ?INFO_MSG("Adding machine's DNS IPs to Erlang system:~n~p", [IPTs]), lists:foreach(fun(IPT) -> inet_db:add_ns(IPT) end, IPTs). broadcast_c2s_shutdown() -> Children = ejabberd_sm:get_all_pids(), lists:foreach( fun(C2SPid) when node(C2SPid) == node() -> C2SPid ! system_shutdown; (_) -> ok end, Children). %%% %%% PID file %%% write_pid_file() -> case ejabberd:get_pid_file() of false -> ok; PidFilename -> write_pid_file(os:getpid(), PidFilename) end. write_pid_file(Pid, PidFilename) -> case file:open(PidFilename, [write]) of {ok, Fd} -> io:format(Fd, "~s~n", [Pid]), file:close(Fd); {error, Reason} -> ?ERROR_MSG("Cannot write PID file ~s~nReason: ~p", [PidFilename, Reason]), throw({cannot_write_pid_file, PidFilename, Reason}) end. delete_pid_file() -> case ejabberd:get_pid_file() of false -> ok; PidFilename -> file:delete(PidFilename) end. set_settings_from_config() -> Level = ejabberd_config:get_option( loglevel, fun(P) when P>=0, P=<5 -> P end, 4), 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(), ejabberd:start_app(sasl), ejabberd:start_app(ssl), ejabberd:start_app(p1_yaml), ejabberd:start_app(p1_tls), ejabberd:start_app(p1_xml), ejabberd:start_app(p1_stringprep), ejabberd:start_app(p1_zlib), ejabberd:start_app(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) -> 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, net_ticktime]. ejabberd-16.01/src/ejabberd_auth_riak.erl0000644000232200023220000002323012645157216020716 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_auth_riak.erl %%% Author : Evgeniy Khramtsov %%% Purpose : Authentification via Riak %%% Created : 12 Nov 2012 by Evgeniy 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(ejabberd_auth_riak). -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, 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, export/1, import/3, plain_password_required/0]). -export([passwd_schema/0]). -include("ejabberd.hrl"). -record(passwd, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$1', password = <<"">> :: binary() | scram() | '_'}). -define(SALT_LENGTH, 16). start(_Host) -> ok. plain_password_required() -> case is_scrammed() of false -> false; true -> true end. store_type() -> case is_scrammed() of false -> plain; %% allows: PLAIN DIGEST-MD5 SCRAM true -> scram %% allows: PLAIN SCRAM end. passwd_schema() -> {record_info(fields, passwd), #passwd{}}. check_password(User, Server, Password) -> 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 /= <<"">>; {ok, #passwd{password = Scram}} when is_record(Scram, scram) -> is_password_scram_valid(Password, Scram); _ -> false end. check_password(User, Server, Password, Digest, DigestGen) -> 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 /= <<"">> -> 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. set_password(User, Server, Password) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), US = {LUser, LServer}, if (LUser == error) or (LServer == error) -> {error, invalid_jid}; true -> Password2 = case is_scrammed() and is_binary(Password) of true -> password_to_scram(Password); false -> Password end, ok = ejabberd_riak:put(#passwd{us = US, password = Password2}, passwd_schema(), [{'2i', [{<<"host">>, LServer}]}]) end. try_register(User, Server, PasswordList) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), 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}; true -> case ejabberd_riak:get(passwd, passwd_schema(), US) of {error, notfound} -> Password2 = case is_scrammed() and is_binary(Password) of true -> password_to_scram(Password); false -> Password end, {atomic, ejabberd_riak:put( #passwd{us = US, password = Password2}, passwd_schema(), [{'2i', [{<<"host">>, LServer}]}])}; {ok, _} -> exists; Err -> {atomic, Err} end end. dirty_get_registered_users() -> lists:flatmap( fun(Server) -> get_vh_registered_users(Server) end, ejabberd_config:get_vh_by_auth_method(riak)). get_vh_registered_users(Server) -> LServer = jid:nameprep(Server), case ejabberd_riak:get_keys_by_index(passwd, <<"host">>, LServer) of {ok, Users} -> Users; _ -> [] end. get_vh_registered_users(Server, _) -> get_vh_registered_users(Server). get_vh_registered_users_number(Server) -> LServer = jid:nameprep(Server), case ejabberd_riak:count_by_index(passwd, <<"host">>, LServer) of {ok, N} -> N; _ -> 0 end. get_vh_registered_users_number(Server, _) -> get_vh_registered_users_number(Server). get_password(User, 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; {ok, #passwd{password = Scram}} when is_record(Scram, scram) -> {jlib:decode_base64(Scram#scram.storedkey), jlib:decode_base64(Scram#scram.serverkey), jlib:decode_base64(Scram#scram.salt), Scram#scram.iterationcount}; _ -> false end. get_password_s(User, 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; {ok, #passwd{password = Scram}} when is_record(Scram, scram) -> <<"">>; _ -> <<"">> end. is_user_exists(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of {error, notfound} -> false; {ok, _} -> true; Err -> Err end. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), ejabberd_riak:delete(passwd, {LUser, LServer}), ok. remove_user(User, Server, Password) -> 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) -> ejabberd_riak:delete(passwd, {LUser, LServer}), ok; {ok, #passwd{password = Scram}} when is_record(Scram, scram) -> case is_password_scram_valid(Password, Scram) of true -> ejabberd_riak:delete(passwd, {LUser, LServer}), ok; false -> not_allowed end; _ -> not_exists end. %%% %%% SCRAM %%% is_scrammed() -> scram == ejabberd_config:get_local_option({auth_password_format, ?MYNAME}, fun(V) -> V end). password_to_scram(Password) -> password_to_scram(Password, ?SCRAM_DEFAULT_ITERATION_COUNT). password_to_scram(Password, IterationCount) -> Salt = crypto:rand_bytes(?SALT_LENGTH), SaltedPassword = scram:salted_password(Password, Salt, IterationCount), StoredKey = scram:stored_key(scram:client_key(SaltedPassword)), ServerKey = scram:server_key(SaltedPassword), #scram{storedkey = jlib:encode_base64(StoredKey), serverkey = jlib:encode_base64(ServerKey), salt = jlib:encode_base64(Salt), iterationcount = IterationCount}. is_password_scram_valid(Password, Scram) -> IterationCount = Scram#scram.iterationcount, Salt = jlib:decode_base64(Scram#scram.salt), SaltedPassword = scram:salted_password(Password, Salt, IterationCount), StoredKey = scram:stored_key(scram:client_key(SaltedPassword)), jlib:decode_base64(Scram#scram.storedkey) == StoredKey. export(_Server) -> [{passwd, fun(Host, #passwd{us = {LUser, LServer}, password = Password}) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), Pass = ejabberd_odbc:escape(Password), [[<<"delete from users where username='">>, Username, <<"';">>], [<<"insert into users(username, password) " "values ('">>, Username, <<"', '">>, Pass, <<"');">>]]; (_Host, _R) -> [] end}]. import(LServer, riak, #passwd{} = Passwd) -> ejabberd_riak:put(Passwd, passwd_schema(), [{'2i', [{<<"host">>, LServer}]}]); import(_, _, _) -> pass. ejabberd-16.01/src/node_dispatch.erl0000644000232200023220000001344712645157216017746 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_dispatch.erl %%% Author : Christophe Romain %%% Purpose : Publish item to node and all child subnodes %%% Created : 1 Dec 2007 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. %%% %%%---------------------------------------------------------------------- %%% @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). -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]). 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, 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_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(Nodes) -> node_hometree:delete_node(Nodes). subscribe_node(_Nidx, _Sender, _Subscriber, _AccessModel, _SendLast, _PresenceSubscription, _RosterGroup, _Options) -> {error, ?ERR_FORBIDDEN}. unsubscribe_node(_Nidx, _Sender, _Subscriber, _SubId) -> {error, ?ERR_FORBIDDEN}. 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(_Nidx, _Publisher, _PublishModel, _ItemId) -> {error, ?ERR_ITEM_NOT_FOUND}. purge_node(_Nidx, _Owner) -> {error, ?ERR_FORBIDDEN}. get_entity_affiliations(_Host, _Owner) -> {result, []}. get_node_affiliations(_Nidx) -> {result, []}. get_affiliation(_Nidx, _Owner) -> {result, none}. set_affiliation(Nidx, Owner, Affiliation) -> node_hometree:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(_Host, _Owner) -> {result, []}. get_node_subscriptions(Nidx) -> node_hometree:get_node_subscriptions(Nidx). get_subscriptions(_Nidx, _Owner) -> {result, []}. 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(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_hometree:node_to_path(Node). path_to_node(Path) -> node_hometree:path_to_node(Path). ejabberd-16.01/src/ejabberd_http.erl0000644000232200023220000007237312645157216017742 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_http.erl %%% Author : Alexey Shchepin %%% Purpose : %%% Created : 27 Feb 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). -behaviour(ejabberd_config). -author('alexey@process-one.net'). %% External exports -export([start/2, start_link/2, become_controller/1, socket_type/0, receive_headers/1, url_encode/1, transform_listen_option/2]). -export([init/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_http.hrl"). -record(state, {sockmod, socket, request_method, request_version, request_path, request_auth, request_keepalive, request_content_length, request_lang = <<"en">>, %% XXX bard: request handlers are configured in %% ejabberd.cfg under the HTTP service. For example, %% to have the module test_web handle requests with %% paths starting with "/test/module": %% %% {5280, ejabberd_http, [http_bind, web_admin, %% {request_handlers, [{["test", "module"], mod_test_web}]}]} %% request_handlers = [], request_host, request_port, request_tp, request_headers = [], end_of_request = false, options = [], default_host, trail = <<>> }). -define(XHTML_DOCTYPE, <<"\n\n">>). -define(HTML_DOCTYPE, <<"\n" "">>). start(SockData, Opts) -> {ok, proc_lib:spawn(ejabberd_http, init, [SockData, Opts])}. start_link(SockData, Opts) -> {ok, proc_lib:spawn_link(ejabberd_http, init, [SockData, Opts])}. init({SockMod, Socket}, Opts) -> TLSEnabled = proplists:get_bool(tls, Opts), TLSOpts1 = lists:filter(fun ({certfile, _}) -> true; ({ciphers, _}) -> true; ({dhfile, _}) -> true; (_) -> false end, Opts), TLSOpts2 = case lists:keysearch(protocol_options, 1, Opts) of {value, {_, O}} -> [_|ProtocolOptions] = lists:foldl( fun(X, Acc) -> X ++ Acc end, [], [["|" | binary_to_list(Opt)] || Opt <- O, is_binary(Opt)] ), [{protocol_options, iolist_to_binary(ProtocolOptions)} | TLSOpts1]; _ -> TLSOpts1 end, TLSOpts3 = case proplists:get_bool(tls_compression, Opts) of false -> [compression_none | TLSOpts2]; true -> TLSOpts2 end, TLSOpts = [verify_none | TLSOpts3], {SockMod1, Socket1} = if TLSEnabled -> inet:setopts(Socket, [{recbuf, 8192}]), {ok, TLSSocket} = p1_tls:tcp_to_tls(Socket, TLSOpts), {p1_tls, TLSSocket}; true -> {SockMod, Socket} end, Captcha = case proplists:get_bool(captcha, Opts) of true -> [{[<<"captcha">>], ejabberd_captcha}]; false -> [] end, Register = case proplists:get_bool(register, Opts) of true -> [{[<<"register">>], mod_register_web}]; false -> [] end, Admin = case proplists:get_bool(web_admin, Opts) of true -> [{[<<"admin">>], ejabberd_web_admin}]; false -> [] end, Bind = case proplists:get_bool(http_bind, Opts) of true -> [{[<<"http-bind">>], mod_http_bind}]; false -> [] end, XMLRPC = case proplists:get_bool(xmlrpc, Opts) of true -> [{[], ejabberd_xmlrpc}]; false -> [] end, DefinedHandlers = gen_mod:get_opt( request_handlers, Opts, fun(Hs) -> [{str:tokens( iolist_to_binary(Path), <<"/">>), Mod} || {Path, Mod} <- Hs] end, []), RequestHandlers = DefinedHandlers ++ Captcha ++ Register ++ Admin ++ Bind ++ XMLRPC, ?DEBUG("S: ~p~n", [RequestHandlers]), DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined), ?INFO_MSG("started: ~p", [{SockMod1, Socket1}]), State = #state{sockmod = SockMod1, socket = Socket1, default_host = DefaultHost, options = Opts, request_handlers = RequestHandlers}, try receive_headers(State) of V -> V catch {error, _} -> State end. become_controller(_Pid) -> ok. socket_type() -> raw. send_text(State, Text) -> case catch (State#state.sockmod):send(State#state.socket, Text) of ok -> ok; {error, timeout} -> ?INFO_MSG("Timeout on ~p:send", [State#state.sockmod]), exit(normal); Error -> ?DEBUG("Error in ~p:send: ~p", [State#state.sockmod, Error]), exit(normal) end. receive_headers(#state{trail = Trail} = State) -> SockMod = State#state.sockmod, Socket = State#state.socket, Data = SockMod:recv(Socket, 0, 300000), case Data of {error, _} -> ok; {ok, D} -> parse_headers(State#state{trail = <>}) end. parse_headers(#state{trail = <<>>} = State) -> receive_headers(State); parse_headers(#state{request_method = Method, trail = Data} = State) -> PktType = case Method of 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}), case NewState#state.end_of_request of true -> ok; _ -> parse_headers(NewState) end; {more, _} -> receive_headers(State#state{trail = Data}); _ -> ok end. process_header(State, Data) -> SockMod = State#state.sockmod, Socket = State#state.socket, case Data of {ok, {http_request, Method, Uri, Version}} -> KeepAlive = case Version of {1, 1} -> true; _ -> false end, Path = case Uri of {absoluteURI, _Scheme, _Host, _Port, P} -> {abs_path, P}; {abs_path, P} -> {abs_path, P}; _ -> Uri end, State#state{request_method = Method, request_version = Version, request_path = Path, request_keepalive = KeepAlive}; {ok, {http_header, _, 'Connection' = Name, _, Conn}} -> KeepAlive1 = case jlib:tolower(Conn) of <<"keep-alive">> -> true; <<"close">> -> false; _ -> State#state.request_keepalive end, State#state{request_keepalive = KeepAlive1, request_headers = add_header(Name, Conn, State)}; {ok, {http_header, _, 'Authorization' = Name, _, Auth}} -> State#state{request_auth = parse_auth(Auth), request_headers = add_header(Name, Auth, State)}; {ok, {http_header, _, 'Content-Length' = Name, _, SLen}} -> case catch jlib:binary_to_integer(SLen) of Len when is_integer(Len) -> State#state{request_content_length = Len, request_headers = add_header(Name, SLen, State)}; _ -> State end; {ok, {http_header, _, 'Accept-Language' = Name, _, Langs}} -> State#state{request_lang = parse_lang(Langs), request_headers = add_header(Name, Langs, State)}; {ok, {http_header, _, 'Host' = Name, _, Host}} -> 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)}; {ok, {http_header, _, Name, _, Value}} -> State#state{request_headers = add_header(Name, Value, State)}; {ok, http_eoh} when State#state.request_host == undefined -> ?WARNING_MSG("An HTTP request without 'Host' HTTP " "header was received.", []), throw(http_request_no_host_header); {ok, http_eoh} -> ?DEBUG("(~w) http query: ~w ~p~n", [State#state.socket, State#state.request_method, element(2, State#state.request_path)]), {HostProvided, Port, TP} = get_transfer_protocol(SockMod, State#state.request_host), Host = get_host_really_served(State#state.default_host, HostProvided), State2 = State#state{request_host = Host, request_port = Port, request_tp = TP}, {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} end; _ -> #state{end_of_request = true, options = State#state.options, default_host = State#state.default_host, request_handlers = State#state.request_handlers} end. add_header(Name, Value, State)-> [{Name, Value} | State#state.request_headers]. get_host_really_served(undefined, Provided) -> Provided; get_host_really_served(Default, Provided) -> case lists:member(Provided, ?MYHOSTS) of true -> Provided; false -> Default end. get_transfer_protocol(SockMod, HostPort) -> [Host | PortList] = str:tokens(HostPort, <<":">>), case {SockMod, PortList} of {gen_tcp, []} -> {Host, 80, http}; {gen_tcp, [Port]} -> {Host, jlib:binary_to_integer(Port), http}; {p1_tls, []} -> {Host, 443, https}; {p1_tls, [Port]} -> {Host, jlib:binary_to_integer(Port), https} end. %% XXX bard: search through request handlers looking for one that %% matches the requested URL path, and pass control to it. If none is %% found, answer with HTTP 404. process([], _, _, _, _) -> ejabberd_web:error(not_found); process(Handlers, Request, Socket, SockMod, Trail) -> {HandlerPathPrefix, HandlerModule, HandlerOpts, HandlersLeft} = case Handlers of [{Pfx, Mod} | Tail] -> {Pfx, Mod, [], Tail}; [{Pfx, Mod, Opts} | Tail] -> {Pfx, Mod, Opts, Tail} end, case (lists:prefix(HandlerPathPrefix, Request#request.path) or (HandlerPathPrefix==Request#request.path)) of true -> ?DEBUG("~p matches ~p", [Request#request.path, HandlerPathPrefix]), %% LocalPath is the path "local to the handler", i.e. if %% the handler was registered to handle "/test/" and the %% requested path is "/test/foo/bar", the local path is %% ["foo", "bar"] LocalPath = lists:nthtail(length(HandlerPathPrefix), Request#request.path), R = try HandlerModule:socket_handoff( LocalPath, Request, Socket, SockMod, Trail, HandlerOpts) catch error:undef -> HandlerModule:process(LocalPath, Request) end, ejabberd_hooks:run(http_request_debug, [{LocalPath, Request}]), R; false -> process(HandlersLeft, Request, Socket, SockMod, Trail) end. extract_path_query(#state{request_method = Method, 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', _} -> {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}, request_content_length = Len, sockmod = _SockMod, socket = _Socket} = State) when (Method =:= 'POST' orelse Method =:= 'PUT') andalso is_integer(Len) -> {NewState, Data} = recv_data(State, Len), ?DEBUG("client data: ~p~n", [Data]), case catch url_decode_q_split(Path) of {'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) -> {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) -> case extract_path_query(State) of {State2, false} -> {State2, make_bad_request(State)}; {State2, {LPath, LQuery, Data}} -> 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, path = LPath, q = LQuery, auth = Auth, data = Data, lang = Lang, host = Host, port = Port, tp = TP, opts = Options, headers = RequestHeaders, ip = IP}, 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) -> make_xhtml_output(State, 400, [], ejabberd_web:make_xhtml([#xmlel{name = <<"h1">>, attrs = [], children = [{xmlcdata, <<"400 Bad Request">>}]}])). analyze_ip_xff(IP, [], _Host) -> IP; analyze_ip_xff({IPLast, Port}, XFF, Host) -> [ClientIP | ProxiesIPs] = str:tokens(XFF, <<", ">>) ++ [jlib:ip_to_list(IPLast)], TrustedProxies = ejabberd_config:get_option( {trusted_proxies, Host}, fun(all) -> all; (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end, []), IPClient = case is_ipchain_trusted(ProxiesIPs, TrustedProxies) of true -> {ok, IPFirst} = inet_parse:address( binary_to_list(ClientIP)), ?DEBUG("The IP ~w was replaced with ~w due to " "header X-Forwarded-For: ~s", [IPLast, IPFirst, XFF]), IPFirst; false -> IPLast end, {IPClient, Port}. is_ipchain_trusted(_UserIPs, all) -> true; is_ipchain_trusted(UserIPs, TrustedIPs) -> [] == UserIPs -- [<<"127.0.0.1">> | TrustedIPs]. recv_data(State, Len) -> recv_data(State, Len, <<>>). 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, min(Len, 16#4000000), 300000) of {ok, Data} -> recv_data(State, Len - byte_size(Data), <>); Err -> ?DEBUG("Cannot receive HTTP data: ~p", [Err]), <<"">> end; _ -> Trail = (State#state.trail), recv_data(State#state{trail = <<>>}, Len - byte_size(Trail), <>) end. 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, Headers1 = case lists:keysearch(<<"Content-Type">>, 1, Headers) of {value, _} -> [{<<"Content-Length">>, iolist_to_binary(integer_to_list(byte_size(Data)))} | Headers]; _ -> [{<<"Content-Type">>, <<"text/html; charset=utf-8">>}, {<<"Content-Length">>, iolist_to_binary(integer_to_list(byte_size(Data)))} | Headers] end, HeadersOut = case {State#state.request_version, State#state.request_keepalive} of {{1, 1}, true} -> Headers1; {_, true} -> [{<<"Connection">>, <<"keep-alive">>} | Headers1]; {_, false} -> [{<<"Connection">>, <<"close">>} | Headers1] end, Version = case State#state.request_version of {1, 1} -> <<"HTTP/1.1 ">>; _ -> <<"HTTP/1.0 ">> end, H = lists:map(fun ({Attr, Val}) -> [Attr, <<": ">>, Val, <<"\r\n">>]; (_) -> [] end, HeadersOut), SL = [Version, iolist_to_binary(integer_to_list(Status)), <<" ">>, code_to_phrase(Status), <<"\r\n">>], Data2 = case State#state.request_method of 'HEAD' -> <<"">>; _ -> Data end, [SL, H, <<"\r\n">>, Data2]. make_text_output(State, Status, Headers, Text) -> make_text_output(State, Status, <<"">>, Headers, Text). make_text_output(State, Status, Reason, Headers, Text) -> Data = iolist_to_binary(Text), Headers1 = case lists:keysearch(<<"Content-Type">>, 1, Headers) of {value, _} -> [{<<"Content-Length">>, jlib:integer_to_binary(byte_size(Data))} | Headers]; _ -> [{<<"Content-Type">>, <<"text/html; charset=utf-8">>}, {<<"Content-Length">>, jlib:integer_to_binary(byte_size(Data))} | Headers] end, HeadersOut = case {State#state.request_version, State#state.request_keepalive} of {{1, 1}, true} -> Headers1; {_, true} -> [{<<"Connection">>, <<"keep-alive">>} | Headers1]; {_, false} -> [{<<"Connection">>, <<"close">>} | Headers1] end, Version = case State#state.request_version of {1, 1} -> <<"HTTP/1.1 ">>; _ -> <<"HTTP/1.0 ">> end, H = lists:map(fun ({Attr, Val}) -> [Attr, <<": ">>, Val, <<"\r\n">>] end, HeadersOut), NewReason = case Reason of <<"">> -> code_to_phrase(Status); _ -> Reason end, SL = [Version, jlib:integer_to_binary(Status), <<" ">>, NewReason, <<"\r\n">>], Data2 = case State#state.request_method of 'HEAD' -> <<"">>; _ -> Data end, [SL, H, <<"\r\n">>, Data2]. parse_lang(Langs) -> case str:tokens(Langs, <<",; ">>) of [First | _] -> First; [] -> <<"en">> end. % Code below is taken (with some modifications) from the yaws webserver, which % is distributed under the folowing license: % % This software (the yaws webserver) is free software. % Parts of this software is Copyright (c) Claes Wikstrom % Any use or misuse of the source code is hereby freely allowed. % % 1. Redistributions of source code must retain the above copyright % notice as well as this list of conditions. % % 2. Redistributions in binary form must reproduce the above copyright % notice as well as this list of conditions. %% @doc Split the URL and return {Path, QueryPart} url_decode_q_split(Path) -> url_decode_q_split(Path, <<>>). url_decode_q_split(<<$?, T/binary>>, Acc) -> %% Don't decode the query string here, that is parsed separately. {path_norm_reverse(Acc), T}; url_decode_q_split(<>, Acc) when H /= 0 -> url_decode_q_split(T, <>); url_decode_q_split(<<>>, Ack) -> {path_norm_reverse(Ack), <<>>}. %% @doc Decode a part of the URL and return string() path_decode(Path) -> path_decode(Path, <<>>). path_decode(<<$%, Hi, Lo, Tail/binary>>, Acc) -> Hex = hex_to_integer([Hi, Lo]), if Hex == 0 -> exit(badurl); true -> ok end, path_decode(Tail, <>); path_decode(<>, Acc) when H /= 0 -> path_decode(T, <>); path_decode(<<>>, Acc) -> Acc. path_norm_reverse(<<"/", T/binary>>) -> start_dir(0, <<"/">>, T); path_norm_reverse(T) -> start_dir(0, <<"">>, T). start_dir(N, Path, <<"..">>) -> rest_dir(N, Path, <<"">>); start_dir(N, Path, <<"/", T/binary>>) -> start_dir(N, Path, T); start_dir(N, Path, <<"./", T/binary>>) -> start_dir(N, Path, T); start_dir(N, Path, <<"../", T/binary>>) -> start_dir(N + 1, Path, T); start_dir(N, Path, T) -> rest_dir(N, Path, T). rest_dir(_N, Path, <<>>) -> case Path of <<>> -> <<"/">>; _ -> Path end; rest_dir(0, Path, <<$/, T/binary>>) -> start_dir(0, <<$/, Path/binary>>, T); rest_dir(N, Path, <<$/, T/binary>>) -> start_dir(N - 1, Path, T); rest_dir(0, Path, <>) -> rest_dir(0, <>, T); rest_dir(N, Path, <<_H, T/binary>>) -> rest_dir(N, Path, T). %% hex_to_integer hex_to_integer(Hex) -> case catch list_to_integer(Hex, 16) of {'EXIT', _} -> old_hex_to_integer(Hex); X -> X end. old_hex_to_integer(Hex) -> DEHEX = fun (H) when H >= $a, H =< $f -> H - $a + 10; (H) when H >= $A, H =< $F -> H - $A + 10; (H) when H >= $0, H =< $9 -> H - $0 end, lists:foldl(fun (E, Acc) -> Acc * 16 + DEHEX(E) end, 0, Hex). code_to_phrase(100) -> <<"Continue">>; code_to_phrase(101) -> <<"Switching Protocols ">>; code_to_phrase(200) -> <<"OK">>; code_to_phrase(201) -> <<"Created">>; code_to_phrase(202) -> <<"Accepted">>; code_to_phrase(203) -> <<"Non-Authoritative Information">>; code_to_phrase(204) -> <<"No Content">>; code_to_phrase(205) -> <<"Reset Content">>; code_to_phrase(206) -> <<"Partial Content">>; code_to_phrase(300) -> <<"Multiple Choices">>; code_to_phrase(301) -> <<"Moved Permanently">>; code_to_phrase(302) -> <<"Found">>; code_to_phrase(303) -> <<"See Other">>; code_to_phrase(304) -> <<"Not Modified">>; code_to_phrase(305) -> <<"Use Proxy">>; code_to_phrase(306) -> <<"(Unused)">>; code_to_phrase(307) -> <<"Temporary Redirect">>; code_to_phrase(400) -> <<"Bad Request">>; code_to_phrase(401) -> <<"Unauthorized">>; code_to_phrase(402) -> <<"Payment Required">>; code_to_phrase(403) -> <<"Forbidden">>; code_to_phrase(404) -> <<"Not Found">>; code_to_phrase(405) -> <<"Method Not Allowed">>; code_to_phrase(406) -> <<"Not Acceptable">>; code_to_phrase(407) -> <<"Proxy Authentication Required">>; code_to_phrase(408) -> <<"Request Timeout">>; code_to_phrase(409) -> <<"Conflict">>; code_to_phrase(410) -> <<"Gone">>; code_to_phrase(411) -> <<"Length Required">>; code_to_phrase(412) -> <<"Precondition Failed">>; code_to_phrase(413) -> <<"Request Entity Too Large">>; code_to_phrase(414) -> <<"Request-URI Too Long">>; code_to_phrase(415) -> <<"Unsupported Media Type">>; code_to_phrase(416) -> <<"Requested Range Not Satisfiable">>; code_to_phrase(417) -> <<"Expectation Failed">>; code_to_phrase(500) -> <<"Internal Server Error">>; code_to_phrase(501) -> <<"Not Implemented">>; code_to_phrase(502) -> <<"Bad Gateway">>; code_to_phrase(503) -> <<"Service Unavailable">>; code_to_phrase(504) -> <<"Gateway Timeout">>; code_to_phrase(505) -> <<"HTTP Version Not Supported">>. parse_auth(<<"Basic ", Auth64/binary>>) -> Auth = jlib:decode_base64(Auth64), %% Auth should be a string with the format: user@server:password %% Note that password can contain additional characters '@' and ':' case str:chr(Auth, $:) of 0 -> undefined; Pos -> {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) -> parse_urlencoded(S, nokey, <<>>, key). parse_urlencoded(<<$%, Hi, Lo, Tail/binary>>, Last, Cur, State) -> Hex = hex_to_integer([Hi, Lo]), parse_urlencoded(Tail, Last, <>, State); parse_urlencoded(<<$&, Tail/binary>>, _Last, Cur, key) -> [{Cur, <<"">>} | parse_urlencoded(Tail, nokey, <<>>, key)]; %% cont keymode parse_urlencoded(<<$&, Tail/binary>>, Last, Cur, value) -> V = {Last, Cur}, [V | parse_urlencoded(Tail, nokey, <<>>, key)]; parse_urlencoded(<<$+, Tail/binary>>, Last, Cur, State) -> parse_urlencoded(Tail, Last, <>, State); parse_urlencoded(<<$=, Tail/binary>>, _Last, Cur, key) -> parse_urlencoded(Tail, Cur, <<>>, value); %% change mode parse_urlencoded(<>, Last, Cur, State) -> parse_urlencoded(Tail, Last, <>, State); parse_urlencoded(<<>>, Last, Cur, _State) -> [{Last, Cur}]; parse_urlencoded(undefined, _, _, _) -> []. url_encode(A) -> url_encode(A, <<>>). url_encode(<>, Acc) when (H >= $a andalso H =< $z) orelse (H >= $A andalso H =< $Z) orelse (H >= $0 andalso H =< $9) orelse H == $_ orelse H == $. orelse H == $- orelse H == $/ orelse H == $: -> url_encode(T, <>); url_encode(<>, Acc) -> case integer_to_hex(H) of [X, Y] -> url_encode(T, <>); [X] -> url_encode(T, <>) end; url_encode(<<>>, Acc) -> Acc. integer_to_hex(I) -> case catch erlang:integer_to_list(I, 16) of {'EXIT', _} -> old_integer_to_hex(I); Int -> Int end. old_integer_to_hex(I) when I < 10 -> integer_to_list(I); old_integer_to_hex(I) when I < 16 -> [I - 10 + $A]; old_integer_to_hex(I) when I >= 16 -> N = trunc(I / 16), old_integer_to_hex(N) ++ old_integer_to_hex(I rem 16). % The following code is mostly taken from yaws_ssl.erl toupper(C) when C >= $a andalso C =< $z -> C - 32; toupper(C) -> C. tolower(C) when C >= $A andalso C =< $Z -> C + 32; tolower(C) -> C. normalize_header_name(Name) -> normalize_header_name(Name, [], true). normalize_header_name(<<"">>, Acc, _) -> iolist_to_binary(Acc); normalize_header_name(<<"-", Rest/binary>>, Acc, _) -> normalize_header_name(Rest, [Acc, "-"], true); normalize_header_name(<>, Acc, true) -> normalize_header_name(Rest, [Acc, toupper(C)], false); normalize_header_name(<>, Acc, false) -> normalize_header_name(Rest, [Acc, tolower(C)], false). normalize_path(Path) -> normalize_path(Path, []). normalize_path([], Norm) -> lists:reverse(Norm); normalize_path([<<"..">>|Path], Norm) -> normalize_path(Path, Norm); normalize_path([_Parent, <<"..">>|Path], Norm) -> normalize_path(Path, Norm); normalize_path([Part | Path], Norm) -> normalize_path(Path, [Part|Norm]). transform_listen_option(captcha, Opts) -> [{captcha, true}|Opts]; transform_listen_option(register, Opts) -> [{register, true}|Opts]; transform_listen_option(web_admin, Opts) -> [{web_admin, true}|Opts]; transform_listen_option(http_bind, Opts) -> [{http_bind, true}|Opts]; transform_listen_option(http_poll, Opts) -> Opts; transform_listen_option({request_handlers, Hs}, Opts) -> Hs1 = lists:map( fun({PList, Mod}) when is_list(PList) -> Path = iolist_to_binary([[$/, P] || P <- PList]), {Path, Mod}; (Opt) -> Opt end, Hs), [{request_handlers, Hs1} | Opts]; transform_listen_option(Opt, Opts) -> [Opt|Opts]. opt_type(trusted_proxies) -> fun (all) -> all; (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end; opt_type(_) -> [trusted_proxies]. ejabberd-16.01/src/node_public.erl0000644000232200023220000001310612645157216017415 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_public.erl %%% Author : Christophe Romain %%% Purpose : %%% Created : 1 Dec 2007 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_public). -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]). 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, 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_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). ejabberd-16.01/src/gen_iq_handler.erl0000644000232200023220000001325112645157216020072 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : gen_iq_handler.erl %%% Author : Alexey Shchepin %%% Purpose : IQ handler support %%% Created : 22 Jan 2003 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(gen_iq_handler). -author('alexey@process-one.net'). -behaviour(gen_server). %% API -export([start_link/3, add_iq_handler/6, remove_iq_handler/3, stop_iq_handler/3, handle/7, process_iq/6, check_type/1, transform_module_options/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -record(state, {host, module, function}). -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. %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link(Host, Module, Function) -> gen_server:start_link(?MODULE, [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) 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); {queues, Pids} -> lists:foreach(fun (Pid) -> catch gen_server:call(Pid, stop) end, Pids); _ -> 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(p1_time_compat:unique_integer(), length(Pids)), Pids), Pid ! {process_iq, From, To, IQ}; parallel -> spawn(?MODULE, process_iq, [Host, Module, Function, From, To, IQ]); _ -> 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]); ResIQ -> if ResIQ /= ignore -> ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)); true -> ok end end. -spec check_type(type()) -> type(). check_type(no_queue) -> no_queue; check_type(one_queue) -> one_queue; check_type(N) when is_integer(N), N>0 -> N; check_type(parallel) -> parallel. -spec transform_module_options([{atom(), any()}]) -> [{atom(), any()}]. transform_module_options(Opts) -> lists:map( fun({iqdisc, {queues, N}}) -> {iqdisc, N}; (Opt) -> Opt end, Opts). %%==================================================================== %% gen_server callbacks %%==================================================================== init([Host, Module, Function]) -> {ok, #state{host = Host, module = Module, function = Function}}. handle_call(stop, _From, State) -> Reply = ok, {stop, normal, Reply, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({process_iq, From, To, IQ}, #state{host = Host, module = Module, function = Function} = State) -> process_iq(Host, Module, Function, From, To, IQ), {noreply, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- ejabberd-16.01/src/nodetree_tree_odbc.erl0000644000232200023220000002237312645157216020753 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : nodetree_tree_odbc.erl %%% Author : Christophe Romain %%% Purpose : Standard node tree plugin with ODBC backend %%% Created : 1 Dec 2007 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. %%% %%%---------------------------------------------------------------------- %%% @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 %%% as a developer basis and reference to build its own custom pubsub node tree %%% types.

%%%

PubSub node tree plugins are using the {@link gen_nodetree} 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(nodetree_tree_odbc). -behaviour(gen_pubsub_nodetree). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). -include("jlib.hrl"). -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]). -export([raw_to_node/2]). init(_Host, _ServerHost, _Opts) -> ok. terminate(_Host, _ServerHost) -> ok. options() -> [{odbc, true} | nodetree_tree:options()]. 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_flat_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) -> 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 " "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. get_node(Nidx) -> case catch 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. get_nodes(Host, _From) -> get_nodes(Host). get_nodes(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, <<"';">>]) of {selected, [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], RItems} -> [raw_to_node(Host, Item) || Item <- RItems]; _ -> [] end. get_parentnodes(_Host, _Node, _From) -> []. %% @doc

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

get_parentnodes_tree(Host, Node, From) -> case get_node(Host, Node, From) of {error, _} -> []; Record -> [{0, [Record]}] end. get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). get_subnodes(Host, Node) -> 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 " "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). get_subnodes_tree(Host, Node) -> 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 " "pubsub_node where host='">>, H, <<"' and node like '">>, N, <<"%';">>]) of {selected, [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], RItems} -> [raw_to_node(Host, Item) || Item <- RItems]; _ -> [] end. create_node(Host, Node, Type, Owner, Options, Parents) -> BJID = jid:tolower(jid:remove_resource(Owner)), 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, Nidx} -> {ok, Nidx}; Other -> Other end; false -> {error, ?ERR_FORBIDDEN} end; {result, _} -> {error, ?ERR_CONFLICT}; Error -> Error end. delete_node(Host, Node) -> 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='">>, H, <<"' and node like '">>, N, <<"%';">>]), Removed. %% helpers 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='">>, 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 = Nidx, type = Type, options = Options}. nodeidx(Host, Node) -> 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 " "host='">>, H, <<"' and node='">>, N, <<"';">>]) of {selected, [<<"nodeid">>], [[Nidx]]} -> {result, Nidx}; {'EXIT', _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; _ -> {error, ?ERR_ITEM_NOT_FOUND} end. nodeowners(Nidx) -> {result, Res} = node_flat_odbc:get_node_affiliations(Nidx), [LJID || {LJID, Aff} <- Res, Aff =:= owner]. ejabberd-16.01/src/jid.erl0000644000232200023220000001417712645157216015711 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @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 %%%=================================================================== ejabberd-16.01/src/mod_last.erl0000644000232200023220000002760312645157216016743 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_last.erl %%% Author : Alexey Shchepin %%% Purpose : jabber:iq:last support (XEP-0012) %%% Created : 24 Oct 2003 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(mod_last). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -protocol({xep, 12, '2.0'}). -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, mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("mod_privacy.hrl"). -record(last_activity, {us = {<<"">>, <<"">>} :: {binary(), binary()}, timestamp = 0 :: non_neg_integer(), status = <<"">> :: binary()}). start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, one_queue), case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(last_activity, [{disc_copies, [node()]}, {attributes, record_info(fields, last_activity)}]), update_table(); _ -> ok end, gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST, ?MODULE, process_local_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST, ?MODULE, process_sm_iq, IQDisc), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:add(unset_presence_hook, Host, ?MODULE, on_presence_update, 50). stop(Host) -> ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:delete(unset_presence_hook, Host, ?MODULE, on_presence_update, 50), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST). %%% %%% Uptime of ejabberd node %%% process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> case Type of set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; get -> Sec = get_node_uptime(), IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_LAST}, {<<"seconds">>, iolist_to_binary(integer_to_list(Sec))}], children = []}]} end. %% @spec () -> integer() %% @doc Get the uptime of the ejabberd node, expressed in seconds. %% When ejabberd is starting, ejabberd_config:start/0 stores the datetime. get_node_uptime() -> case ejabberd_config:get_option( node_start, fun(S) when is_integer(S), S >= 0 -> S end) of undefined -> trunc(element(1, erlang:statistics(wall_clock)) / 1000); Now -> p1_time_compat:system_time(seconds) - Now end. now_to_seconds({MegaSecs, Secs, _MicroSecs}) -> MegaSecs * 1000000 + Secs. %%% %%% Serve queries about user last online %%% process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> case Type of set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; get -> User = To#jid.luser, Server = To#jid.lserver, {Subscription, _Groups} = ejabberd_hooks:run_fold(roster_get_jid_info, Server, {none, []}, [User, Server, From]), if (Subscription == both) or (Subscription == from) or (From#jid.luser == To#jid.luser) and (From#jid.lserver == To#jid.lserver) -> UserListRecord = ejabberd_hooks:run_fold(privacy_get_user_list, Server, #userlist{}, [User, Server]), case ejabberd_hooks:run_fold(privacy_check_packet, Server, allow, [User, Server, UserListRecord, {To, From, #xmlel{name = <<"presence">>, attrs = [], children = []}}, out]) of allow -> get_last_iq(IQ, SubEl, User, Server); deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} end; true -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} end end. %% @spec (LUser::string(), LServer::string()) -> %% {ok, TimeStamp::integer(), Status::string()} | not_found | {error, Reason} get_last(LUser, LServer) -> get_last(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). get_last(LUser, LServer, mnesia) -> case catch mnesia:dirty_read(last_activity, {LUser, LServer}) of {'EXIT', Reason} -> {error, Reason}; [] -> not_found; [#last_activity{timestamp = TimeStamp, status = Status}] -> {ok, TimeStamp, Status} end; get_last(LUser, LServer, riak) -> case ejabberd_riak:get(last_activity, last_activity_schema(), {LUser, LServer}) of {ok, #last_activity{timestamp = TimeStamp, status = Status}} -> {ok, TimeStamp, Status}; {error, notfound} -> not_found; Err -> 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}} end. get_last_iq(IQ, SubEl, LUser, LServer) -> case ejabberd_sm:get_user_resources(LUser, LServer) of [] -> case get_last(LUser, LServer) of {error, _Reason} -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}; not_found -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; {ok, TimeStamp, Status} -> TimeStamp2 = p1_time_compat:system_time(seconds), Sec = TimeStamp2 - TimeStamp, IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_LAST}, {<<"seconds">>, iolist_to_binary(integer_to_list(Sec))}], children = [{xmlcdata, Status}]}]} end; _ -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_LAST}, {<<"seconds">>, <<"0">>}], children = []}]} end. on_presence_update(User, Server, _Resource, Status) -> TimeStamp = p1_time_compat:system_time(seconds), store_last_info(User, Server, TimeStamp, Status). store_last_info(User, Server, TimeStamp, Status) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), DBType = gen_mod:db_type(LServer, ?MODULE), store_last_info(LUser, LServer, TimeStamp, Status, DBType). store_last_info(LUser, LServer, TimeStamp, Status, mnesia) -> US = {LUser, LServer}, F = fun () -> mnesia:write(#last_activity{us = US, timestamp = TimeStamp, status = Status}) end, mnesia:transaction(F); store_last_info(LUser, LServer, TimeStamp, Status, riak) -> US = {LUser, LServer}, {atomic, ejabberd_riak:put(#last_activity{us = US, timestamp = TimeStamp, status = 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). %% @spec (LUser::string(), LServer::string()) -> %% {ok, TimeStamp::integer(), Status::string()} | not_found get_last_info(LUser, LServer) -> case get_last(LUser, LServer) of {error, _Reason} -> not_found; Res -> Res end. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), DBType = gen_mod:db_type(LServer, ?MODULE), remove_user(LUser, LServer, DBType). remove_user(LUser, LServer, mnesia) -> US = {LUser, LServer}, 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); remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete(last_activity, {LUser, LServer})}. update_table() -> Fields = record_info(fields, last_activity), case mnesia:table_info(last_activity, attributes) of Fields -> ejabberd_config:convert_table_to_binary( last_activity, Fields, set, fun(#last_activity{us = {U, _}}) -> U end, fun(#last_activity{us = {U, S}, status = Status} = R) -> R#last_activity{us = {iolist_to_binary(U), iolist_to_binary(S)}, status = iolist_to_binary(Status)} end); _ -> ?INFO_MSG("Recreating last_activity table", []), mnesia:transform_table(last_activity, ignore, Fields) end. last_activity_schema() -> {record_info(fields, last_activity), #last_activity{}}. export(_Server) -> [{last_activity, fun(Host, #last_activity{us = {LUser, LServer}, timestamp = TimeStamp, status = Status}) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), Seconds = ejabberd_odbc:escape(jlib:integer_to_binary(TimeStamp)), State = ejabberd_odbc:escape(Status), [[<<"delete from last where username='">>, Username, <<"';">>], [<<"insert into last(username, seconds, " "state) values ('">>, Username, <<"', '">>, Seconds, <<"', '">>, State, <<"');">>]]; (_Host, _R) -> [] end}]. import(LServer) -> [{<<"select username, seconds, state from last">>, fun([LUser, TimeStamp, State]) -> #last_activity{us = {LUser, LServer}, timestamp = jlib:binary_to_integer( TimeStamp), status = State} end}]. import(_LServer, mnesia, #last_activity{} = LA) -> mnesia:dirty_write(LA); import(_LServer, riak, #last_activity{} = LA) -> ejabberd_riak:put(LA, last_activity_schema()); import(_, _, _) -> pass. transform_options(Opts) -> lists:foldl(fun transform_options/2, [], Opts). transform_options({node_start, {_, _, _} = Now}, Opts) -> ?WARNING_MSG("Old 'node_start' format detected. This is still supported " "but it is better to fix your config.", []), [{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]. ejabberd-16.01/src/ejabberd_riak.erl0000644000232200023220000004435512645157216017710 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Alexey Shchepin %%% @doc %%% Interface for Riak database %%% @end %%% 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 %%% 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_riak). -behaviour(gen_server). %% API -export([start_link/4, 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, count/1, delete_by_index/3]). %% For debugging -export([get_tables/0]). %% map/reduce exports -export([map_key/3]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("ejabberd.hrl"). -include("logger.hrl"). -record(state, {pid = self() :: pid()}). -type index() :: {binary(), any()}. -type index_info() :: [{i, any()} | {'2i', [index()]}]. %% The `record_schema()' is just a tuple: %% {record_info(fields, some_record), #some_record{}} -type record_schema() :: {[atom()], tuple()}. %% The `index_info()' is used in put/delete functions: %% `i' defines a primary index, `` '2i' '' defines secondary indexes. %% There must be only one primary index. If `i' is not specified, %% the first element of the record is assumed as a primary index, %% i.e. `i' = element(2, Record). -export_types([index_info/0]). %%%=================================================================== %%% API %%%=================================================================== %% @private start_link(Num, Server, Port, _StartInterval) -> gen_server:start_link({local, get_proc(Num)}, ?MODULE, [Server, Port], []). %% @private is_connected() -> catch riakc_pb_socket:is_connected(get_random_pid()). %% @private get_proc(I) -> jlib:binary_to_atom( iolist_to_binary( [atom_to_list(?MODULE), $_, integer_to_list(I)])). -spec make_bucket(atom()) -> binary(). %% @doc Makes a bucket from a table name %% @private make_bucket(Table) -> erlang:atom_to_binary(Table, utf8). -spec put(tuple(), record_schema()) -> ok | {error, any()}. %% @equiv put(Record, []) put(Record, RecFields) -> ?MODULE:put(Record, RecFields, []). -spec put(tuple(), record_schema(), index_info()) -> ok | {error, any()}. %% @doc Stores a record `Rec' with indexes described in ``IndexInfo'' put(Rec, RecSchema, IndexInfo) -> Key = encode_key(proplists:get_value(i, IndexInfo, element(2, Rec))), SecIdxs = [encode_index_key(K, V) || {K, V} <- proplists:get_value('2i', IndexInfo, [])], Table = element(1, Rec), Value = encode_record(Rec, RecSchema), case put_raw(Table, Key, Value, SecIdxs) of ok -> ok; {error, _} = Error -> log_error(Error, put, [{record, Rec}, {index_info, IndexInfo}]), Error end. put_raw(Table, Key, Value, Indexes) -> Bucket = make_bucket(Table), Obj = riakc_obj:new(Bucket, Key, Value, "application/x-erlang-term"), Obj1 = if Indexes /= [] -> MetaData = dict:store(<<"index">>, Indexes, dict:new()), riakc_obj:update_metadata(Obj, MetaData); true -> Obj end, catch riakc_pb_socket:put(get_random_pid(), Obj1). get_object_raw(Table, Key) -> Bucket = make_bucket(Table), catch riakc_pb_socket:get(get_random_pid(), Bucket, Key). -spec get(atom(), record_schema()) -> {ok, [any()]} | {error, any()}. %% @doc Returns all objects from table `Table' get(Table, RecSchema) -> Bucket = make_bucket(Table), case catch riakc_pb_socket:mapred( get_random_pid(), Bucket, [{map, {modfun, riak_kv_mapreduce, map_object_value}, none, true}]) of {ok, [{_, Objs}]} -> {ok, lists:flatmap( fun(Obj) -> case catch decode_record(Obj, RecSchema) of {'EXIT', _} -> Error = {error, make_invalid_object(Obj)}, log_error(Error, get, [{table, Table}]), []; Term -> [Term] end end, Objs)}; {ok, []} -> {ok, []}; {error, notfound} -> {ok, []}; {error, _} = Error -> Error end. -spec get(atom(), record_schema(), any()) -> {ok, any()} | {error, any()}. %% @doc Reads record by `Key' from table `Table' get(Table, RecSchema, Key) -> case get_raw(Table, encode_key(Key)) of {ok, Val} -> case catch decode_record(Val, RecSchema) of {'EXIT', _} -> Error = {error, make_invalid_object(Val)}, log_error(Error, get, [{table, Table}, {key, Key}]), {error, notfound}; Term -> {ok, Term} end; {error, _} = Error -> log_error(Error, get, [{table, Table}, {key, Key}]), Error end. -spec get_by_index(atom(), record_schema(), binary(), any()) -> {ok, [any()]} | {error, any()}. %% @doc Reads records by `Index' and value `Key' from `Table' get_by_index(Table, RecSchema, Index, Key) -> {NewIndex, NewKey} = encode_index_key(Index, Key), case get_by_index_raw(Table, NewIndex, NewKey) of {ok, Vals} -> {ok, lists:flatmap( fun(Val) -> case catch decode_record(Val, RecSchema) of {'EXIT', _} -> Error = {error, make_invalid_object(Val)}, log_error(Error, get_by_index, [{table, Table}, {index, Index}, {key, Key}]), []; Term -> [Term] end end, Vals)}; {error, notfound} -> {ok, []}; {error, _} = Error -> log_error(Error, get_by_index, [{table, Table}, {index, Index}, {key, Key}]), Error end. -spec get_by_index_range(atom(), record_schema(), binary(), any(), any()) -> {ok, [any()]} | {error, any()}. %% @doc Reads records by `Index' in the range `FromKey'..`ToKey' from `Table' get_by_index_range(Table, RecSchema, Index, FromKey, ToKey) -> {NewIndex, NewFromKey} = encode_index_key(Index, FromKey), {NewIndex, NewToKey} = encode_index_key(Index, ToKey), case get_by_index_range_raw(Table, NewIndex, NewFromKey, NewToKey) of {ok, Vals} -> {ok, lists:flatmap( fun(Val) -> case catch decode_record(Val, RecSchema) of {'EXIT', _} -> Error = {error, make_invalid_object(Val)}, log_error(Error, get_by_index_range, [{table, Table}, {index, Index}, {start_key, FromKey}, {end_key, ToKey}]), []; Term -> [Term] end end, Vals)}; {error, notfound} -> {ok, []}; {error, _} = Error -> log_error(Error, get_by_index_range, [{table, Table}, {index, Index}, {start_key, FromKey}, {end_key, ToKey}]), Error end. get_raw(Table, Key) -> case get_object_raw(Table, Key) of {ok, Obj} -> {ok, riakc_obj:get_value(Obj)}; {error, _} = Error -> Error end. -spec get_keys(atom()) -> {ok, [any()]} | {error, any()}. %% @doc Returns a list of index values get_keys(Table) -> Bucket = make_bucket(Table), case catch riakc_pb_socket:mapred( get_random_pid(), Bucket, [{map, {modfun, ?MODULE, map_key}, none, true}]) of {ok, [{_, Keys}]} -> {ok, Keys}; {ok, []} -> {ok, []}; {error, _} = Error -> log_error(Error, get_keys, [{table, Table}]), Error end. -spec get_keys_by_index(atom(), binary(), any()) -> {ok, [any()]} | {error, any()}. %% @doc Returns a list of primary keys of objects indexed by `Key'. get_keys_by_index(Table, Index, Key) -> {NewIndex, NewKey} = encode_index_key(Index, Key), Bucket = make_bucket(Table), case catch riakc_pb_socket:mapred( get_random_pid(), {index, Bucket, NewIndex, NewKey}, [{map, {modfun, ?MODULE, map_key}, none, true}]) of {ok, [{_, Keys}]} -> {ok, Keys}; {ok, []} -> {ok, []}; {error, _} = Error -> log_error(Error, get_keys_by_index, [{table, Table}, {index, Index}, {key, Key}]), Error end. %% @hidden get_tables() -> catch riakc_pb_socket:list_buckets(get_random_pid()). get_by_index_raw(Table, Index, Key) -> Bucket = make_bucket(Table), case riakc_pb_socket:mapred( get_random_pid(), {index, Bucket, Index, Key}, [{map, {modfun, riak_kv_mapreduce, map_object_value}, none, true}]) of {ok, [{_, Objs}]} -> {ok, Objs}; {ok, []} -> {ok, []}; {error, _} = Error -> Error end. get_by_index_range_raw(Table, Index, FromKey, ToKey) -> Bucket = make_bucket(Table), case catch riakc_pb_socket:mapred( get_random_pid(), {index, Bucket, Index, FromKey, ToKey}, [{map, {modfun, riak_kv_mapreduce, map_object_value}, none, true}]) of {ok, [{_, Objs}]} -> {ok, Objs}; {ok, []} -> {ok, []}; {error, _} = Error -> Error end. -spec count(atom()) -> {ok, non_neg_integer()} | {error, any()}. %% @doc Returns the number of objects in the `Table' count(Table) -> Bucket = make_bucket(Table), case catch riakc_pb_socket:mapred( get_random_pid(), Bucket, [{reduce, {modfun, riak_kv_mapreduce, reduce_count_inputs}, none, true}]) of {ok, [{_, [Cnt]}]} -> {ok, Cnt}; {error, _} = Error -> log_error(Error, count, [{table, Table}]), Error end. -spec count_by_index(atom(), binary(), any()) -> {ok, non_neg_integer()} | {error, any()}. %% @doc Returns the number of objects in the `Table' by index count_by_index(Tab, Index, Key) -> {NewIndex, NewKey} = encode_index_key(Index, Key), case count_by_index_raw(Tab, NewIndex, NewKey) of {ok, Cnt} -> {ok, Cnt}; {error, notfound} -> {ok, 0}; {error, _} = Error -> log_error(Error, count_by_index, [{table, Tab}, {index, Index}, {key, Key}]), Error end. count_by_index_raw(Table, Index, Key) -> Bucket = make_bucket(Table), case catch riakc_pb_socket:mapred( get_random_pid(), {index, Bucket, Index, Key}, [{reduce, {modfun, riak_kv_mapreduce, reduce_count_inputs}, none, true}]) of {ok, [{_, [Cnt]}]} -> {ok, Cnt}; {error, _} = Error -> Error end. -spec delete(tuple() | atom()) -> ok | {error, any()}. %% @doc Same as delete(T, []) when T is record. %% Or deletes all elements from table if T is atom. delete(Rec) when is_tuple(Rec) -> delete(Rec, []); delete(Table) when is_atom(Table) -> try {ok, Keys} = ?MODULE:get_keys(Table), lists:foreach( fun(K) -> ok = delete(Table, K) end, Keys) catch _:{badmatch, Err} -> Err end. -spec delete(tuple() | atom(), index_info() | any()) -> ok | {error, any()}. %% @doc Delete an object delete(Rec, Opts) when is_tuple(Rec) -> Table = element(1, Rec), Key = proplists:get_value(i, Opts, element(2, Rec)), delete(Table, Key); delete(Table, Key) when is_atom(Table) -> case delete_raw(Table, encode_key(Key)) of ok -> ok; Err -> log_error(Err, delete, [{table, Table}, {key, Key}]), Err end. delete_raw(Table, Key) -> Bucket = make_bucket(Table), catch riakc_pb_socket:delete(get_random_pid(), Bucket, Key). -spec delete_by_index(atom(), binary(), any()) -> ok | {error, any()}. %% @doc Deletes objects by index delete_by_index(Table, Index, Key) -> try {ok, Keys} = get_keys_by_index(Table, Index, Key), lists:foreach( fun(K) -> ok = delete(Table, K) end, Keys) catch _:{badmatch, Err} -> Err end. %%%=================================================================== %%% map/reduce functions %%%=================================================================== %% @private map_key(Obj, _, _) -> [case riak_object:key(Obj) of <<"b_", B/binary>> -> B; <<"i_", B/binary>> -> list_to_integer(binary_to_list(B)); B -> erlang:binary_to_term(B) end]. %%%=================================================================== %%% gen_server API %%%=================================================================== %% @private init([Server, Port]) -> case riakc_pb_socket:start( Server, Port, [auto_reconnect]) of {ok, Pid} -> erlang:monitor(process, Pid), {ok, #state{pid = Pid}}; Err -> {stop, Err} end. %% @private handle_call(get_pid, _From, #state{pid = Pid} = State) -> {reply, {ok, Pid}, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. %% @private handle_cast(_Msg, State) -> {noreply, State}. %% @private handle_info({'DOWN', _MonitorRef, _Type, _Object, _Info}, State) -> {stop, normal, State}; handle_info(_Info, State) -> ?ERROR_MSG("unexpected info: ~p", [_Info]), {noreply, State}. %% @private terminate(_Reason, _State) -> ok. %% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. %%%=================================================================== %%% Internal functions %%%=================================================================== encode_index_key(Idx, Key) when is_integer(Key) -> {<>, Key}; encode_index_key(Idx, Key) -> {<>, encode_key(Key)}. encode_key(Bin) when is_binary(Bin) -> <<"b_", Bin/binary>>; encode_key(Int) when is_integer(Int) -> <<"i_", (list_to_binary(integer_to_list(Int)))/binary>>; encode_key(Term) -> erlang:term_to_binary(Term). log_error({error, notfound}, _, _) -> ok; log_error({error, Why} = Err, Function, Opts) -> Txt = lists:map( fun({table, Table}) -> io_lib:fwrite("** Table: ~p~n", [Table]); ({key, Key}) -> io_lib:fwrite("** Key: ~p~n", [Key]); ({index, Index}) -> io_lib:fwrite("** Index = ~p~n", [Index]); ({start_key, Key}) -> io_lib:fwrite("** Start Key: ~p~n", [Key]); ({end_key, Key}) -> io_lib:fwrite("** End Key: ~p~n", [Key]); ({record, Rec}) -> io_lib:fwrite("** Record = ~p~n", [Rec]); ({index_info, IdxInfo}) -> io_lib:fwrite("** Index info = ~p~n", [IdxInfo]); (_) -> "" end, Opts), ErrTxt = if is_binary(Why) -> io_lib:fwrite("** Error: ~s", [Why]); true -> io_lib:fwrite("** Error: ~p", [Err]) end, ?ERROR_MSG("database error:~n** Function: ~p~n~s~s", [Function, Txt, ErrTxt]); log_error(_, _, _) -> ok. make_invalid_object(Val) -> list_to_binary(io_lib:fwrite("Invalid object: ~p", [Val])). get_random_pid() -> PoolPid = ejabberd_riak_sup:get_random_pid(), case catch gen_server:call(PoolPid, get_pid) of {ok, Pid} -> Pid; {'EXIT', {timeout, _}} -> throw({error, timeout}); {'EXIT', Err} -> throw({error, Err}) end. encode_record(Rec, {Fields, DefRec}) -> term_to_binary(encode_record(Rec, Fields, DefRec, 2)). encode_record(Rec, [FieldName|Fields], DefRec, Pos) -> Value = element(Pos, Rec), DefValue = element(Pos, DefRec), if Value == DefValue -> encode_record(Rec, Fields, DefRec, Pos+1); true -> [{FieldName, Value}|encode_record(Rec, Fields, DefRec, Pos+1)] end; encode_record(_, [], _, _) -> []. decode_record(Bin, {Fields, DefRec}) -> decode_record(binary_to_term(Bin), Fields, DefRec, 2). decode_record(KeyVals, [FieldName|Fields], Rec, Pos) -> case lists:keyfind(FieldName, 1, KeyVals) of {_, Value} -> NewRec = setelement(Pos, Rec, Value), decode_record(KeyVals, Fields, NewRec, Pos+1); false -> decode_record(KeyVals, Fields, Rec, Pos+1) end; decode_record(_, [], Rec, _) -> Rec. ejabberd-16.01/src/mod_metrics.erl0000644000232200023220000001133312645157216017437 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% 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(jid:nameprep(Server), remove_user). register_user(_User, Server) -> push(jid: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. ejabberd-16.01/src/mod_ip_blacklist.erl0000644000232200023220000000744312645157216020440 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_ip_blacklist.erl %%% Author : Mickael Remond %%% Purpose : Download blacklists from ProcessOne %%% Created : 5 May 2008 by Mickael Remond %%% Usage : Add the following line in modules section of ejabberd.cfg: %%% {mod_ip_blacklist, []} %%% %%% %%% 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_ip_blacklist). -author('mremond@process-one.net'). -behaviour(gen_mod). %% API: -export([start/2, preinit/2, init/1, stop/1]). -export([update_bl_c2s/0]). -export([is_ip_in_c2s_blacklist/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -define(PROCNAME, ?MODULE). -define(BLC2S, <<"http://xaai.process-one.net/bl_c2s.txt">>). -define(UPDATE_INTERVAL, 6). -record(state, {timer}). %% Start once for all vhost -record(bl_c2s, {ip = <<"">> :: binary()}). start(_Host, _Opts) -> Pid = spawn(?MODULE, preinit, [self(), #state{}]), receive {ok, Pid, PreinitResult} -> PreinitResult end. preinit(Parent, State) -> Pid = self(), try register(?PROCNAME, Pid) of true -> Parent ! {ok, Pid, true}, init(State) catch error:_ -> Parent ! {ok, Pid, true} end. %% TODO: stop(_Host) -> ok. init(State) -> ets:new(bl_c2s, [named_table, public, {keypos, #bl_c2s.ip}]), update_bl_c2s(), ejabberd_hooks:add(check_bl_c2s, ?MODULE, is_ip_in_c2s_blacklist, 50), timer:apply_interval(timer:hours(?UPDATE_INTERVAL), ?MODULE, update_bl_c2s, []), loop(State). %% Remove timer when stop is received. loop(_State) -> receive stop -> ok end. %% Download blacklist file from ProcessOne XAAI %% and update the table internal table %% TODO: Support comment lines starting by % update_bl_c2s() -> ?INFO_MSG("Updating C2S Blacklist", []), case httpc:request(?BLC2S) of {ok, 200, _Headers, Body} -> IPs = str:tokens(Body, <<"\n">>), ets:delete_all_objects(bl_c2s), lists:foreach(fun (IP) -> ets:insert(bl_c2s, #bl_c2s{ip = IP}) end, IPs); {error, Reason} -> ?ERROR_MSG("Cannot download C2S blacklist file. " "Reason: ~p", [Reason]) end. %% Hook is run with: %% ejabberd_hooks:run_fold(check_bl_c2s, false, [IP]), %% Return: false: IP not blacklisted %% true: IP is blacklisted %% IPV4 IP tuple: is_ip_in_c2s_blacklist(_Val, IP, Lang) when is_tuple(IP) -> BinaryIP = jlib:ip_to_list(IP), case ets:lookup(bl_c2s, BinaryIP) of [] -> %% Not in blacklist false; [_] -> LogReason = io_lib:fwrite( "This IP address is blacklisted in ~s", [?BLC2S]), ReasonT = io_lib:fwrite( translate:translate( Lang, <<"This IP address is blacklisted in ~s">>), [?BLC2S]), {stop, {true, LogReason, ReasonT}} end; is_ip_in_c2s_blacklist(_Val, _IP, _Lang) -> false. %% TODO: %% - For now, we do not kick user already logged on a given IP after %% we update the blacklist. mod_opt_type(_) -> []. ejabberd-16.01/src/ejabberd_sm.erl0000644000232200023220000006005212645157216017371 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_sm.erl %%% Author : Alexey Shchepin %%% Purpose : Session manager %%% Created : 24 Nov 2002 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_sm). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_server). %% API -export([start/0, start_link/0, route/3, open_session/5, open_session/6, close_session/4, check_in_subscription/6, bounce_offline_message/3, disconnect_removed_user/2, get_user_resources/2, get_user_present_resources/2, set_presence/7, unset_presence/6, close_session_unset_presence/5, dirty_get_sessions_list/0, dirty_get_my_sessions_list/0, get_vh_session_list/1, get_vh_session_number/1, register_iq_handler/4, register_iq_handler/5, unregister_iq_handler/2, force_update_presence/1, connected_users/0, connected_users_number/0, user_resources/2, kick_user/2, get_session_pid/3, get_user_info/3, get_user_ip/3, get_max_user_sessions/2, get_all_pids/0, is_existing_resource/3 ]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_commands.hrl"). -include("mod_privacy.hrl"). -include("ejabberd_sm.hrl"). -callback init() -> ok | {error, any()}. -callback set_session(#session{}) -> ok. -callback delete_session(binary(), binary(), binary(), sid()) -> {ok, #session{}} | {error, notfound}. -callback get_sessions() -> [#session{}]. -callback get_sessions(binary()) -> [#session{}]. -callback get_sessions(binary(), binary()) -> [#session{}]. -callback get_sessions(binary(), binary(), binary()) -> [#session{}]. -record(state, {}). %% default value for the maximum number of user connections -define(MAX_USER_SESSIONS, infinity). %%==================================================================== %% API %%==================================================================== -export_type([sid/0]). start() -> ChildSpec = {?MODULE, {?MODULE, start_link, []}, transient, 1000, worker, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec). start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). -spec route(jid(), jid(), xmlel() | broadcast()) -> ok. route(From, To, Packet) -> case catch do_route(From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p~nwhen processing: ~p", [Reason, {From, To, Packet}]); _ -> ok end. -spec open_session(sid(), binary(), binary(), binary(), prio(), info()) -> ok. 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 = jid:make(User, Server, Resource), ejabberd_hooks:run(sm_register_connection_hook, JID#jid.lserver, [SID, JID, Info]). -spec open_session(sid(), binary(), binary(), binary(), info()) -> ok. open_session(SID, User, Server, Resource, Info) -> open_session(SID, User, Server, Resource, undefined, 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), Info = case Mod:delete_session(LUser, LServer, LResource, SID) of {ok, #session{info = I}} -> I; {error, notfound} -> [] end, JID = jid:make(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; false -> {stop, false} end. -spec bounce_offline_message(jid(), jid(), xmlel()) -> stop. bounce_offline_message(From, To, Packet) -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err), stop. -spec disconnect_removed_user(binary(), binary()) -> ok. disconnect_removed_user(User, Server) -> ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>), jid:make(User, Server, <<"">>), {broadcast, {exit, <<"User removed">>}}). get_user_resources(User, 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)]. -spec get_user_present_resources(binary(), binary()) -> [tuple()]. get_user_present_resources(LUser, LServer) -> Mod = get_sm_backend(), Ss = Mod:get_sessions(LUser, LServer), [{S#session.priority, element(3, S#session.usr)} || S <- clean_session_list(Ss), is_integer(S#session.priority)]. -spec get_user_ip(binary(), binary(), binary()) -> ip(). get_user_ip(User, Server, 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 [] -> undefined; Ss -> Session = lists:max(Ss), proplists:get_value(ip, Session#session.info) end. -spec get_user_info(binary(), binary(), binary()) -> info() | offline. get_user_info(User, Server, 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 [] -> offline; Ss -> Session = lists:max(Ss), Node = node(element(2, Session#session.sid)), Conn = proplists:get_value(conn, Session#session.info), IP = proplists:get_value(ip, Session#session.info), [{node, Node}, {conn, Conn}, {ip, IP}] end. -spec set_presence(sid(), binary(), binary(), binary(), prio(), xmlel(), info()) -> ok. set_presence(SID, User, Server, Resource, Priority, Presence, Info) -> set_session(SID, User, Server, Resource, Priority, Info), ejabberd_hooks:run(set_presence_hook, jid:nameprep(Server), [User, Server, Resource, Presence]). -spec unset_presence(sid(), binary(), binary(), binary(), binary(), info()) -> ok. unset_presence(SID, User, Server, Resource, Status, Info) -> set_session(SID, User, Server, Resource, undefined, Info), ejabberd_hooks:run(unset_presence_hook, jid:nameprep(Server), [User, Server, Resource, Status]). -spec close_session_unset_presence(sid(), binary(), binary(), binary(), binary()) -> ok. close_session_unset_presence(SID, User, Server, Resource, Status) -> close_session(SID, User, Server, Resource), ejabberd_hooks:run(unset_presence_hook, jid:nameprep(Server), [User, Server, Resource, Status]). -spec get_session_pid(binary(), binary(), binary()) -> none | pid(). get_session_pid(User, Server, 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; _ -> none end. -spec dirty_get_sessions_list() -> [ljid()]. 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()]. -spec get_vh_session_list(binary()) -> [ljid()]. get_vh_session_list(Server) -> LServer = jid:nameprep(Server), Mod = get_sm_backend(), [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()]. -spec get_vh_session_number(binary()) -> non_neg_integer(). get_vh_session_number(Server) -> LServer = jid: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}. -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}. -spec unregister_iq_handler(binary(), binary()) -> any(). unregister_iq_handler(Host, XMLNS) -> ejabberd_sm ! {unregister_iq_handler, Host, XMLNS}. %%==================================================================== %% gen_server callbacks %%==================================================================== init([]) -> Mod = get_sm_backend(), Mod:init(), ets:new(sm_iqtable, [named_table]), lists:foreach( fun(Host) -> ejabberd_hooks:add(roster_in_subscription, Host, ejabberd_sm, check_in_subscription, 20), ejabberd_hooks:add(offline_message_hook, Host, ejabberd_sm, bounce_offline_message, 100), ejabberd_hooks:add(remove_user, Host, ejabberd_sm, disconnect_removed_user, 100) end, ?MYHOSTS), ejabberd_commands:register_commands(commands()), {ok, #state{}}. 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(From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p~nwhen processing: ~p", [Reason, {From, To, Packet}]); _ -> ok end, {noreply, State}; handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) -> ets:insert(sm_iqtable, {{XMLNS, Host}, Module, Function}), {noreply, State}; handle_info({register_iq_handler, Host, XMLNS, Module, Function, Opts}, State) -> ets:insert(sm_iqtable, {{XMLNS, Host}, Module, Function, Opts}), {noreply, State}; handle_info({unregister_iq_handler, Host, XMLNS}, State) -> case ets:lookup(sm_iqtable, {XMLNS, Host}) of [{_, Module, Function, Opts}] -> gen_iq_handler:stop_iq_handler(Module, Function, Opts); _ -> ok end, ets:delete(sm_iqtable, {XMLNS, Host}), {noreply, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ejabberd_commands:unregister_commands(commands()), ok. 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 = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), US = {LUser, LServer}, USR = {LUser, LServer, LResource}, Mod = get_sm_backend(), Mod:set_session(#session{sid = SID, usr = USR, us = US, priority = Priority, info = Info}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% do_route(From, To, {broadcast, _} = Packet) -> case To#jid.lresource of <<"">> -> lists:foreach(fun(R) -> do_route(From, jid:replace_resource(To, R), Packet) end, get_user_resources(To#jid.user, To#jid.server)); _ -> {U, S, R} = jid:tolower(To), Mod = get_sm_backend(), case Mod:get_sessions(U, S, R) of [] -> ?DEBUG("packet dropped~n", []); Ss -> Session = lists:max(Ss), Pid = element(2, Session#session.sid), ?DEBUG("sending to process ~p~n", [Pid]), Pid ! {route, From, To, Packet} end end; do_route(From, To, #xmlel{} = Packet) -> ?DEBUG("session manager~n\tfrom ~p~n\tto ~p~n\tpacket " "~P~n", [From, To, Packet, 8]), #jid{user = User, server = Server, luser = LUser, lserver = LServer, lresource = LResource} = To, #xmlel{name = Name, attrs = Attrs} = Packet, case LResource of <<"">> -> case Name of <<"presence">> -> {Pass, _Subsc} = case xml:get_attr_s(<<"type">>, Attrs) of <<"subscribe">> -> Reason = xml:get_path_s(Packet, [{elem, <<"status">>}, cdata]), {is_privacy_allow(From, To, Packet) andalso ejabberd_hooks:run_fold(roster_in_subscription, LServer, false, [User, Server, From, subscribe, Reason]), true}; <<"subscribed">> -> {is_privacy_allow(From, To, Packet) andalso ejabberd_hooks:run_fold(roster_in_subscription, LServer, false, [User, Server, From, subscribed, <<"">>]), true}; <<"unsubscribe">> -> {is_privacy_allow(From, To, Packet) andalso ejabberd_hooks:run_fold(roster_in_subscription, LServer, false, [User, Server, From, unsubscribe, <<"">>]), true}; <<"unsubscribed">> -> {is_privacy_allow(From, To, Packet) andalso ejabberd_hooks:run_fold(roster_in_subscription, LServer, false, [User, Server, From, unsubscribed, <<"">>]), true}; _ -> {true, false} end, if Pass -> PResources = get_user_present_resources(LUser, LServer), lists:foreach(fun ({_, R}) -> do_route(From, jid:replace_resource(To, R), Packet) end, PResources); true -> ok end; <<"message">> -> case xml:get_attr_s(<<"type">>, Attrs) of <<"chat">> -> route_message(From, To, Packet, chat); <<"headline">> -> route_message(From, To, Packet, headline); <<"error">> -> ok; <<"groupchat">> -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err); _ -> route_message(From, To, Packet, normal) end; <<"iq">> -> process_iq(From, To, Packet); _ -> ok end; _ -> Mod = get_sm_backend(), case Mod:get_sessions(LUser, LServer, LResource) of [] -> case Name of <<"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, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err) end; <<"iq">> -> 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; _ -> ?DEBUG("packet dropped~n", []) end; Ss -> Session = lists:max(Ss), Pid = element(2, Session#session.sid), ?DEBUG("sending to process ~p~n", [Pid]), Pid ! {route, From, To, Packet} end end. %% The default list applies to the user as a whole, %% and is processed if there is no active list set %% for the target session/resource to which a stanza is addressed, %% or if there are no current sessions for the user. is_privacy_allow(From, To, Packet) -> User = To#jid.user, Server = To#jid.server, PrivacyList = ejabberd_hooks:run_fold(privacy_get_user_list, Server, #userlist{}, [User, Server]), is_privacy_allow(From, To, Packet, PrivacyList). %% Check if privacy rules allow this delivery %% Function copied from ejabberd_c2s.erl is_privacy_allow(From, To, Packet, PrivacyList) -> User = To#jid.user, Server = To#jid.server, allow == ejabberd_hooks:run_fold(privacy_check_packet, Server, allow, [User, Server, PrivacyList, {From, To, Packet}, in]). route_message(From, To, Packet, Type) -> LUser = To#jid.luser, LServer = To#jid.lserver, PrioRes = get_user_present_resources(LUser, LServer), case catch lists:max(PrioRes) of {Priority, _R} when is_integer(Priority), Priority >= 0 -> lists:foreach(fun ({P, R}) when P == Priority; (P >= 0) and (Type == headline) -> LResource = jid:resourceprep(R), Mod = get_sm_backend(), case Mod:get_sessions(LUser, LServer, LResource) of [] -> ok; % Race condition Ss -> Session = lists:max(Ss), Pid = element(2, Session#session.sid), ?DEBUG("sending to process ~p~n", [Pid]), Pid ! {route, From, To, Packet} end; %% Ignore other priority: ({_Prio, _Res}) -> ok end, PrioRes); _ -> case Type of headline -> ok; _ -> case ejabberd_auth:is_user_exists(LUser, LServer) of true -> case is_privacy_allow(From, To, Packet) of true -> ejabberd_hooks:run(offline_message_hook, LServer, [From, To, Packet]); false -> ok end; _ -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err) end end end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% clean_session_list(Ss) -> clean_session_list(lists:keysort(#session.usr, Ss), []). clean_session_list([], Res) -> Res; clean_session_list([S], Res) -> [S | Res]; clean_session_list([S1, S2 | Rest], Res) -> if S1#session.usr == S2#session.usr -> if S1#session.sid > S2#session.sid -> clean_session_list([S1 | Rest], Res); true -> clean_session_list([S2 | Rest], Res) end; true -> clean_session_list([S2 | Rest], [S1 | Res]) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% On new session, check if some existing connections need to be replace check_for_sessions_to_replace(User, Server, Resource) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), check_existing_resources(LUser, LServer, LResource), check_max_sessions(LUser, LServer). check_existing_resources(LUser, LServer, LResource) -> SIDs = get_resource_sessions(LUser, LServer, LResource), if SIDs == [] -> ok; true -> MaxSID = lists:max(SIDs), lists:foreach(fun ({_, Pid} = S) when S /= MaxSID -> Pid ! replaced; (_) -> ok end, SIDs) end. -spec is_existing_resource(binary(), binary(), binary()) -> boolean(). is_existing_resource(LUser, LServer, LResource) -> [] /= get_resource_sessions(LUser, LServer, LResource). get_resource_sessions(User, Server, 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)]. check_max_sessions(LUser, LServer) -> Mod = get_sm_backend(), SIDs = [S#session.sid || S <- Mod:get_sessions(LUser, LServer)], MaxSessions = get_max_user_sessions(LUser, LServer), if length(SIDs) =< MaxSessions -> ok; true -> {_, Pid} = lists:min(SIDs), Pid ! replaced end. %% Get the user_max_session setting %% This option defines the max number of time a given users are allowed to %% log in %% Defaults to infinity get_max_user_sessions(LUser, Host) -> case acl:match_rule(Host, max_user_sessions, jid:make(LUser, Host, <<"">>)) of Max when is_integer(Max) -> Max; infinity -> infinity; _ -> ?MAX_USER_SESSIONS end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% process_iq(From, To, Packet) -> IQ = jlib:iq_query_info(Packet), case IQ of #iq{xmlns = XMLNS} -> Host = To#jid.lserver, case ets:lookup(sm_iqtable, {XMLNS, Host}) of [{_, Module, Function}] -> ResIQ = Module:Function(From, To, IQ), if ResIQ /= ignore -> ejabberd_router:route(To, From, jlib:iq_to_xml(ResIQ)); true -> ok end; [{_, Module, Function, Opts}] -> gen_iq_handler:handle(Host, Module, Function, Opts, From, To, IQ); [] -> Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err) end; reply -> ok; _ -> Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), ejabberd_router:route(To, From, Err), ok end. -spec force_update_presence({binary(), binary()}) -> any(). 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, LServer} end, Ss). -spec get_sm_backend() -> module(). get_sm_backend() -> DBType = ejabberd_config:get_option(sm_db_type, fun(mnesia) -> mnesia; (internal) -> mnesia; (odbc) -> odbc; (redis) -> redis end, mnesia), list_to_atom("ejabberd_sm_" ++ atom_to_list(DBType)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% ejabberd commands 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 = [], result = {resources, {list, {resource, string}}}}, #ejabberd_commands{name = kick_user, tags = [session], desc = "Disconnect user's active sessions", module = ?MODULE, function = kick_user, args = [{user, binary}, {host, binary}], result = {num_resources, integer}}]. -spec connected_users() -> [binary()]. connected_users() -> USRs = dirty_get_sessions_list(), SUSRs = lists:sort(USRs), lists:map(fun ({U, S, R}) -> <> end, SUSRs). connected_users_number() -> length(dirty_get_sessions_list()). user_resources(User, Server) -> Resources = get_user_resources(User, Server), lists:sort(Resources). kick_user(User, Server) -> Resources = get_user_resources(User, Server), lists:foreach( fun(Resource) -> PID = get_session_pid(User, Server, Resource), 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]. ejabberd-16.01/src/ELDAPv3.asn1db0000644000232200023220000010613412645157216016622 0ustar debalancedebalancecXM $bWLAƒhhd compresseddfalsehdmemoryb½hdownergd nonode@nohostwhdheirdnonehdnamed asn1_ELDAPv3hdsizea9hdnoded nonode@nohosthd named_tabledfalsehdtypedsethdkeyposahd protectiond protectedhd major_versionahd minor_versionahd extended_infojÓbWLAƒhdMatchingRuleAssertionhdtypedefdtrueaÐdMatchingRuleAssertionhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaÑd matchingRulehdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajahd ComponentTypeaÒdtypehdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajahd ComponentTypeaÓd matchValuehdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnod mandatorylhdCONTEXTajahd ComponentTypeaÔd dnAttributeshdtypelhdtagdCONTEXTadIMPLICITajdBOOLEANjjdnohdDEFAULTdfalselhdCONTEXTajajjjdnoÕbWLAƒhdAttributeValueAssertionhdtypedefdtruea?dAttributeValueAssertionhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypea@d attributeDeschdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaAdassertionValuehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajajjjdnoŽbWLAƒhdAttributeDescriptionhdtypedefdtruea0dAttributeDescriptionhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnobbWLAƒhdEXTERNALhdtypedefdfalsed undefineddEXTERNALhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTyped undefinedddirect-referencehdtypejdOBJECT IDENTIFIERjjdnodOPTIONALlhd UNIVERSALajd undefinedhd ComponentTyped undefineddindirect-referencehdtypejdINTEGERjjdnodOPTIONALlhd UNIVERSALajd undefinedhd ComponentTyped undefinedddata-value-descriptorhdtypejdObjectDescriptorjjdnodOPTIONALd undefinedd undefinedhd ComponentTyped undefineddencodinghdtypejhdCHOICElhd ComponentTyped undefineddsingle-ASN1-typehdtypelhdtagdCONTEXTadEXPLICITa jdANYjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTyped undefinedd octet-alignedhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTyped undefinedd arbitraryhdtypelhdtagdCONTEXTadIMPLICITajhd BIT STRINGjjjdnod mandatorylhdCONTEXTajd undefinedjjjdnod mandatoryd undefinedd undefinedjjjdno¿bWLAƒhdReferralhdtypedefdtruea†dReferralhdtypelhdtagd UNIVERSALadIMPLICITa jhd SEQUENCE OFhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnojjdnotbWLAƒhdLDAPURLhdtypedefdtrueaˆdLDAPURLhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdno‚bWLAƒhdAttributeValuehdtypedefdtruea=dAttributeValuehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdno¼bWLAƒhdExtendedResponsehdtypedefdtruebdExtendedResponsehdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaLd resultCodehdtypelhdtagd UNIVERSALa dIMPLICITajhd ENUMERATEDl'hdsuccessahdoperationsErrorahd protocolErrorahdtimeLimitExceededahdsizeLimitExceededahd compareFalseahd compareTrueahdauthMethodNotSupportedahdstrongAuthRequiredahdreferrala hdadminLimitExceededa hdunavailableCriticalExtensiona hdconfidentialityRequireda hdsaslBindInProgressahdnoSuchAttributeahdundefinedAttributeTypeahdinappropriateMatchingahdconstraintViolationahdattributeOrValueExistsahdinvalidAttributeSyntaxahd noSuchObjecta hd aliasProblema!hdinvalidDNSyntaxa"hdaliasDereferencingProblema$hdinappropriateAuthenticationa0hdinvalidCredentialsa1hdinsufficientAccessRightsa2hdbusya3hd unavailablea4hdunwillingToPerforma5hd loopDetecta6hdnamingViolationa@hdobjectClassViolationaAhdnotAllowedOnNonLeafaBhdnotAllowedOnRDNaChdentryAlreadyExistsaDhdobjectClassModsProhibitedaEhdaffectsMultipleDSAsaGhdotheraPjjjdnod mandatorylhd UNIVERSALa jahd ComponentTypea‚d matchedDNhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaƒd errorMessagehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypea„dreferralhdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferencea„dELDAPv3dReferraljjdnodOPTIONALlhdCONTEXTajahd ComponentTypebd responseNamehdtypelhdtagdCONTEXTa dIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTa jahd ComponentTypebdresponsehdtypelhdtagdCONTEXTa dIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTa jajjjdno²bWLAƒhdModifyDNResponsehdtypedefdtrueb dModifyDNResponsehdtypelhdtagd APPLICATIONa dIMPLICITa jhdExternaltypereferenceb dELDAPv3d LDAPResultjjdno€bWLAƒhd AttributeTypehdtypedefdtruea.d AttributeTypehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnoZbWLAƒhdPasswdModifyRequestValuehdtypedefdtrueb#dPasswdModifyRequestValuehdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeb$d userIdentityhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajahd ComponentTypeb%d oldPasswdhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajahd ComponentTypeb&d newPasswdhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajajjjdno°bWLAƒhdCompareResponsehdtypedefdtruebdCompareResponsehdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferencebdELDAPv3d LDAPResultjjdno|bWLAƒhd DelRequesthdtypedefdtrueaÿd DelRequesthdtypelhdtagd APPLICATIONa dIMPLICITajd OCTET STRINGjjdno;bWLAƒhd AttributeListhdtypedefdtrueaùd AttributeListhdtypelhdtagd UNIVERSALadIMPLICITa jhd SEQUENCE OFhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaúdtypehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaûdvalshdtypelhdtagd UNIVERSALadIMPLICITa jhdSET OFhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnojjdnod mandatorylhd UNIVERSALajajjjdnojjdnoâbWLAƒhd AddRequesthdtypedefdtrueaõd AddRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaödentryhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypea÷d attributeshdtypelhdtagd UNIVERSALadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d AttributeListjjdnod mandatorylhd UNIVERSALajajjjdnoqbWLAƒhd BindRequesthdtypedefdtruea‘d BindRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypea’dversionhdtypelhdtagd UNIVERSALadIMPLICITajdINTEGERlhd ValueRangehaajjdnod mandatorylhd UNIVERSALajahd ComponentTypea“dnamehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypea”dauthenticationhdtypejhdExternaltypereferenced undefineddELDAPv3dAuthenticationChoicejjdnod mandatorylhdCONTEXTahdCONTEXTajajjjdnoßbWLAƒhdAttributeDescriptionListhdtypedefdtruea:dAttributeDescriptionListhdtypelhdtagd UNIVERSALadIMPLICITa jhd SEQUENCE OFhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnojjdno…bWLAƒhdSubstringFilterhdtypedefdtrueaÈdSubstringFilterhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaÉdtypehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaËd substringshdtypelhdtagd UNIVERSALadIMPLICITa jhd SEQUENCE OFhdtypejhdCHOICElhd ComponentTypeaÌdinitialhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÍdanyhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÎdfinalhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnod mandatorylhdCONTEXTajd undefinedjjjdnojjdnod mandatorylhd UNIVERSALajajjjdnozbWLAƒhd LDAPStringhdtypedefdtruea&d LDAPStringhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnoEbWLAƒhdPasswdModifyResponseValuehdtypedefdtrueb(dPasswdModifyResponseValuehdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeb)d genPasswdhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajajjjdno¶bWLAƒhdSearchResultDonehdtypedefdtrueaädSearchResultDonehdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d LDAPResultjjdno‚bWLAƒhdAssertionValuehdtypedefdtrueaCdAssertionValuehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnoŸbWLAƒhdAbandonRequesthdtypedefdtruebdAbandonRequesthdtypelhdtagd APPLICATIONadIMPLICITajdINTEGERlhd ValueRangehabÿÿÿjjdnoïbWLAƒhdCompareRequesthdtypedefdtruebdCompareRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypebdentryhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypebdavahdtypelhdtagd UNIVERSALadIMPLICITa jhdExternaltypereferencebdELDAPv3dAttributeValueAssertionjjdnod mandatorylhd UNIVERSALajajjjdnozbWLAƒhd UnbindRequesthdtypedefdtruea©d UnbindRequesthdtypelhdtagd APPLICATIONadIMPLICITajdNULLjjdno‚bWLAƒhd SearchRequesthdtypedefdtruea«d SearchRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypea¬d baseObjecthdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypea­dscopehdtypelhdtagd UNIVERSALa dIMPLICITajhd ENUMERATEDlhd baseObjectahd singleLevelahd wholeSubtreeajjjdnod mandatorylhd UNIVERSALa jahd ComponentTypea±d derefAliaseshdtypelhdtagd UNIVERSALa dIMPLICITajhd ENUMERATEDlhdneverDerefAliasesahdderefInSearchingahdderefFindingBaseObjahd derefAlwaysajjjdnod mandatorylhd UNIVERSALa jahd ComponentTypea¶d sizeLimithdtypelhdtagd UNIVERSALadIMPLICITajdINTEGERlhd ValueRangehabÿÿÿjjdnod mandatorylhd UNIVERSALajahd ComponentTypea·d timeLimithdtypelhdtagd UNIVERSALadIMPLICITajdINTEGERlhd ValueRangehabÿÿÿjjdnod mandatorylhd UNIVERSALajahd ComponentTypea¸d typesOnlyhdtypelhdtagd UNIVERSALadIMPLICITajdBOOLEANjjdnod mandatorylhd UNIVERSALajahd ComponentTypea¹dfilterhdtypejhdExternaltypereferenced undefineddELDAPv3dFilterjjdnod mandatoryl hdCONTEXTahdCONTEXTahdCONTEXTahdCONTEXTahdCONTEXTahdCONTEXTahdCONTEXTahdCONTEXTahdCONTEXTahdCONTEXTa jahd ComponentTypeaºd attributeshdtypelhdtagd UNIVERSALadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dAttributeDescriptionListjjdnod mandatorylhd UNIVERSALajajjjdnoZbWLAƒhdTYPE-IDENTIFIERhdclassdefdtrued undefineddTYPE-IDENTIFIERhd objectclasslhdfixedtypevaluefielddidhdtypehdtagd UNIVERSALadIMPLICITadOBJECT IDENTIFIERjjdnodUNIQUEd MANDATORYhd typefielddTyped MANDATORYjhd WITH SYNTAXlhdtypefieldreferencedTyped IDENTIFIEDdBYhdvaluefieldreferencedidjAbWLAƒhdControlhdtypedefdtrueaŒdControlhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypead controlTypehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaŽd criticalityhdtypelhdtagd UNIVERSALadIMPLICITajdBOOLEANjjdnohdDEFAULTdfalselhd UNIVERSALajahd ComponentTypead controlValuehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhd UNIVERSALajajjjdnoübWLAƒhdSearchResultEntryhdtypedefdtrueaÚdSearchResultEntryhdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaÛd objectNamehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaÜd attributeshdtypelhdtagd UNIVERSALadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dPartialAttributeListjjdnod mandatorylhd UNIVERSALajajjjdnoHbWLAƒhd EMBEDDED PDVhdtypedefdfalsed undefinedd EMBEDDED PDVhdtypelhdtagd UNIVERSALa dIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTyped undefineddidentificationhdtypejhdCHOICElhd ComponentTyped undefineddsyntaxeshdtypejhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTyped undefineddabstracthdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddtransferhdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedjjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddsyntaxhdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddpresentation-context-idhdtypejdINTEGERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddcontext-negotiationhdtypejhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTyped undefineddpresentation-context-idhdtypejdINTEGERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddtransfer-syntaxhdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedjjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddtransfer-syntaxhdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddfixedhdtypejdNULLjjdnod mandatoryd undefinedd undefinedjjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefinedd data-valuehdtypejd OCTET STRINGjjdnod mandatoryd undefinedd undefinedjjjdno¨bWLAƒhdModifyResponsehdtypedefdtrueaódModifyResponsehdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenceaódELDAPv3d LDAPResultjjdnoÛbWLAƒhdSearchResultReferencehdtypedefdtrueaâdSearchResultReferencehdtypelhdtagd APPLICATIONadIMPLICITa jhd SEQUENCE OFhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnojjdno¨bWLAƒhd DelResponsehdtypedefdtruebd DelResponsehdtypelhdtagd APPLICATIONa dIMPLICITa jhdExternaltypereferencebdELDAPv3d LDAPResultjjdno¢bWLAƒhd AddResponsehdtypedefdtrueaýd AddResponsehdtypelhdtagd APPLICATIONa dIMPLICITa jhdExternaltypereferenceaýdELDAPv3d LDAPResultjjdno2bWLAƒhd BindResponsehdtypedefdtrueaŸd BindResponsehdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaLd resultCodehdtypelhdtagd UNIVERSALa dIMPLICITajhd ENUMERATEDl'hdsuccessahdoperationsErrorahd protocolErrorahdtimeLimitExceededahdsizeLimitExceededahd compareFalseahd compareTrueahdauthMethodNotSupportedahdstrongAuthRequiredahdreferrala hdadminLimitExceededa hdunavailableCriticalExtensiona hdconfidentialityRequireda hdsaslBindInProgressahdnoSuchAttributeahdundefinedAttributeTypeahdinappropriateMatchingahdconstraintViolationahdattributeOrValueExistsahdinvalidAttributeSyntaxahd noSuchObjecta hd aliasProblema!hdinvalidDNSyntaxa"hdaliasDereferencingProblema$hdinappropriateAuthenticationa0hdinvalidCredentialsa1hdinsufficientAccessRightsa2hdbusya3hd unavailablea4hdunwillingToPerforma5hd loopDetecta6hdnamingViolationa@hdobjectClassViolationaAhdnotAllowedOnNonLeafaBhdnotAllowedOnRDNaChdentryAlreadyExistsaDhdobjectClassModsProhibitedaEhdaffectsMultipleDSAsaGhdotheraPjjjdnod mandatorylhd UNIVERSALa jahd ComponentTypea‚d matchedDNhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaƒd errorMessagehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypea„dreferralhdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dReferraljjdnodOPTIONALlhdCONTEXTajahd ComponentTypea§dserverSaslCredshdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajajjjdno·bWLAƒhdAuthenticationChoicehdtypedefdtruea–dAuthenticationChoicehdtypejhdCHOICElhd ComponentTypea—dsimplehdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypea™dsaslhdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dSaslCredentialsjjdnod mandatorylhdCONTEXTajd undefinedjjjdnoêbWLAƒhd AttributehdtypedefdtrueaEd Attributehdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaFdtypehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaGdvalshdtypelhdtagd UNIVERSALadIMPLICITa jhdSET OFhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnojjdnod mandatorylhd UNIVERSALajajjjdnoIbWLAƒhdPartialAttributeListhdtypedefdtrueaÞdPartialAttributeListhdtypelhdtagd UNIVERSALadIMPLICITa jhd SEQUENCE OFhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaßdtypehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaàdvalshdtypelhdtagd UNIVERSALadIMPLICITa jhdSET OFhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnojjdnod mandatorylhd UNIVERSALajajjjdnojjdno•bWLAƒhd LDAPResulthdtypedefdtrueaKd LDAPResulthdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaLd resultCodehdtypelhdtagd UNIVERSALa dIMPLICITajhd ENUMERATEDl'hdsuccessahdoperationsErrorahd protocolErrorahdtimeLimitExceededahdsizeLimitExceededahd compareFalseahd compareTrueahdauthMethodNotSupportedahdstrongAuthRequiredahdreferrala hdadminLimitExceededa hdunavailableCriticalExtensiona hdconfidentialityRequireda hdsaslBindInProgressahdnoSuchAttributeahdundefinedAttributeTypeahdinappropriateMatchingahdconstraintViolationahdattributeOrValueExistsahdinvalidAttributeSyntaxahd noSuchObjecta hd aliasProblema!hdinvalidDNSyntaxa"hdaliasDereferencingProblema$hdinappropriateAuthenticationa0hdinvalidCredentialsa1hdinsufficientAccessRightsa2hdbusya3hd unavailablea4hdunwillingToPerforma5hd loopDetecta6hdnamingViolationa@hdobjectClassViolationaAhdnotAllowedOnNonLeafaBhdnotAllowedOnRDNaChdentryAlreadyExistsaDhdobjectClassModsProhibitedaEhdaffectsMultipleDSAsaGhdotheraPjjjdnod mandatorylhd UNIVERSALa jahd ComponentTypea‚d matchedDNhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaƒd errorMessagehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypea„dreferralhdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferencea„dELDAPv3dReferraljjdnodOPTIONALlhdCONTEXTajajjjdnoUbWLAƒhdmaxInthdvaluedefdtruea$dmaxInthdtypejdINTEGERjjdnobÿÿÿdELDAPv3£bWLAƒhd ModifyRequesthdtypedefdtrueaæd ModifyRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaçdobjecthdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeaèd modificationhdtypelhdtagd UNIVERSALadIMPLICITa jhd SEQUENCE OFhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaéd operationhdtypelhdtagd UNIVERSALa dIMPLICITajhd ENUMERATEDlhdaddahddeleteahdreplaceajjjdnod mandatorylhd UNIVERSALa jahd ComponentTypeaíd modificationhdtypelhdtagd UNIVERSALadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dAttributeTypeAndValuesjjdnod mandatorylhd UNIVERSALajajjjdnojjdnod mandatorylhd UNIVERSALajajjjdnobWLAƒhd MessageIDhdtypedefdtruea"d MessageIDhdtypelhdtagd UNIVERSALadIMPLICITajdINTEGERlhd ValueRangehabÿÿÿjjdnobWLAƒhdAttributeTypeAndValueshdtypedefdtrueaïdAttributeTypeAndValueshdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaðdtypehdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypeañdvalshdtypelhdtagd UNIVERSALadIMPLICITa jhdSET OFhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnojjdnod mandatorylhd UNIVERSALajajjjdnoêbWLAƒhdControlshdtypedefdtrueaŠdControlshdtypelhdtagd UNIVERSALadIMPLICITa jhd SEQUENCE OFhdtypelhdtagd UNIVERSALadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dControljjdnojjdno½bWLAƒhdSaslCredentialshdtypedefdtruea›dSaslCredentialshdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypeaœd mechanismhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypead credentialshdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhd UNIVERSALajajjjdno‚bWLAƒhdRelativeLDAPDNhdtypedefdtruea,dRelativeLDAPDNhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnorbWLAƒhdLDAPDNhdtypedefdtruea*dLDAPDNhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnobWLAƒhdABSTRACT-SYNTAXhdclassdefdtrued undefineddABSTRACT-SYNTAXhd objectclasslhdfixedtypevaluefielddidhdtypehdtagd UNIVERSALadIMPLICITadOBJECT IDENTIFIERjjdnodUNIQUEd MANDATORYhd typefielddTyped MANDATORYhdfixedtypevaluefielddpropertyhdtypehdtagd UNIVERSALadIMPLICITahd BIT STRINGjjjdnod undefinedhdDEFAULTkjhd WITH SYNTAXlhdtypefieldreferencedTyped IDENTIFIEDdBYhdvaluefieldreferencedidldHASdPROPERTYhdvaluefieldreferencedpropertyjjRbWLAƒhdCHARACTER STRINGhdtypedefdfalsed undefineddCHARACTER STRINGhdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTyped undefineddidentificationhdtypejhdCHOICElhd ComponentTyped undefineddsyntaxeshdtypejhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTyped undefineddabstracthdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddtransferhdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedjjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddsyntaxhdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddpresentation-context-idhdtypejdINTEGERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddcontext-negotiationhdtypejhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTyped undefineddpresentation-context-idhdtypejdINTEGERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddtransfer-syntaxhdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedjjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddtransfer-syntaxhdtypejdOBJECT IDENTIFIERjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefineddfixedhdtypejdNULLjjdnod mandatoryd undefinedd undefinedjjjdnod mandatoryd undefinedd undefinedhd ComponentTyped undefinedd string-valuehdtypejd OCTET STRINGjjdnod mandatoryd undefinedd undefinedjjjdnoabWLAƒhd LDAPMessagehdtypedefdtruea d LDAPMessagehdtypelhdtagd UNIVERSALadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypea d messageIDhdtypelhdtagd UNIVERSALadIMPLICITajdINTEGERlhd ValueRangehabÿÿÿjjdnod mandatorylhd UNIVERSALajahd ComponentTypea d protocolOphdtypejhdCHOICElhd ComponentTypea d bindRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d BindRequestjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypea d bindResponsehdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d BindResponsejjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead unbindRequesthdtypelhdtagd APPLICATIONadIMPLICITajdNULLjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead searchRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d SearchRequestjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypeadsearchResEntryhdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dSearchResultEntryjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead searchResDonehdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dSearchResultDonejjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead searchResRefhdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dSearchResultReferencejjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead modifyRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d ModifyRequestjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypeadmodifyResponsehdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dModifyResponsejjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead addRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d AddRequestjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead addResponsehdtypelhdtagd APPLICATIONa dIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d AddResponsejjdnod mandatorylhd APPLICATIONa jd undefinedhd ComponentTypead delRequesthdtypelhdtagd APPLICATIONa dIMPLICITajd OCTET STRINGjjdnod mandatorylhd APPLICATIONa jd undefinedhd ComponentTypead delResponsehdtypelhdtagd APPLICATIONa dIMPLICITa jhdExternaltypereferenced undefineddELDAPv3d DelResponsejjdnod mandatorylhd APPLICATIONa jd undefinedhd ComponentTypead modDNRequesthdtypelhdtagd APPLICATIONa dIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dModifyDNRequestjjdnod mandatorylhd APPLICATIONa jd undefinedhd ComponentTypead modDNResponsehdtypelhdtagd APPLICATIONa dIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dModifyDNResponsejjdnod mandatorylhd APPLICATIONa jd undefinedhd ComponentTypeadcompareRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dCompareRequestjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypeadcompareResponsehdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dCompareResponsejjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypeadabandonRequesthdtypelhdtagd APPLICATIONadIMPLICITajdINTEGERlhd ValueRangehabÿÿÿjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead extendedReqhdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dExtendedRequestjjdnod mandatorylhd APPLICATIONajd undefinedhd ComponentTypead extendedResphdtypelhdtagd APPLICATIONadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dExtendedResponsejjdnod mandatorylhd APPLICATIONajd undefinedjjjdnod mandatorylhd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONa hd APPLICATIONa hd APPLICATIONa hd APPLICATIONa hd APPLICATIONa hd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONahd APPLICATIONajahd ComponentTypea dcontrolshdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dControlsjjdnodOPTIONALlhdCONTEXTajajjjdnoÈbWLAƒhdMODULEh dmoduleadELDAPv3jdIMPLICIThdexportsdallhdimportsjd undefinedhl1d LDAPMessaged MessageIDd LDAPStringdLDAPOIDdLDAPDNdRelativeLDAPDNd AttributeTypedAttributeDescriptiondAttributeDescriptionListdAttributeValuedAttributeValueAssertiondAssertionValued AttributedMatchingRuleIdd LDAPResultdReferraldLDAPURLdControlsdControld BindRequestdAuthenticationChoicedSaslCredentialsd BindResponsed UnbindRequestd SearchRequestdFilterdSubstringFilterdMatchingRuleAssertiondSearchResultEntrydPartialAttributeListdSearchResultReferencedSearchResultDoned ModifyRequestdAttributeTypeAndValuesdModifyResponsed AddRequestd AttributeListd AddResponsed DelRequestd DelResponsedModifyDNRequestdModifyDNResponsedCompareRequestdCompareResponsedAbandonRequestdExtendedRequestdExtendedResponsedPasswdModifyRequestValuedPasswdModifyResponseValuejldmaxIntdpasswdModifyOIDjjjjjÃbWLAƒhdExtendedRequesthdtypedefdtruebdExtendedRequesthdtypelhdtagd APPLICATIONadIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypebd requestNamehdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnod mandatorylhdCONTEXTajahd ComponentTypebd requestValuehdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajajjjdnoÙbWLAƒhdModifyDNRequesthdtypedefdtruebdModifyDNRequesthdtypelhdtagd APPLICATIONa dIMPLICITa jhdSEQUENCEdfalsedfalsed undefinedlhd ComponentTypebdentryhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypebdnewrdnhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnod mandatorylhd UNIVERSALajahd ComponentTypebd deleteoldrdnhdtypelhdtagd UNIVERSALadIMPLICITajdBOOLEANjjdnod mandatorylhd UNIVERSALajahd ComponentTypebd newSuperiorhdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnodOPTIONALlhdCONTEXTajajjjdno‚bWLAƒhdMatchingRuleIdhdtypedefdtrueaIdMatchingRuleIdhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdnotbWLAƒhdLDAPOIDhdtypedefdtruea(dLDAPOIDhdtypelhdtagd UNIVERSALadIMPLICITajd OCTET STRINGjjdno¨bWLAƒhdpasswdModifyOIDhdvaluedefdtrueb!dpasswdModifyOIDhdtypejhdExternaltypereferenceb!dELDAPv3dLDAPOIDjjdnok1.3.6.1.4.1.4203.1.11.1dELDAPv3ÛbWLAƒhdFilterhdtypedefdtruea¼dFilterhdtypejhdCHOICEl hd ComponentTypea½dandhdtypelhdtagdCONTEXTadIMPLICITa jhdSET OFhdtypejhdExternaltypereferenced undefineddELDAPv3dFilterjjdnojjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypea¾dorhdtypelhdtagdCONTEXTadIMPLICITa jhdSET OFhdtypejhdExternaltypereferencea¾dELDAPv3dFilterjjdnojjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypea¿dnothdtypelhdtagdCONTEXTadEXPLICITa jhdExternaltypereferencea¿dELDAPv3dFilterjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÀd equalityMatchhdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dAttributeValueAssertionjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÁd substringshdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dSubstringFilterjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÂdgreaterOrEqualhdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferenceaÂdELDAPv3dAttributeValueAssertionjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÃd lessOrEqualhdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferenceaÃdELDAPv3dAttributeValueAssertionjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÄdpresenthdtypelhdtagdCONTEXTadIMPLICITajd OCTET STRINGjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÅd approxMatchhdtypelhdtagdCONTEXTadIMPLICITa jhdExternaltypereferenceaÅdELDAPv3dAttributeValueAssertionjjdnod mandatorylhdCONTEXTajd undefinedhd ComponentTypeaÆdextensibleMatchhdtypelhdtagdCONTEXTa dIMPLICITa jhdExternaltypereferenced undefineddELDAPv3dMatchingRuleAssertionjjdnod mandatorylhdCONTEXTa jd undefinedjjjdnoejabberd-16.01/src/nodetree_tree.erl0000644000232200023220000001370412645157216017762 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : nodetree_tree.erl %%% Author : Christophe Romain %%% Purpose : Standard node tree plugin %%% Created : 1 Dec 2007 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. %%% %%%---------------------------------------------------------------------- %%% @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 %%% as a developer basis and reference to build its own custom pubsub node tree %%% types.

%%%

PubSub node tree plugins are using the {@link gen_nodetree} 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(nodetree_tree). -behaviour(gen_pubsub_nodetree). -author('christophe.romain@process-one.net'). -include_lib("stdlib/include/qlc.hrl"). -include("pubsub.hrl"). -include("jlib.hrl"). -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]). init(_Host, _ServerHost, _Options) -> mnesia:create_table(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 end, %% mnesia:transform_table(pubsub_state, ignore, StatesFields) ok. terminate(_Host, _ServerHost) -> ok. options() -> [{virtual_tree, false}]. set_node(Node) when is_record(Node, pubsub_node) -> mnesia:write(Node). get_node(Host, Node, _From) -> get_node(Host, Node). 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. 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) -> mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, _ = '_'}). get_parentnodes(_Host, _Node, _From) -> []. %% @doc

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

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. get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). get_subnodes(Host, <<>>) -> Q = qlc:q([N || #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)]), qlc:e(Q). get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, 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. create_node(Host, Node, Type, Owner, Options, Parents) -> BJID = jid:tolower(jid:remove_resource(Owner)), 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. 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. ejabberd-16.01/src/mod_client_state.erl0000644000232200023220000000710012645157216020444 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_client_state.erl %%% Author : Holger Weiss %%% Purpose : Filter stanzas sent to inactive clients (XEP-0352) %%% Created : 11 Sep 2014 by Holger Weiss %%% %%% %%% ejabberd, Copyright (C) 2014-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_client_state). -author('holger@zedat.fu-berlin.de'). -protocol({xep, 85, '2.1'}). -protocol({xep, 352, '0.1'}). -behavior(gen_mod). -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"). -include("jlib.hrl"). start(Host, Opts) -> QueuePresence = gen_mod:get_opt(queue_presence, Opts, fun(true) -> true; (false) -> false end, true), DropChatStates = gen_mod:get_opt(drop_chat_states, Opts, fun(true) -> true; (false) -> false end, true), if QueuePresence; DropChatStates -> ejabberd_hooks:add(c2s_post_auth_features, Host, ?MODULE, add_stream_feature, 50), if QueuePresence -> ejabberd_hooks:add(csi_filter_stanza, Host, ?MODULE, filter_presence, 50); true -> ok end, if DropChatStates -> ejabberd_hooks:add(csi_filter_stanza, Host, ?MODULE, filter_chat_states, 50); true -> ok end; true -> ok end, ok. stop(Host) -> ejabberd_hooks:delete(csi_filter_stanza, Host, ?MODULE, filter_presence, 50), ejabberd_hooks:delete(csi_filter_stanza, Host, ?MODULE, filter_chat_states, 50), ejabberd_hooks:delete(c2s_post_auth_features, Host, ?MODULE, add_stream_feature, 50), ok. add_stream_feature(Features, _Host) -> Feature = #xmlel{name = <<"csi">>, attrs = [{<<"xmlns">>, ?NS_CLIENT_STATE}], children = []}, [Feature | Features]. filter_presence(_Action, #xmlel{name = <<"presence">>, attrs = Attrs}) -> case xml:get_attr(<<"type">>, Attrs) of {value, Type} when Type /= <<"unavailable">> -> ?DEBUG("Got important presence stanza", []), {stop, send}; _ -> ?DEBUG("Got availability presence stanza", []), {stop, queue} end; filter_presence(Action, _Stanza) -> Action. filter_chat_states(_Action, #xmlel{name = <<"message">>} = Stanza) -> case jlib:is_standalone_chat_state(Stanza) of true -> ?DEBUG("Got standalone chat state notification", []), {stop, drop}; false -> ?DEBUG("Got 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]. ejabberd-16.01/src/ejabberd_commands_doc.erl0000644000232200023220000005754312645157216021413 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% 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() -> " ". ejabberd-16.01/src/node_club.erl0000644000232200023220000001310712645157216017065 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_club.erl %%% Author : Christophe Romain %%% Purpose : %%% Created : 1 Dec 2007 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_club). -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]). 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, 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_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). ejabberd-16.01/src/ejabberd_stun.erl0000644000232200023220000000660112645157216017743 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov %%% @copyright (C) 2014, Evgeny Khramtsov %%% @doc %%% %%% @end %%% Created : 8 May 2014 by Evgeny 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., %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%%------------------------------------------------------------------- -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]). -include("ejabberd.hrl"). -include("logger.hrl"). %%%=================================================================== %%% API %%%=================================================================== tcp_init(Socket, Opts) -> ejabberd:start_app(p1_stun), stun:tcp_init(Socket, prepare_turn_opts(Opts)). udp_init(Socket, Opts) -> ejabberd:start_app(p1_stun), stun:udp_init(Socket, prepare_turn_opts(Opts)). udp_recv(Socket, Addr, Port, Packet, Opts) -> stun:udp_recv(Socket, Addr, Port, Packet, Opts). start(Opaque, Opts) -> stun:start(Opaque, Opts). socket_type() -> raw. %%%=================================================================== %%% Internal functions %%%=================================================================== prepare_turn_opts(Opts) -> UseTurn = proplists:get_bool(use_turn, Opts), prepare_turn_opts(Opts, UseTurn). prepare_turn_opts(Opts, _UseTurn = false) -> Opts; prepare_turn_opts(Opts, _UseTurn = true) -> NumberOfMyHosts = length(?MYHOSTS), case proplists:get_value(turn_ip, Opts) of undefined -> ?WARNING_MSG("option 'turn_ip' is undefined, " "more likely the TURN relay won't be working " "properly", []); _ -> ok end, AuthFun = fun ejabberd_auth:get_password_s/2, Shaper = gen_mod:get_opt(shaper, Opts, fun(S) when is_atom(S) -> S end, none), AuthType = gen_mod:get_opt(auth_type, Opts, fun(anonymous) -> anonymous; (user) -> user end, user), Realm = case gen_mod:get_opt(auth_realm, Opts, fun iolist_to_binary/1) of undefined when AuthType == user -> if NumberOfMyHosts > 1 -> ?WARNING_MSG("you have several virtual " "hosts configured, but option " "'auth_realm' is undefined and " "'auth_type' is set to 'user', " "more likely the TURN relay won't " "be working properly. Using ~s as " "a fallback", [?MYNAME]); true -> ok end, [{auth_realm, ?MYNAME}]; _ -> [] end, MaxRate = shaper:get_max_rate(Shaper), Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} | lists:keydelete(shaper, 1, Opts)]. ejabberd-16.01/src/mod_privacy.erl0000644000232200023220000012302212645157216017445 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_privacy.erl %%% Author : Alexey Shchepin %%% Purpose : jabber:iq:privacy support %%% Created : 21 Jul 2003 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(mod_privacy). -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, 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]). -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, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("mod_privacy.hrl"). privacy_schema() -> {record_info(fields, privacy), #privacy{}}. start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, one_queue), case gen_mod:db_type(Host, Opts) of mnesia -> mnesia:create_table(privacy, [{disc_copies, [node()]}, {attributes, record_info(fields, privacy)}]), update_table(); _ -> ok end, mod_disco:register_feature(Host, ?NS_PRIVACY), ejabberd_hooks:add(privacy_iq_get, Host, ?MODULE, process_iq_get, 50), ejabberd_hooks:add(privacy_iq_set, Host, ?MODULE, process_iq_set, 50), ejabberd_hooks:add(privacy_get_user_list, Host, ?MODULE, get_user_list, 50), ejabberd_hooks:add(privacy_check_packet, Host, ?MODULE, check_packet, 50), ejabberd_hooks:add(privacy_updated_list, Host, ?MODULE, updated_list, 50), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY, ?MODULE, process_iq, IQDisc). stop(Host) -> mod_disco:unregister_feature(Host, ?NS_PRIVACY), ejabberd_hooks:delete(privacy_iq_get, Host, ?MODULE, process_iq_get, 50), ejabberd_hooks:delete(privacy_iq_set, Host, ?MODULE, process_iq_set, 50), ejabberd_hooks:delete(privacy_get_user_list, Host, ?MODULE, get_user_list, 50), ejabberd_hooks:delete(privacy_check_packet, Host, ?MODULE, check_packet, 50), ejabberd_hooks:delete(privacy_updated_list, Host, ?MODULE, updated_list, 50), ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY). process_iq(_From, _To, IQ) -> SubEl = IQ#iq.sub_el, IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. 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 [] -> process_lists_get(LUser, LServer, Active); [#xmlel{name = Name, attrs = Attrs}] -> case Name of <<"list">> -> ListName = xml:get_attr(<<"name">>, Attrs), process_list_get(LUser, LServer, ListName); _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end. process_lists_get(LUser, LServer, Active) -> case process_lists_get(LUser, LServer, Active, gen_mod:db_type(LServer, ?MODULE)) of error -> {error, ?ERR_INTERNAL_SERVER_ERROR}; {_Default, []} -> {result, [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_PRIVACY}], children = []}]}; {Default, LItems} -> DItems = case Default of none -> LItems; _ -> [#xmlel{name = <<"default">>, attrs = [{<<"name">>, Default}], children = []} | LItems] end, ADItems = case Active of none -> DItems; _ -> [#xmlel{name = <<"active">>, attrs = [{<<"name">>, Active}], children = []} | DItems] end, {result, [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_PRIVACY}], children = ADItems}]} end. process_lists_get(LUser, LServer, _Active, mnesia) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of {'EXIT', _Reason} -> error; [] -> {none, []}; [#privacy{default = Default, lists = Lists}] -> LItems = lists:map(fun ({N, _}) -> #xmlel{name = <<"list">>, attrs = [{<<"name">>, N}], children = []} end, Lists), {Default, LItems} end; process_lists_get(LUser, LServer, _Active, riak) -> case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{default = Default, lists = Lists}} -> LItems = lists:map(fun ({N, _}) -> #xmlel{name = <<"list">>, attrs = [{<<"name">>, N}], children = []} end, Lists), {Default, LItems}; {error, notfound} -> {none, []}; {error, _} -> 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; _ -> none end, case catch sql_get_privacy_list_names(LUser, LServer) of {selected, [<<"name">>], Names} -> LItems = lists:map(fun ([N]) -> #xmlel{name = <<"list">>, attrs = [{<<"name">>, N}], children = []} end, Names), {Default, LItems}; _ -> error end. process_list_get(LUser, LServer, {value, Name}) -> case process_list_get(LUser, LServer, Name, gen_mod:db_type(LServer, ?MODULE)) of error -> {error, ?ERR_INTERNAL_SERVER_ERROR}; not_found -> {error, ?ERR_ITEM_NOT_FOUND}; Items -> LItems = lists:map(fun item_to_xml/1, Items), {result, [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_PRIVACY}], children = [#xmlel{name = <<"list">>, attrs = [{<<"name">>, Name}], children = LItems}]}]} end; process_list_get(_LUser, _LServer, false) -> {error, ?ERR_BAD_REQUEST}. process_list_get(LUser, LServer, Name, mnesia) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of {'EXIT', _Reason} -> error; [] -> not_found; [#privacy{lists = Lists}] -> case lists:keysearch(Name, 1, Lists) of {value, {_, List}} -> List; _ -> not_found end end; process_list_get(LUser, LServer, Name, riak) -> case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{lists = Lists}} -> case lists:keysearch(Name, 1, Lists) of {value, {_, List}} -> List; _ -> not_found end; {error, notfound} -> not_found; {error, _} -> 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} -> lists:flatmap(fun raw_to_item/1, RItems); _ -> error end; _ -> error end. item_to_xml(Item) -> Attrs1 = [{<<"action">>, action_to_list(Item#listitem.action)}, {<<"order">>, order_to_list(Item#listitem.order)}], Attrs2 = case Item#listitem.type of none -> Attrs1; Type -> [{<<"type">>, type_to_list(Item#listitem.type)}, {<<"value">>, value_to_list(Type, Item#listitem.value)} | Attrs1] end, SubEls = case Item#listitem.match_all of true -> []; false -> SE1 = case Item#listitem.match_iq of true -> [#xmlel{name = <<"iq">>, attrs = [], children = []}]; false -> [] end, SE2 = case Item#listitem.match_message of true -> [#xmlel{name = <<"message">>, attrs = [], children = []} | SE1]; false -> SE1 end, SE3 = case Item#listitem.match_presence_in of true -> [#xmlel{name = <<"presence-in">>, attrs = [], children = []} | SE2]; false -> SE2 end, SE4 = case Item#listitem.match_presence_out of true -> [#xmlel{name = <<"presence-out">>, attrs = [], children = []} | SE3]; false -> SE3 end, SE4 end, #xmlel{name = <<"item">>, attrs = Attrs2, children = SubEls}. action_to_list(Action) -> case Action of allow -> <<"allow">>; deny -> <<"deny">> end. order_to_list(Order) -> iolist_to_binary(integer_to_list(Order)). type_to_list(Type) -> case Type of jid -> <<"jid">>; group -> <<"group">>; subscription -> <<"subscription">> end. value_to_list(Type, Val) -> case Type of jid -> jid:to_string(Val); group -> Val; subscription -> case Val of both -> <<"both">>; to -> <<"to">>; from -> <<"from">>; none -> <<"none">> end end. list_to_action(S) -> case S of <<"allow">> -> allow; <<"deny">> -> deny end. 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 [#xmlel{name = Name, attrs = Attrs, children = SubEls}] -> ListName = xml:get_attr(<<"name">>, Attrs), case Name of <<"list">> -> process_list_set(LUser, LServer, ListName, xml:remove_cdata(SubEls)); <<"active">> -> process_active_set(LUser, LServer, ListName); <<"default">> -> process_default_set(LUser, LServer, ListName); _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end. process_default_set(LUser, LServer, Value) -> case process_default_set(LUser, LServer, Value, gen_mod:db_type(LServer, ?MODULE)) of {atomic, error} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; {atomic, not_found} -> {error, ?ERR_ITEM_NOT_FOUND}; {atomic, ok} -> {result, []}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end. process_default_set(LUser, LServer, {value, Name}, mnesia) -> F = fun () -> case mnesia:read({privacy, {LUser, LServer}}) of [] -> not_found; [#privacy{lists = Lists} = P] -> case lists:keymember(Name, 1, Lists) of true -> mnesia:write(P#privacy{default = Name, lists = Lists}), ok; false -> not_found end end end, mnesia:transaction(F); process_default_set(LUser, LServer, {value, Name}, riak) -> {atomic, case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{lists = Lists} = P} -> case lists:keymember(Name, 1, Lists) of true -> ejabberd_riak:put(P#privacy{default = Name, lists = Lists}, privacy_schema()); false -> not_found end; {error, _} -> not_found end}; 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 true -> sql_set_default_privacy_list(LUser, Name), ok; false -> not_found end end end, odbc_queries:sql_transaction(LServer, F); process_default_set(LUser, LServer, false, mnesia) -> F = fun () -> case mnesia:read({privacy, {LUser, LServer}}) of [] -> ok; [R] -> mnesia:write(R#privacy{default = none}) end end, mnesia:transaction(F); process_default_set(LUser, LServer, false, riak) -> {atomic, case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, R} -> ejabberd_riak:put(R#privacy{default = none}, privacy_schema()); {error, _} -> ok end}; process_default_set(LUser, LServer, false, odbc) -> case catch sql_unset_default_privacy_list(LUser, LServer) of {'EXIT', _Reason} -> {atomic, error}; {error, _Reason} -> {atomic, error}; _ -> {atomic, ok} end. process_active_set(LUser, LServer, {value, Name}) -> case process_active_set(LUser, LServer, Name, gen_mod:db_type(LServer, ?MODULE)) of error -> {error, ?ERR_ITEM_NOT_FOUND}; Items -> NeedDb = is_list_needdb(Items), {result, [], #userlist{name = Name, list = Items, needdb = NeedDb}} end; process_active_set(_LUser, _LServer, false) -> {result, [], #userlist{}}. process_active_set(LUser, LServer, Name, mnesia) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of [] -> error; [#privacy{lists = Lists}] -> case lists:keysearch(Name, 1, Lists) of {value, {_, List}} -> List; false -> error end end; process_active_set(LUser, LServer, Name, riak) -> case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{lists = Lists}} -> case lists:keysearch(Name, 1, Lists) of {value, {_, List}} -> List; false -> error end; {error, _} -> 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} -> lists:flatmap(fun raw_to_item/1, RItems); _ -> error end; _ -> error end. remove_privacy_list(LUser, LServer, Name, mnesia) -> F = fun () -> case mnesia:read({privacy, {LUser, LServer}}) of [] -> ok; [#privacy{default = Default, lists = Lists} = P] -> if Name == Default -> conflict; true -> NewLists = lists:keydelete(Name, 1, Lists), mnesia:write(P#privacy{lists = NewLists}) end end end, mnesia:transaction(F); remove_privacy_list(LUser, LServer, Name, riak) -> {atomic, case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{default = Default, lists = Lists} = P} -> if Name == Default -> conflict; true -> NewLists = lists:keydelete(Name, 1, Lists), ejabberd_riak:put(P#privacy{lists = NewLists}, privacy_schema()) end; {error, _} -> ok end}; remove_privacy_list(LUser, LServer, Name, odbc) -> F = fun () -> case sql_get_default_privacy_list_t(LUser) of {selected, [<<"name">>], []} -> sql_remove_privacy_list(LUser, Name), ok; {selected, [<<"name">>], [[Default]]} -> if Name == Default -> conflict; true -> sql_remove_privacy_list(LUser, Name), ok end end end, odbc_queries:sql_transaction(LServer, F). set_privacy_list(LUser, LServer, Name, List, mnesia) -> F = fun () -> case mnesia:wread({privacy, {LUser, LServer}}) of [] -> NewLists = [{Name, List}], mnesia:write(#privacy{us = {LUser, LServer}, lists = NewLists}); [#privacy{lists = Lists} = P] -> NewLists1 = lists:keydelete(Name, 1, Lists), NewLists = [{Name, List} | NewLists1], mnesia:write(P#privacy{lists = NewLists}) end end, mnesia:transaction(F); set_privacy_list(LUser, LServer, Name, List, riak) -> {atomic, case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{lists = Lists} = P} -> NewLists1 = lists:keydelete(Name, 1, Lists), NewLists = [{Name, List} | NewLists1], ejabberd_riak:put(P#privacy{lists = NewLists}, privacy_schema()); {error, _} -> NewLists = [{Name, List}], ejabberd_riak:put(#privacy{us = {LUser, LServer}, lists = NewLists}, privacy_schema()) end}; 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">>], []} -> sql_add_privacy_list(LUser, Name), {selected, [<<"id">>], [[I]]} = sql_get_privacy_list_id_t(LUser, Name), I; {selected, [<<"id">>], [[I]]} -> I end, sql_set_privacy_list(ID, RItems), ok end, odbc_queries:sql_transaction(LServer, F). process_list_set(LUser, LServer, {value, Name}, Els) -> case parse_items(Els) of false -> {error, ?ERR_BAD_REQUEST}; remove -> case remove_privacy_list(LUser, LServer, Name, gen_mod:db_type(LServer, ?MODULE)) of {atomic, conflict} -> {error, ?ERR_CONFLICT}; {atomic, ok} -> ejabberd_sm:route(jid:make(LUser, LServer, <<"">>), jid:make(LUser, LServer, <<"">>), {broadcast, {privacy_list, #userlist{name = Name, list = []}, Name}}), {result, []}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end; List -> case set_privacy_list(LUser, LServer, Name, List, gen_mod:db_type(LServer, ?MODULE)) of {atomic, ok} -> NeedDb = is_list_needdb(List), ejabberd_sm:route(jid:make(LUser, LServer, <<"">>), jid:make(LUser, LServer, <<"">>), {broadcast, {privacy_list, #userlist{name = Name, list = List, needdb = NeedDb}, Name}}), {result, []}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end end; process_list_set(_LUser, _LServer, false, _Els) -> {error, ?ERR_BAD_REQUEST}. parse_items([]) -> remove; parse_items(Els) -> parse_items(Els, []). parse_items([], Res) -> lists:keysort(#listitem.order, Res); 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), Action = case catch list_to_action(element(2, SAction)) of {'EXIT', _} -> false; Val -> Val end, Order = case catch jlib:binary_to_integer(element(2, SOrder)) of {'EXIT', _} -> false; IntVal -> if IntVal >= 0 -> IntVal; true -> false end end, if (Action /= false) and (Order /= false) -> I1 = #listitem{action = Action, order = Order}, I2 = case {Type, Value} of {{value, T}, {value, V}} -> case T of <<"jid">> -> case jid:from_string(V) of error -> false; JID -> I1#listitem{type = jid, value = jid:tolower(JID)} end; <<"group">> -> I1#listitem{type = group, value = V}; <<"subscription">> -> case V of <<"none">> -> I1#listitem{type = subscription, value = none}; <<"both">> -> I1#listitem{type = subscription, value = both}; <<"from">> -> I1#listitem{type = subscription, value = from}; <<"to">> -> I1#listitem{type = subscription, value = to}; _ -> false end end; {{value, _}, false} -> false; _ -> I1 end, case I2 of false -> false; _ -> case parse_matches(I2, xml:remove_cdata(SubEls)) of false -> false; I3 -> parse_items(Els, [I3 | Res]) end end; true -> false end; parse_items(_, _Res) -> false. parse_matches(Item, []) -> Item#listitem{match_all = true}; parse_matches(Item, Els) -> parse_matches1(Item, Els). parse_matches1(Item, []) -> Item; parse_matches1(Item, [#xmlel{name = <<"message">>} | Els]) -> parse_matches1(Item#listitem{match_message = true}, Els); parse_matches1(Item, [#xmlel{name = <<"iq">>} | Els]) -> parse_matches1(Item#listitem{match_iq = true}, Els); parse_matches1(Item, [#xmlel{name = <<"presence-in">>} | Els]) -> parse_matches1(Item#listitem{match_presence_in = true}, Els); parse_matches1(Item, [#xmlel{name = <<"presence-out">>} | Els]) -> parse_matches1(Item#listitem{match_presence_out = true}, Els); parse_matches1(_Item, [#xmlel{} | _Els]) -> false. is_list_needdb(Items) -> lists:any(fun (X) -> case X#listitem.type of subscription -> true; group -> true; _ -> false end end, Items). get_user_list(Acc, User, 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), #userlist{name = Default, list = Items, needdb = NeedDb}. get_user_list(_, LUser, LServer, mnesia) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of [] -> {none, []}; [#privacy{default = Default, lists = Lists}] -> case Default of none -> {none, []}; _ -> case lists:keysearch(Default, 1, Lists) of {value, {_, List}} -> {Default, List}; _ -> {none, []} end end; _ -> {none, []} end; get_user_list(_, LUser, LServer, riak) -> case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{default = Default, lists = Lists}} -> case Default of none -> {none, []}; _ -> case lists:keysearch(Default, 1, Lists) of {value, {_, List}} -> {Default, List}; _ -> {none, []} end end; {error, _} -> {none, []} end; get_user_list(_, LUser, LServer, odbc) -> case catch sql_get_default_privacy_list(LUser, LServer) of {selected, [<<"name">>], []} -> {none, []}; {selected, [<<"name">>], [[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, lists:flatmap(fun raw_to_item/1, RItems)}; _ -> {none, []} end; _ -> {none, []} end. get_user_lists(User, 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) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of [#privacy{} = P] -> {ok, P}; _ -> error end; get_user_lists(LUser, LServer, riak) -> case ejabberd_riak:get(privacy, privacy_schema(), {LUser, LServer}) of {ok, #privacy{} = P} -> {ok, P}; {error, _} -> error end; get_user_lists(LUser, LServer, odbc) -> Default = case catch sql_get_default_privacy_list(LUser, LServer) of {selected, [<<"name">>], []} -> none; {selected, [<<"name">>], [[DefName]]} -> DefName; _ -> none end, case catch sql_get_privacy_list_names(LUser, LServer) of {selected, [<<"name">>], Names} -> Lists = lists:flatmap( 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} -> [{Name, lists:flatmap(fun raw_to_item/1, RItems)}]; _ -> [] end end, Names), {ok, #privacy{default = Default, us = {LUser, LServer}, lists = Lists}}; _ -> error end. %% From is the sender, To is the destination. %% If Dir = out, User@Server is the sender account (From). %% If Dir = in, User@Server is the destination account (To). check_packet(_, _User, _Server, _UserList, {#jid{luser = <<"">>, lserver = Server} = _From, #jid{lserver = Server} = _To, _}, in) -> allow; check_packet(_, _User, _Server, _UserList, {#jid{lserver = Server} = _From, #jid{luser = <<"">>, lserver = Server} = _To, _}, out) -> allow; check_packet(_, _User, _Server, _UserList, {#jid{luser = User, lserver = Server} = _From, #jid{luser = User, lserver = Server} = _To, _}, _Dir) -> allow; check_packet(_, User, Server, #userlist{list = List, needdb = NeedDb}, {From, To, #xmlel{name = PName, attrs = Attrs}}, Dir) -> case List of [] -> allow; _ -> PType = case PName of <<"message">> -> message; <<"iq">> -> iq; <<"presence">> -> case xml:get_attr_s(<<"type">>, Attrs) of %% notification <<"">> -> presence; <<"unavailable">> -> presence; %% subscribe, subscribed, unsubscribe, %% unsubscribed, error, probe, or other _ -> other end end, PType2 = case {PType, Dir} of {message, in} -> message; {iq, in} -> iq; {presence, in} -> presence_in; {presence, out} -> presence_out; {_, _} -> other end, LJID = case Dir of in -> jid:tolower(From); out -> jid:tolower(To) end, {Subscription, Groups} = case NeedDb of true -> ejabberd_hooks:run_fold(roster_get_jid_info, jid:nameprep(Server), {none, []}, [User, Server, LJID]); false -> {[], []} end, check_packet_aux(List, PType2, LJID, Subscription, Groups) end. %% Ptype = mesage | iq | presence_in | presence_out | other check_packet_aux([], _PType, _JID, _Subscription, _Groups) -> allow; check_packet_aux([Item | List], PType, JID, Subscription, Groups) -> #listitem{type = Type, value = Value, action = Action} = Item, case is_ptype_match(Item, PType) of true -> case Type of none -> Action; _ -> case is_type_match(Type, Value, JID, Subscription, Groups) of true -> Action; false -> check_packet_aux(List, PType, JID, Subscription, Groups) end end; false -> check_packet_aux(List, PType, JID, Subscription, Groups) end. is_ptype_match(Item, PType) -> case Item#listitem.match_all of true -> true; false -> case PType of message -> Item#listitem.match_message; iq -> Item#listitem.match_iq; presence_in -> Item#listitem.match_presence_in; presence_out -> Item#listitem.match_presence_out; other -> false end end. is_type_match(Type, Value, JID, Subscription, Groups) -> case Type of jid -> case Value of {<<"">>, Server, <<"">>} -> case JID of {_, Server, _} -> true; _ -> false end; {User, Server, <<"">>} -> case JID of {User, Server, _} -> true; _ -> false end; _ -> Value == JID end; subscription -> Value == Subscription; group -> lists:member(Value, Groups) end. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). remove_user(LUser, LServer, mnesia) -> F = fun () -> mnesia:delete({privacy, {LUser, LServer}}) end, mnesia:transaction(F); remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete(privacy, {LUser, LServer})}; remove_user(LUser, LServer, odbc) -> sql_del_privacy_lists(LUser, LServer). updated_list(_, #userlist{name = OldName} = Old, #userlist{name = NewName} = New) -> if OldName == NewName -> New; true -> Old end. raw_to_item([SType, SValue, SAction, SOrder, SMatchAll, SMatchIQ, SMatchMessage, SMatchPresenceIn, SMatchPresenceOut] = Row) -> try {Type, Value} = case SType of <<"n">> -> {none, none}; <<"j">> -> case jid:from_string(SValue) of #jid{} = JID -> {jid, jid:tolower(JID)} end; <<"g">> -> {group, SValue}; <<"s">> -> case SValue of <<"none">> -> {subscription, none}; <<"both">> -> {subscription, both}; <<"from">> -> {subscription, from}; <<"to">> -> {subscription, to} end end, Action = case SAction of <<"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, match_presence_in = MatchPresenceIn, match_presence_out = MatchPresenceOut}] catch _:_ -> ?WARNING_MSG("failed to parse row: ~p", [Row]), [] end. item_to_raw(#listitem{type = Type, value = Value, action = Action, order = Order, match_all = MatchAll, match_iq = MatchIQ, match_message = MatchMessage, match_presence_in = MatchPresenceIn, match_presence_out = MatchPresenceOut}) -> {SType, SValue} = case Type of none -> {<<"n">>, <<"">>}; jid -> {<<"j">>, ejabberd_odbc:escape(jid:to_string(Value))}; group -> {<<"g">>, ejabberd_odbc:escape(Value)}; subscription -> case Value of none -> {<<"s">>, <<"none">>}; both -> {<<"s">>, <<"both">>}; from -> {<<"s">>, <<"from">>}; to -> {<<"s">>, <<"to">>} end end, SAction = case Action of 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]. sql_get_default_privacy_list(LUser, LServer) -> Username = ejabberd_odbc:escape(LUser), odbc_queries:get_default_privacy_list(LServer, Username). sql_get_default_privacy_list_t(LUser) -> Username = ejabberd_odbc:escape(LUser), odbc_queries:get_default_privacy_list_t(Username). sql_get_privacy_list_names(LUser, LServer) -> Username = ejabberd_odbc:escape(LUser), odbc_queries:get_privacy_list_names(LServer, Username). sql_get_privacy_list_names_t(LUser) -> Username = ejabberd_odbc:escape(LUser), odbc_queries:get_privacy_list_names_t(Username). 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). 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). 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). sql_get_privacy_list_data_t(LUser, Name) -> Username = ejabberd_odbc:escape(LUser), SName = ejabberd_odbc:escape(Name), odbc_queries:get_privacy_list_data_t(Username, SName). sql_get_privacy_list_data_by_id(ID, LServer) -> odbc_queries:get_privacy_list_data_by_id(LServer, ID). 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). sql_unset_default_privacy_list(LUser, LServer) -> Username = ejabberd_odbc:escape(LUser), odbc_queries:unset_default_privacy_list(LServer, Username). sql_remove_privacy_list(LUser, Name) -> Username = ejabberd_odbc:escape(LUser), SName = ejabberd_odbc:escape(Name), odbc_queries:remove_privacy_list(Username, SName). sql_add_privacy_list(LUser, Name) -> Username = ejabberd_odbc:escape(LUser), SName = ejabberd_odbc:escape(Name), odbc_queries:add_privacy_list(Username, SName). 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). update_table() -> Fields = record_info(fields, privacy), case mnesia:table_info(privacy, attributes) of Fields -> ejabberd_config:convert_table_to_binary( privacy, Fields, set, fun(#privacy{us = {U, _}}) -> U end, fun(#privacy{us = {U, S}, default = Def, lists = Lists} = R) -> NewLists = lists:map( fun({Name, Ls}) -> NewLs = lists:map( fun(#listitem{value = Val} = L) -> NewVal = case Val of {LU, LS, LR} -> {iolist_to_binary(LU), iolist_to_binary(LS), iolist_to_binary(LR)}; none -> none; both -> both; from -> from; to -> to; _ -> iolist_to_binary(Val) end, L#listitem{value = NewVal} end, Ls), {iolist_to_binary(Name), NewLs} end, Lists), NewDef = case Def of none -> none; _ -> iolist_to_binary(Def) end, NewUS = {iolist_to_binary(U), iolist_to_binary(S)}, R#privacy{us = NewUS, default = NewDef, lists = NewLists} end); _ -> ?INFO_MSG("Recreating privacy table", []), mnesia:transform_table(privacy, ignore, Fields) end. export(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]]} -> put(id, jlib:binary_to_integer(I)); _ -> put(id, 0) end, [{privacy, fun(Host, #privacy{us = {LUser, LServer}, lists = Lists, default = Default}) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), if Default /= none -> SDefault = ejabberd_odbc:escape(Default), [[<<"delete from privacy_default_list where ">>, <<"username='">>, Username, <<"';">>], [<<"insert into privacy_default_list(username, " "name) ">>, <<"values ('">>, Username, <<"', '">>, SDefault, <<"');">>]]; true -> [] end ++ lists:flatmap( fun({Name, List}) -> SName = ejabberd_odbc:escape(Name), RItems = lists:map(fun item_to_raw/1, List), ID = jlib:integer_to_binary(get_id()), [[<<"delete from privacy_list where username='">>, Username, <<"' and name='">>, SName, <<"';">>], [<<"insert into privacy_list(username, " "name, id) values ('">>, Username, <<"', '">>, SName, <<"', '">>, ID, <<"');">>], [<<"delete from privacy_list_data where " "id='">>, ID, <<"';">>]] ++ [[<<"insert into privacy_list_data(id, t, " "value, action, ord, match_all, match_iq, " "match_message, match_presence_in, " "match_presence_out) values ('">>, ID, <<"', '">>, str:join(Items, <<"', '">>), <<"');">>] || Items <- RItems] end, Lists); (_Host, _R) -> [] end}]. get_id() -> ID = get(id), put(id, ID + 1), ID + 1. import(LServer) -> [{<<"select username from privacy_list;">>, fun([LUser]) -> Default = case sql_get_default_privacy_list_t(LUser) of {selected, [<<"name">>], []} -> none; {selected, [<<"name">>], [[DefName]]} -> DefName; _ -> none end, {selected, [<<"name">>], Names} = sql_get_privacy_list_names_t(LUser), Lists = lists:flatmap( fun([Name]) -> case sql_get_privacy_list_data_t(LUser, Name) of {selected, _, RItems} -> [{Name, lists:map(fun raw_to_item/1, RItems)}]; _ -> [] end end, Names), #privacy{default = Default, us = {LUser, LServer}, lists = Lists} end}]. import(_LServer, mnesia, #privacy{} = P) -> mnesia:dirty_write(P); 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]. ejabberd-16.01/src/ejabberd_riak_sup.erl0000644000232200023220000001173112645157216020567 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_riak_sup.erl %%% Author : Alexey Shchepin %%% Purpose : Riak connections supervisor %%% Created : 29 Dec 2011 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_riak_sup). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -export([start/0, start_link/0, init/1, get_pids/0, transform_options/1, get_random_pid/0, get_random_pid/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -define(DEFAULT_POOL_SIZE, 10). -define(DEFAULT_RIAK_START_INTERVAL, 30). % 30 seconds -define(DEFAULT_RIAK_HOST, "127.0.0.1"). -define(DEFAULT_RIAK_PORT, 8087). % time to wait for the supervisor to start its child before returning % a timeout error to the request -define(CONNECT_TIMEOUT, 500). % milliseconds start() -> case lists:any( fun(Host) -> is_riak_configured(Host) end, ?MYHOSTS) of true -> ejabberd:start_app(riakc), do_start(); false -> ok end. is_riak_configured(Host) -> ServerConfigured = ejabberd_config:get_option( {riak_server, Host}, fun(_) -> true end, false), PortConfigured = ejabberd_config:get_option( {riak_port, Host}, fun(_) -> true end, false), AuthConfigured = lists:member( ejabberd_auth_riak, ejabberd_auth:auth_modules(Host)), Modules = ejabberd_config:get_option( {modules, Host}, fun(L) when is_list(L) -> L end, []), ModuleWithRiakDBConfigured = lists:any( fun({_Module, Opts}) -> gen_mod:db_type(Host, Opts) == riak end, Modules), ServerConfigured or PortConfigured or AuthConfigured or ModuleWithRiakDBConfigured. do_start() -> SupervisorName = ?MODULE, ChildSpec = {SupervisorName, {?MODULE, start_link, []}, transient, infinity, supervisor, [?MODULE]}, case supervisor:start_child(ejabberd_sup, ChildSpec) of {ok, _PID} -> ok; _Error -> ?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying...~n", [SupervisorName, _Error]), timer:sleep(5000), start() end. start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> PoolSize = get_pool_size(), StartInterval = get_start_interval(), Server = get_riak_server(), Port = get_riak_port(), {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]}, transient, 2000, worker, [?MODULE]} end, lists:seq(1, PoolSize))}}. get_start_interval() -> ejabberd_config:get_option( riak_start_interval, fun(N) when is_integer(N), N >= 1 -> N end, ?DEFAULT_RIAK_START_INTERVAL). get_pool_size() -> ejabberd_config:get_option( riak_pool_size, fun(N) when is_integer(N), N >= 1 -> N end, ?DEFAULT_POOL_SIZE). get_riak_server() -> ejabberd_config:get_option( riak_server, fun(S) -> binary_to_list(iolist_to_binary(S)) end, ?DEFAULT_RIAK_HOST). get_riak_port() -> ejabberd_config:get_option( riak_port, fun(P) when is_integer(P), P > 0, P < 65536 -> P end, ?DEFAULT_RIAK_PORT). get_pids() -> [ejabberd_riak:get_proc(I) || I <- lists:seq(1, get_pool_size())]. get_random_pid() -> get_random_pid(p1_time_compat:monotonic_time()). get_random_pid(Term) -> I = erlang:phash2(Term, get_pool_size()) + 1, ejabberd_riak:get_proc(I). transform_options(Opts) -> lists:foldl(fun transform_options/2, [], Opts). transform_options({riak_server, {S, P}}, Opts) -> [{riak_server, S}, {riak_port, P}|Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. 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]. ejabberd-16.01/src/pubsub_migrate.erl0000644000232200023220000003175712645157216020156 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% 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., %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%---------------------------------------------------------------------- -module(pubsub_migrate). -include("pubsub.hrl"). -include("logger.hrl"). -export([update_node_database/2, update_state_database/2]). -export([update_item_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_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 () -> 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 = {p1_time_compat:timestamp(), 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(). ejabberd-16.01/src/node_mb.erl0000644000232200023220000001405012645157216016534 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_mb.erl %%% Author : Eric Cestari %%% Purpose : PEP microglobing experimentation %%% Created : 25 Sep 2008 by Eric Cestari %%% %%% %%% 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_mb). -behaviour(gen_pubsub_node). -author('ecestari@process-one.net'). -include("pubsub.hrl"). -include("jlib.hrl"). %%% @doc The module {@module} is the pep microblog PubSub plugin. %%%

To be used, mod_pubsub must be configured:

%%% mod_pubsub:
%%%   access_createnode: pubsub_createnode
%%%   ignore_pep_from_offline: false
%%%   plugins:
%%%     - "flat"
%%%     - "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, 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). 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}]. 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(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(Nidx) -> node_pep:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> node_pep:get_affiliation(Nidx, Owner). 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(Nidx) -> node_pep:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> node_pep:get_subscriptions(Nidx, Owner). 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(Nidx) -> node_pep:get_states(Nidx). get_state(Nidx, JID) -> node_pep:get_state(Nidx, JID). set_state(State) -> node_pep:set_state(State). get_items(Nidx, From, RSM) -> node_pep:get_items(Nidx, From, RSM). get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> node_pep:get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM). get_item(Nidx, ItemId) -> node_pep:get_item(Nidx, ItemId). 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). get_item_name(Host, Node, Id) -> node_pep:get_item_name(Host, Node, Id). node_to_path(Node) -> node_pep:node_to_path(Node). path_to_node(Path) -> node_pep:path_to_node(Path). ejabberd-16.01/src/ejabberd_listener.erl0000644000232200023220000005463712645157216020613 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_listener.erl %%% Author : Alexey Shchepin %%% Purpose : Manage socket listener %%% Created : 16 Nov 2002 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_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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). %% We do not block on send anymore. -define(TCP_SEND_TIMEOUT, 15000). start_link() -> supervisor:start_link({local, ejabberd_listeners}, ?MODULE, []). init(_) -> ets:new(listen_sockets, [named_table, public]), bind_tcp_ports(), {ok, {{one_for_one, 10, 1}, []}}. bind_tcp_ports() -> case ejabberd_config:get_option(listen, fun validate_cfg/1) of undefined -> ignore; Ls -> lists:foreach( fun({Port, Module, Opts}) -> ModuleRaw = strip_frontend(Module), case ModuleRaw:socket_type() of independent -> ok; _ -> bind_tcp_port(Port, Module, Opts) end end, Ls) end. bind_tcp_port(PortIP, Module, RawOpts) -> try check_listener_options(RawOpts) of ok -> {Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts), {_Opts, SockOpts} = prepare_opts(IPT, IPV, OptsClean), case Proto of udp -> ok; _ -> ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS), ets:insert(listen_sockets, {PortIP, ListenSocket}), ok end catch throw:{error, Error} -> ?ERROR_MSG(Error, []) end. start_listeners() -> case ejabberd_config:get_option(listen, fun validate_cfg/1) of undefined -> ignore; Ls -> Ls2 = lists:map( fun({Port, Module, Opts}) -> case start_listener(Port, Module, Opts) of {ok, _Pid} = R -> R; {error, Error} -> throw(Error) end end, Ls), report_duplicated_portips(Ls), {ok, {{one_for_one, 10, 1}, Ls2}} end. report_duplicated_portips(L) -> LKeys = [Port || {Port, _, _} <- L], LNoDupsKeys = proplists:get_keys(L), case LKeys -- LNoDupsKeys of [] -> ok; Dups -> ?CRITICAL_MSG("In the ejabberd configuration there are duplicated " "Port number + IP address:~n ~p", [Dups]) end. start(Port, Module, Opts) -> %% Check if the module is an ejabberd listener or an independent listener ModuleRaw = strip_frontend(Module), case ModuleRaw:socket_type() of independent -> ModuleRaw:start_listener(Port, Opts); _ -> start_dependent(Port, Module, Opts) end. %% @spec(Port, Module, Opts) -> {ok, Pid} | {error, ErrorMessage} start_dependent(Port, Module, Opts) -> try check_listener_options(Opts) of ok -> proc_lib:start_link(?MODULE, init, [Port, Module, Opts]) catch throw:{error, Error} -> ?ERROR_MSG(Error, []), {error, Error} end. init(PortIP, Module, RawOpts) -> {Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts), {Opts, SockOpts} = prepare_opts(IPT, IPV, OptsClean), if Proto == udp -> init_udp(PortIP, Module, Opts, SockOpts, Port, IPS); true -> init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) end. init_udp(PortIP, Module, Opts, SockOpts, Port, IPS) -> case gen_udp:open(Port, [binary, {active, false}, {reuseaddr, true} | SockOpts]) of {ok, Socket} -> %% Inform my parent that this port was opened succesfully proc_lib:init_ack({ok, self()}), case erlang:function_exported(Module, udp_init, 2) of false -> udp_recv(Socket, Module, Opts); true -> case catch Module:udp_init(Socket, Opts) of {'EXIT', _} = Err -> ?ERROR_MSG("failed to process callback function " "~p:~s(~p, ~p): ~p", [Module, udp_init, Socket, Opts, Err]), udp_recv(Socket, Module, Opts); NewOpts -> udp_recv(Socket, Module, NewOpts) end end; {error, Reason} -> socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) end. init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) -> ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS), %% Inform my parent that this port was opened succesfully proc_lib:init_ack({ok, self()}), case erlang:function_exported(Module, tcp_init, 2) of false -> accept(ListenSocket, Module, Opts); true -> case catch Module:tcp_init(ListenSocket, Opts) of {'EXIT', _} = Err -> ?ERROR_MSG("failed to process callback function " "~p:~s(~p, ~p): ~p", [Module, tcp_init, ListenSocket, Opts, Err]), accept(ListenSocket, Module, Opts); NewOpts -> accept(ListenSocket, Module, NewOpts) end end. listen_tcp(PortIP, Module, SockOpts, Port, IPS) -> case ets:lookup(listen_sockets, PortIP) of [{PortIP, ListenSocket}] -> ?INFO_MSG("Reusing listening port for ~p", [PortIP]), ets:delete(listen_sockets, PortIP), ListenSocket; _ -> Res = gen_tcp:listen(Port, [binary, {packet, 0}, {active, false}, {reuseaddr, true}, {nodelay, true}, {send_timeout, ?TCP_SEND_TIMEOUT}, {send_timeout_close, true}, {keepalive, true} | SockOpts]), case Res of {ok, ListenSocket} -> ListenSocket; {error, Reason} -> socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) end end. %% @spec (PortIP, Opts) -> {Port, IPT, IPS, IPV, OptsClean} %% where %% PortIP = Port | {Port, IPT | IPS} %% Port = integer() %% IPT = tuple() %% IPS = string() %% IPV = inet | inet6 %% Opts = [IPV | {ip, IPT} | atom() | tuple()] %% OptsClean = [atom() | tuple()] %% @doc Parse any kind of ejabberd listener specification. %% The parsed options are returned in several formats. %% OptsClean does not include inet/inet6 or ip options. %% Opts can include the options inet6 and {ip, Tuple}, %% but they are only used when no IP address was specified in the PortIP. %% The IP version (either IPv4 or IPv6) is inferred from the IP address type, %% 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 proplists:get_bool(inet6, Opts2) of true -> {inet6, proplists:delete(inet6, Opts2)}; false -> {inet, Opts2} end, {Port, IPT, IPS, Proto} = case add_proto(PortIP, Opts) of {P, Prot} -> T = get_ip_tuple(IPOpt, IPVOpt), S = jlib:ip_to_list(T), {P, T, S, Prot}; {P, T, Prot} when is_integer(P) and is_tuple(T) -> S = jlib:ip_to_list(T), {P, T, S, Prot}; {P, S, Prot} when is_integer(P) and is_binary(S) -> [S | _] = str:tokens(S, <<"/">>), {ok, T} = inet_parse:address(binary_to_list(S)), {P, T, S, Prot} end, IPV = case tuple_size(IPT) of 4 -> inet; 8 -> inet6 end, {Port, IPT, IPS, IPV, Proto, OptsClean}. prepare_opts(IPT, IPV, OptsClean) -> %% The first inet|inet6 and the last {ip, _} work, %% so overriding those in Opts Opts = [IPV | OptsClean] ++ [{ip, IPT}], SockOpts = lists:filter(fun({ip, _}) -> true; (inet6) -> true; (inet) -> true; ({backlog, _}) -> true; (_) -> false end, Opts), {Opts, SockOpts}. add_proto(Port, Opts) when is_integer(Port) -> {Port, get_proto(Opts)}; add_proto({Port, Proto}, _Opts) when is_atom(Proto) -> {Port, normalize_proto(Proto)}; add_proto({Port, Addr}, Opts) -> {Port, Addr, get_proto(Opts)}; add_proto({Port, Addr, Proto}, _Opts) -> {Port, Addr, normalize_proto(Proto)}. strip_ip_option(Opts) -> {IPL, OptsNoIP} = lists:partition( fun({ip, _}) -> true; (_) -> false end, Opts), case IPL of %% Only the first ip option is considered [{ip, T1} | _] -> {T1, OptsNoIP}; [] -> {no_ip_option, OptsNoIP} end. get_ip_tuple(no_ip_option, inet) -> {0, 0, 0, 0}; get_ip_tuple(no_ip_option, inet6) -> {0, 0, 0, 0, 0, 0, 0, 0}; 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 {{ok, {Addr, Port}}, {ok, {PAddr, PPort}}} -> ?INFO_MSG("(~w) Accepted connection ~s:~p -> ~s:~p", [Socket, ejabberd_config:may_hide_data(inet_parse:ntoa(PAddr)), PPort, inet_parse:ntoa(Addr), Port]); _ -> ok end, CallMod = case is_frontend(Module) of true -> ejabberd_frontend_socket; false -> ejabberd_socket end, CallMod:start(strip_frontend(Module), gen_tcp, Socket, Opts), accept(ListenSocket, Module, Opts, NewInterval); {error, Reason} -> ?ERROR_MSG("(~w) Failed TCP accept: ~w", [ListenSocket, Reason]), accept(ListenSocket, Module, Opts, NewInterval) end. udp_recv(Socket, Module, Opts) -> case gen_udp:recv(Socket, 0) of {ok, {Addr, Port, Packet}} -> case catch Module:udp_recv(Socket, Addr, Port, Packet, Opts) of {'EXIT', Reason} -> ?ERROR_MSG("failed to process UDP packet:~n" "** Source: {~p, ~p}~n" "** Reason: ~p~n** Packet: ~p", [Addr, Port, Reason, Packet]), udp_recv(Socket, Module, Opts); NewOpts -> udp_recv(Socket, Module, NewOpts) end; {error, Reason} -> ?ERROR_MSG("unexpected UDP error: ~s", [format_error(Reason)]), throw({error, Reason}) end. %% @spec (Port, Module, Opts) -> {ok, Pid} | {error, Error} start_listener(Port, Module, Opts) -> case start_listener2(Port, Module, Opts) of {ok, _Pid} = R -> R; {error, {{'EXIT', {undef, [{M, _F, _A}|_]}}, _} = Error} -> ?ERROR_MSG("Error starting the ejabberd listener: ~p.~n" "It could not be loaded or is not an ejabberd listener.~n" "Error: ~p~n", [Module, Error]), {error, {module_not_available, M}}; {error, {already_started, Pid}} -> {ok, Pid}; {error, Error} -> {error, Error} end. %% @spec (Port, Module, Opts) -> {ok, Pid} | {error, Error} start_listener2(Port, Module, Opts) -> %% It is only required to start the supervisor in some cases. %% But it doesn't hurt to attempt to start it for any listener. %% So, it's normal (and harmless) that in most cases this call returns: {error, {already_started, pid()}} maybe_start_sip(Module), start_module_sup(Port, Module), start_listener_sup(Port, Module, Opts). start_module_sup(_Port, Module) -> Proc1 = gen_mod:get_module_proc(<<"sup">>, Module), ChildSpec1 = {Proc1, {ejabberd_tmp_sup, start_link, [Proc1, strip_frontend(Module)]}, permanent, infinity, supervisor, [ejabberd_tmp_sup]}, supervisor:start_child(ejabberd_sup, ChildSpec1). start_listener_sup(Port, Module, Opts) -> ChildSpec = {Port, {?MODULE, start, [Port, Module, Opts]}, transient, brutal_kill, worker, [?MODULE]}, supervisor:start_child(ejabberd_listeners, ChildSpec). stop_listeners() -> Ports = ejabberd_config:get_option(listen, fun validate_cfg/1), lists:foreach( fun({PortIpNetp, Module, _Opts}) -> delete_listener(PortIpNetp, Module) end, Ports). %% @spec (PortIP, Module) -> ok %% where %% PortIP = {Port, IPT | IPS} %% Port = integer() %% IPT = tuple() %% IPS = string() %% Module = atom() stop_listener(PortIP, _Module) -> supervisor:terminate_child(ejabberd_listeners, PortIP), supervisor:delete_child(ejabberd_listeners, PortIP). %% @spec (PortIP, Module, Opts) -> {ok, Pid} | {error, Error} %% where %% PortIP = {Port, IPT | IPS} %% Port = integer() %% IPT = tuple() %% IPS = string() %% IPV = inet | inet6 %% Module = atom() %% Opts = [IPV | {ip, IPT} | atom() | tuple()] %% @doc Add a listener and store in config if success add_listener(PortIP, Module, Opts) -> {Port, IPT, _, _, Proto, _} = parse_listener_portip(PortIP, Opts), PortIP1 = {Port, IPT, Proto}, case start_listener(PortIP1, Module, Opts) of {ok, _Pid} -> Ports = case ejabberd_config:get_option( listen, fun validate_cfg/1) of undefined -> []; Ls -> Ls end, Ports1 = lists:keydelete(PortIP1, 1, Ports), Ports2 = [{PortIP1, Module, Opts} | Ports1], Ports3 = lists:map(fun transform_option/1, Ports2), ejabberd_config:add_option(listen, Ports3), ok; {error, {already_started, _Pid}} -> {error, {already_started, PortIP}}; {error, Error} -> {error, Error} end. delete_listener(PortIP, Module) -> delete_listener(PortIP, Module, []). %% @spec (PortIP, Module, Opts) -> ok %% where %% PortIP = {Port, IPT | IPS} %% Port = integer() %% IPT = tuple() %% IPS = string() %% Module = atom() %% Opts = [term()] delete_listener(PortIP, Module, Opts) -> {Port, IPT, _, _, Proto, _} = parse_listener_portip(PortIP, Opts), PortIP1 = {Port, IPT, Proto}, Ports = case ejabberd_config:get_option( listen, fun validate_cfg/1) of undefined -> []; Ls -> Ls end, Ports1 = lists:keydelete(PortIP1, 1, Ports), Ports2 = lists:map(fun transform_option/1, Ports1), ejabberd_config:add_option(listen, Ports2), stop_listener(PortIP1, Module). -spec is_frontend({frontend, module} | module()) -> boolean(). is_frontend({frontend, _Module}) -> true; is_frontend(_) -> false. %% @doc(FrontMod) -> atom() %% where FrontMod = atom() | {frontend, atom()} -spec strip_frontend({frontend, module()} | module()) -> module(). strip_frontend({frontend, Module}) -> Module; strip_frontend(Module) when is_atom(Module) -> Module. maybe_start_sip(esip_socket) -> ejabberd:start_app(esip); maybe_start_sip(_) -> ok. %%% %%% Check options %%% check_listener_options(Opts) -> case includes_deprecated_ssl_option(Opts) of false -> ok; true -> Error = "There is a problem with your ejabberd configuration file: " "the option 'ssl' for listening sockets is no longer available." " To get SSL encryption use the option 'tls'.", throw({error, Error}) end, case certfile_readable(Opts) of true -> ok; {false, Path} -> ErrorText = "There is a problem in the configuration: " "the specified file is not readable: ", throw({error, ErrorText ++ Path}) end, ok. %% Parse the options of the socket, %% and return if the deprecated option 'ssl' is included %% @spec (Opts) -> true | false includes_deprecated_ssl_option(Opts) -> case lists:keysearch(ssl, 1, Opts) of {value, {ssl, _SSLOpts}} -> true; _ -> lists:member(ssl, Opts) end. %% @spec (Opts) -> true | {false, Path::string()} certfile_readable(Opts) -> case proplists:lookup(certfile, Opts) of none -> true; {certfile, Path} -> PathS = binary_to_list(Path), case ejabberd_config:is_file_readable(PathS) of true -> true; false -> {false, PathS} end end. get_proto(Opts) -> case proplists:get_value(proto, Opts) of undefined -> tcp; Proto -> normalize_proto(Proto) end. normalize_proto(tcp) -> tcp; normalize_proto(udp) -> udp; normalize_proto(UnknownProto) -> ?WARNING_MSG("There is a problem in the configuration: " "~p is an unknown IP protocol. Using tcp as fallback", [UnknownProto]), tcp. socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) -> ReasonT = case Reason of eaddrnotavail -> "IP address not available: " ++ binary_to_list(IPS); eaddrinuse -> "IP address and port number already used: " ++binary_to_list(IPS)++" "++integer_to_list(Port); _ -> format_error(Reason) end, ?ERROR_MSG("Failed to open socket:~n ~p~nReason: ~s", [{Port, Module, SockOpts}, ReasonT]), throw({Reason, PortIP}). format_error(Reason) -> case inet:format_error(Reason) of "unknown POSIX error" -> atom_to_list(Reason); ReasonStr -> 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))). -define(IS_TRANSPORT(T), ((T == tcp) or (T == udp))). transform_option({{Port, IP, Transport}, Mod, Opts}) -> IPStr = if is_tuple(IP) -> list_to_binary(inet_parse:ntoa(IP)); true -> IP end, Opts1 = lists:map( fun({ip, IPT}) when is_tuple(IPT) -> {ip, list_to_binary(inet_parse:ntoa(IP))}; (ssl) -> {tls, true}; (A) when is_atom(A) -> {A, true}; (Opt) -> Opt end, Opts), Opts2 = lists:foldl( fun(Opt, Acc) -> try Mod:transform_listen_option(Opt, Acc) catch error:undef -> [Opt|Acc] end end, [], Opts1), TransportOpt = if Transport == tcp -> []; true -> [{transport, Transport}] end, IPOpt = if IPStr == <<"0.0.0.0">> -> []; true -> [{ip, IPStr}] end, IPOpt ++ TransportOpt ++ [{port, Port}, {module, Mod} | Opts2]; transform_option({{Port, Transport}, Mod, Opts}) when ?IS_TRANSPORT(Transport) -> 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, all_zero_ip(Opts), tcp}, Mod, Opts}); transform_option(Opt) -> Opt. transform_options(Opts) -> lists:foldl(fun transform_options/2, [], Opts). transform_options({listen, LOpts}, Opts) -> [{listen, lists:map(fun transform_option/1, LOpts)} | Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. -type transport() :: udp | tcp. -type port_ip_transport() :: inet:port_number() | {inet:port_number(), transport()} | {inet:port_number(), inet:ip_address()} | {inet:port_number(), inet:ip_address(), transport()}. -spec validate_cfg(list()) -> [{port_ip_transport(), module(), list()}]. validate_cfg(L) -> lists:map( fun(LOpts) -> lists:foldl( fun({port, Port}, {{_, IP, T}, Mod, Opts}) -> true = ?IS_PORT(Port), {{Port, IP, T}, Mod, Opts}; ({ip, IP}, {{Port, _, T}, Mod, Opts}) -> {{Port, prepare_ip(IP), T}, Mod, Opts}; ({transport, T}, {{Port, IP, _}, Mod, Opts}) -> true = ?IS_TRANSPORT(T), {{Port, IP, T}, Mod, Opts}; ({module, Mod}, {Port, _, Opts}) -> {Port, prepare_mod(Mod), Opts}; (Opt, {Port, Mod, Opts}) -> {Port, Mod, [Opt|Opts]} end, {{5222, all_zero_ip(LOpts), tcp}, ejabberd_c2s, []}, LOpts) end, L). prepare_ip({A, B, C, D} = IP) when ?IS_CHAR(A) and ?IS_CHAR(B) and ?IS_CHAR(C) and ?IS_CHAR(D) -> IP; prepare_ip({A, B, C, D, E, F, G, H} = IP) when ?IS_UINT(A) and ?IS_UINT(B) and ?IS_UINT(C) and ?IS_UINT(D) and ?IS_UINT(E) and ?IS_UINT(F) and ?IS_UINT(G) and ?IS_UINT(H) -> IP; prepare_ip(IP) when is_list(IP) -> {ok, Addr} = inet_parse:address(IP), Addr; prepare_ip(IP) when is_binary(IP) -> prepare_ip(binary_to_list(IP)). prepare_mod(ejabberd_sip) -> prepare_mod(sip); prepare_mod(sip) -> esip_socket; 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]. ejabberd-16.01/src/node_dag.erl0000644000232200023220000001242512645157216016675 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_dag.erl %%% Author : Brian Cully %%% Purpose : experimental support of XEP-248 %%% Created : 15 Jun 2009 by Brian Cully %%% %%% %%% 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_dag). -behaviour(gen_pubsub_node). -author('bjc@kublai.com'). -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]). init(Host, ServerHost, Opts) -> node_hometree:init(Host, ServerHost, Opts). terminate(Host, ServerHost) -> node_hometree:terminate(Host, ServerHost). options() -> [{node_type, leaf} | node_hometree:options()]. features() -> [<<"multi-collection">> | node_hometree:features()]. create_node_permission(_Host, _ServerHost, _Node, _ParentNode, _Owner, _Access) -> {result, true}. create_node(Nidx, Owner) -> node_hometree:create_node(Nidx, Owner). delete_node(Removed) -> node_hometree:delete_node(Removed). 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(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) -> node_hometree:get_entity_affiliations(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) -> node_hometree:get_entity_subscriptions(Host, Owner). 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). 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_hometree:node_to_path(Node). path_to_node(Path) -> node_hometree:path_to_node(Path). ejabberd-16.01/src/ejabberd_frontend_socket.erl0000644000232200023220000001744112645157216022145 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% File : ejabberd_frontend_socket.erl %%% Author : Alexey Shchepin %%% Purpose : Frontend socket with zlib and TLS support library %%% Created : 23 Aug 2006 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_frontend_socket). -author('alexey@process-one.net'). -behaviour(gen_server). %% API -export([start/4, start_link/5, %connect/3, starttls/2, starttls/3, compress/1, compress/2, reset_stream/1, send/2, change_shaper/2, monitor/1, get_sockmod/1, get_peer_certificate/1, get_verify_result/1, close/1, sockname/1, peername/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -record(state, {sockmod, socket, receiver}). -define(HIBERNATE_TIMEOUT, 90000). %%==================================================================== %% API %%==================================================================== start_link(Module, SockMod, Socket, Opts, Receiver) -> gen_server:start_link(?MODULE, [Module, SockMod, Socket, Opts, Receiver], []). start(Module, SockMod, Socket, Opts) -> case Module:socket_type() of xml_stream -> MaxStanzaSize = case lists:keysearch(max_stanza_size, 1, Opts) of {value, {_, Size}} -> Size; _ -> infinity end, Receiver = ejabberd_receiver:start(Socket, SockMod, none, MaxStanzaSize), case SockMod:controlling_process(Socket, Receiver) of ok -> ok; {error, _Reason} -> SockMod:close(Socket) end, supervisor:start_child(ejabberd_frontend_socket_sup, [Module, SockMod, Socket, Opts, Receiver]); raw -> %{ok, Pid} = Module:start({SockMod, Socket}, Opts), %case SockMod:controlling_process(Socket, Pid) of % ok -> % ok; % {error, _Reason} -> % SockMod:close(Socket) %end todo end. starttls(FsmRef, _TLSOpts) -> %% TODO: Frontend improvements planned by Aleksey %%gen_server:call(FsmRef, {starttls, TLSOpts}), FsmRef. starttls(FsmRef, TLSOpts, Data) -> gen_server:call(FsmRef, {starttls, TLSOpts, Data}), FsmRef. compress(FsmRef) -> compress(FsmRef, undefined). compress(FsmRef, Data) -> gen_server:call(FsmRef, {compress, Data}), FsmRef. reset_stream(FsmRef) -> gen_server:call(FsmRef, reset_stream). send(FsmRef, Data) -> gen_server:call(FsmRef, {send, Data}). change_shaper(FsmRef, Shaper) -> gen_server:call(FsmRef, {change_shaper, Shaper}). monitor(FsmRef) -> erlang:monitor(process, FsmRef). get_sockmod(FsmRef) -> gen_server:call(FsmRef, get_sockmod). get_peer_certificate(FsmRef) -> gen_server:call(FsmRef, get_peer_certificate). get_verify_result(FsmRef) -> gen_server:call(FsmRef, get_verify_result). close(FsmRef) -> gen_server:call(FsmRef, close). sockname(FsmRef) -> gen_server:call(FsmRef, sockname). peername(_FsmRef) -> %% TODO: Frontend improvements planned by Aleksey %%gen_server:call(FsmRef, peername). {ok, {{0, 0, 0, 0}, 0}}. %%==================================================================== %% gen_server callbacks %%==================================================================== init([Module, SockMod, Socket, Opts, Receiver]) -> Node = ejabberd_node_groups:get_closest_node(backend), {SockMod2, Socket2} = check_starttls(SockMod, Socket, Receiver, Opts), {ok, Pid} = rpc:call(Node, Module, start, [{?MODULE, self()}, Opts]), ejabberd_receiver:become_controller(Receiver, Pid), {ok, #state{sockmod = SockMod2, socket = Socket2, receiver = Receiver}}. handle_call({starttls, TLSOpts}, _From, State) -> {ok, TLSSocket} = p1_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}, ?HIBERNATE_TIMEOUT}; handle_call({starttls, TLSOpts, Data}, _From, State) -> {ok, TLSSocket} = p1_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}, ?HIBERNATE_TIMEOUT}; handle_call({compress, Data}, _From, State) -> {ok, ZlibSocket} = ejabberd_receiver:compress(State#state.receiver, Data), Reply = ok, {reply, Reply, State#state{socket = ZlibSocket, sockmod = ezlib}, ?HIBERNATE_TIMEOUT}; handle_call(reset_stream, _From, State) -> ejabberd_receiver:reset_stream(State#state.receiver), Reply = ok, {reply, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call({send, Data}, _From, State) -> catch (State#state.sockmod):send(State#state.socket, Data), Reply = ok, {reply, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call({change_shaper, Shaper}, _From, State) -> ejabberd_receiver:change_shaper(State#state.receiver, Shaper), Reply = ok, {reply, Reply, State, ?HIBERNATE_TIMEOUT}; 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, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call(get_verify_result, _From, State) -> Reply = p1_tls:get_verify_result(State#state.socket), {reply, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call(close, _From, State) -> ejabberd_receiver:close(State#state.receiver), Reply = ok, {stop, normal, Reply, State}; handle_call(sockname, _From, State) -> #state{sockmod = SockMod, socket = Socket} = State, Reply = case SockMod of gen_tcp -> inet:sockname(Socket); _ -> SockMod:sockname(Socket) end, {reply, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call(peername, _From, State) -> #state{sockmod = SockMod, socket = Socket} = State, Reply = case SockMod of gen_tcp -> inet:peername(Socket); _ -> SockMod:peername(Socket) end, {reply, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State, ?HIBERNATE_TIMEOUT}. handle_cast(_Msg, State) -> {noreply, State, ?HIBERNATE_TIMEOUT}. handle_info(timeout, State) -> proc_lib:hibernate(gen_server, enter_loop, [?MODULE, [], State]), {noreply, State, ?HIBERNATE_TIMEOUT}; handle_info(_Info, State) -> {noreply, State, ?HIBERNATE_TIMEOUT}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. check_starttls(SockMod, Socket, Receiver, Opts) -> TLSEnabled = proplists:get_bool(tls, Opts), TLSOpts = lists:filter(fun({certfile, _}) -> true; (_) -> false end, Opts), if TLSEnabled -> {ok, TLSSocket} = p1_tls:tcp_to_tls(Socket, TLSOpts), ejabberd_receiver:starttls(Receiver, TLSSocket), {p1_tls, TLSSocket}; true -> {SockMod, Socket} end. ejabberd-16.01/src/ejabberd_xmlrpc.erl0000644000232200023220000005305312645157216020262 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_xmlrpc.erl %%% Author : Badlop %%% Purpose : XML-RPC server that frontends ejabberd commands %%% 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., %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%---------------------------------------------------------------------- %%% TODO: Implement a command in ejabberdctl 'help COMMAND LANGUAGE' that shows %%% a coding example to call that command in a specific language (python, php). %%% TODO: Remove support for plaintext password %%% TODO: commands strings should be strings without ~n -module(ejabberd_xmlrpc). -author('badlop@process-one.net'). -export([start/2, handler/2, process/2, socket_type/0, transform_listen_option/2]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("ejabberd_http.hrl"). -include("mod_roster.hrl"). -include("jlib.hrl"). -record(state, {access_commands = [] :: list(), auth = noauth :: noauth | {binary(), binary(), binary()}, get_auth = true :: boolean()}). %% Test: %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, take_integer, [{struct, [{thisinteger, 5}]}]}). %% {ok,{response,[{struct,[{zero,0}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_string, [{struct, [{thisstring, "abcd"}]}]}). %% {ok,{response,[{struct,[{thatstring,"abcd"}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, tell_tuple_3integer, [{struct, [{thisstring, "abcd"}]}]}). %% {ok,{response, %% [{struct, %% [{thattuple, %% {array, %% [{struct,[{first,123}]}, %% {struct,[{second,456}]}, %% {struct,[{third,789}]}]}}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, pow, [{struct, [{base, 5}, {exponent, 7}]}]}). %% {ok,{response,[{struct,[{pow,78125}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, seq, [{struct, [{from, 3}, {to, 7}]}]}). %% {ok,{response,[{array,[{struct,[{intermediate,3}]}, %% {struct,[{intermediate,4}]}, %% {struct,[{intermediate,5}]}, %% {struct,[{intermediate,6}]}, %% {struct,[{intermediate,7}]}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, substrs, [{struct, [{word, "abcd"}]}]}). %% NO: %% {ok,{response,[{array,[{struct,[{miniword,"a"}]}, %% {struct,[{miniword,"ab"}]}, %% {struct,[{miniword,"abc"}]}, %% {struct,[{miniword,"abcd"}]}]}]}} %% {ok,{response, %% [{struct, %% [{substrings, %% {array, %% [{struct,[{miniword,"a"}]}, %% {struct,[{miniword,"ab"}]}, %% {struct,[{miniword,"abc"}]}, %% {struct,[{miniword,"abcd"}]}]}}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, splitjid, [{struct, [{jid, "abcd@localhost/work"}]}]}). %% {ok,{response, %% [{struct, %% [{jidparts, %% {array, %% [{struct,[{user,"abcd"}]}, %% {struct,[{server,"localhost"}]}, %% {struct,[{resource,"work"}]}]}}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_string, [{struct, [{thisstring, "abc"}, {thisinteger, 55}]}]}). %% {ok,{response, %% [{struct, %% [{thistuple, %% {array, %% [{struct,[{thisinteger,55}]}, %% {struct,[{thisstring,"abc"}]}]}}]}]}} %% %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_list_integer, [{struct, [{thislist, {array, [{struct, [{thisinteger, 55}, {thisinteger, 4567}]}]}}]}]}). %% {ok,{response, %% [{struct, %% [{thatlist, %% {array, %% [{struct,[{thatinteger,55}]}, %% {struct,[{thatinteger,4567}]}]}}]}]}} %% %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_list_string, [{struct, [{thisinteger, 123456}, {thislist, {array, [{struct, [{thisstring, "abc"}, {thisstring, "bobo baba"}]}]}}]}]}). %% {ok, %% {response, %% [{struct, %% [{thistuple, %% {array, %% [{struct,[{thatinteger,123456}]}, %% {struct, %% [{thatlist, %% {array, %% [{struct,[{thatstring,"abc"}]}, %% {struct,[{thatstring,"bobo baba"}]}]}}]}]}}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, take_tuple_2integer, [{struct, [{thistuple, {array, [{struct, [{thisinteger1, 55}, {thisinteger2, 4567}]}]}}]}]}). %% {ok,{response,[{struct,[{zero,0}]}]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_isatils, [{struct, %% [{thisinteger, 123456990}, %% {thisstring, "This is ISATILS"}, %% {thisatom, "test_isatils"}, %% {thistuple, {array, [{struct, [ %% {listlen, 2}, %% {thislist, {array, [{struct, [ %% {contentstring, "word1"}, %% {contentstring, "word 2"} %% ]}]}} %% ]}]}} %% ]}]}). %% {ok,{response, %% [{struct, %% [{results, %% {array, %% [{struct,[{thatinteger,123456990}]}, %% {struct,[{thatstring,"This is ISATILS"}]}, %% {struct,[{thatatom,"test_isatils"}]}, %% {struct, %% [{thattuple, %% {array, %% [{struct,[{listlen,123456990}]}, %% {struct,[{thatlist,...}]}]}}]}]}}]}]}} %% ecommand doesn't exist: %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_string2, [{struct, [{thisstring, "abc"}]}]}). %% {ok,{response,{fault,-1, "Unknown call: {call,echo_integer_string2,[{struct,[{thisstring,\"abc\"}]}]}"}}} %% %% Duplicated argument: %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_string, [{struct, [{thisstring, "abc"}, {thisinteger, 44}, {thisinteger, 55}]}]}). %% {ok,{response,{fault,-104, "Error -104\nAttribute 'thisinteger' duplicated:\n[{thisstring,\"abc\"},{thisinteger,44},{thisinteger,55}]"}}} %% %% Missing argument: %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_string, [{struct, [{thisstring, "abc"}]}]}). %% {ok,{response,{fault,-106, "Error -106\nRequired attribute 'thisinteger' not found:\n[{thisstring,\"abc\"}]"}}} %% %% Duplicated tuple element: %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, take_tuple_2integer, [{struct, [{thistuple, {array, [{struct, [{thisinteger1, 55}, {thisinteger1, 66}, {thisinteger2, 4567}]}]}}]}]}). %% {ok,{response,{fault,-104, "Error -104\nAttribute 'thisinteger1' defined multiple times:\n[{thisinteger1,55},{thisinteger1,66},{thisinteger2,4567}]"}}} %% %% Missing element in tuple: %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, take_tuple_2integer, [{struct, [{thistuple, {array, [{struct, [{thisinteger1, 55}, {thisintegerc, 66}, {thisinteger, 4567}]}]}}]}]}). %% {ok,{response,{fault,-106, "Error -106\nRequired attribute 'thisinteger2' not found:\n[{thisintegerc,66},{thisinteger,4567}]"}}} %% %% The ecommand crashed: %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, this_crashes, [{struct, []}]}). %% {ok,{response,{fault,-100, "Error -100\nA problem 'error' occurred executing the command this_crashes with arguments []: badarith"}}} %% ----------------------------- %% Listener interface %% ----------------------------- start({gen_tcp = _SockMod, Socket}, Opts) -> ejabberd_http:start({gen_tcp, Socket}, [{xmlrpc, true}|Opts]). socket_type() -> raw. %% ----------------------------- %% HTTP interface %% ----------------------------- process(_, #request{method = 'POST', data = Data, opts = Opts}) -> AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts, fun(L) when is_list(L) -> L 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, _} -> {400, [], #xmlel{name = <<"h1">>, attrs = [], children = [{xmlcdata, <<"Malformed XML">>}]}}; El -> case p1_xmlrpc:decode(El) of {error, _} = Err -> ?ERROR_MSG("XML-RPC request ~s failed with reason: ~p", [Data, Err]), {400, [], #xmlel{name = <<"h1">>, attrs = [], children = [{xmlcdata, <<"Malformed Request">>}]}}; {ok, RPC} -> ?DEBUG("got XML-RPC request: ~p", [RPC]), {false, Result} = handler(State, RPC), XML = xml:element_to_binary(p1_xmlrpc:encode(Result)), {200, [{<<"Content-Type">>, <<"text/xml">>}], <<"", XML/binary>>} end end; process(_, _) -> {400, [], #xmlel{name = <<"h1">>, attrs = [], children = [{xmlcdata, <<"400 Bad Request">>}]}}. %% ----------------------------- %% Access verification %% ----------------------------- get_auth(AuthList) -> 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 %% ----------------------------- %% Call: Arguments: Returns: %% ............................. %% Access verification %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [152]}). %% {ok,{response,{fault,-103, "Error -103\nRequired authentication: {call,echothis,[152]}"}}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [{struct, [{user, "badlop"}, {server, "localhost"}, {password, "ada"}]}, 152]}). %% {ok,{response,{fault,-103, %% "Error -103\nAuthentication non valid: [{user,\"badlop\"},\n %% {server,\"localhost\"},\n %% {password,\"ada\"}]"}}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [{struct, [{user, "badlop"}, {server, "localhost"}, {password, "ada90ada"}]}, 152]}). %% {ok,{response,[152]}} %% %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [{struct, [{user, "badlop"}, {server, "localhost"}, {password, "79C1574A43BC995F2B145A299EF97277"}]}, 152]}). %% {ok,{response,[152]}} 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}) catch {error, missing_auth_arguments, _Attr} -> handler(State#state{get_auth = false, auth = noauth}, {call, Method, AllArgs}) end; %% ............................. %% Debug %% echothis String String handler(_State, {call, echothis, [A]}) -> {false, {response, [A]}}; %% echothisnew struct[{sentence, String}] struct[{repeated, String}] handler(_State, {call, echothisnew, [{struct, [{sentence, A}]}]}) -> {false, {response, [{struct, [{repeated, A}]}]}}; %% multhis struct[{a, Integer}, {b, Integer}] Integer handler(_State, {call, multhis, [{struct, [{a, A}, {b, B}]}]}) -> {false, {response, [A * B]}}; %% multhisnew struct[{a, Integer}, {b, Integer}] struct[{mu, Integer}] handler(_State, {call, multhisnew, [{struct, [{a, A}, {b, B}]}]}) -> {false, {response, [{struct, [{mu, A * B}]}]}}; %% ............................. %% ejabberd commands handler(State, {call, Command, []}) -> handler(State, {call, Command, [{struct, []}]}); handler(State, {call, Command, [{struct, AttrL}]} = Payload) -> case ejabberd_commands:get_command_format(Command, State#state.auth) of {error, command_unknown} -> build_fault_response(-112, "Unknown call: ~p", [Payload]); {ArgsF, ResultF} -> try_do_command(State#state.access_commands, State#state.auth, Command, AttrL, ArgsF, ResultF) end; %% If no other guard matches handler(_State, Payload) -> build_fault_response(-112, "Unknown call: ~p", [Payload]). %% ----------------------------- %% Command %% ----------------------------- try_do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ResultF) -> try do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ResultF) of {command_result, ResultFormatted} -> {false, {response, [ResultFormatted]}} catch exit:{duplicated_attribute, ExitAt, ExitAtL} -> build_fault_response(-114, "Attribute '~p' duplicated:~n~p", [ExitAt, ExitAtL]); exit:{attribute_not_found, ExitAt, ExitAtL} -> build_fault_response(-116, "Required attribute '~p' not found:~n~p", [ExitAt, ExitAtL]); exit:{additional_unused_args, ExitAtL} -> build_fault_response(-120, "The call provided additional unused " "arguments:~n~p", [ExitAtL]); Why -> build_fault_response(-118, "A problem '~p' occurred executing the " "command ~p with arguments~n~p", [Why, Command, AttrL]) end. build_fault_response(Code, ParseString, ParseArgs) -> FaultString = "Error " ++ integer_to_list(Code) ++ "\n" ++ lists:flatten(io_lib:format(ParseString, ParseArgs)), ?WARNING_MSG(FaultString, []), {false, {response, {fault, Code, list_to_binary(FaultString)}}}. do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ResultF) -> ArgsFormatted = format_args(AttrL, ArgsF), Result = ejabberd_commands:execute_command(AccessCommands, Auth, Command, ArgsFormatted), ResultFormatted = format_result(Result, ResultF), {command_result, ResultFormatted}. %%----------------------------- %% Format arguments %%----------------------------- get_attrs(Attribute_names, L) -> [get_attr(A, L) || A <- Attribute_names]. get_attr(A, L) -> case lists:keysearch(A, 1, L) of {value, {A, Value}} -> Value; false -> %% Report the error and then force a crash exit({attribute_not_found, A, L}) 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) -> Arg; format_arg(Arg, string) when is_binary(Arg) -> binary_to_list(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)). %% ----------------------------- %% Result %% ----------------------------- format_result({error, Error}, _) -> throw({error, Error}); format_result(String, string) -> lists:flatten(String); format_result(Atom, {Name, atom}) -> {struct, [{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) -> {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) -> {struct, [{Name, binary_to_list(Binary)}]}; format_result(Code, {Name, rescode}) -> {struct, [{Name, make_status(Code)}]}; format_result({Code, Text}, {Name, restuple}) -> {struct, [{Name, make_status(Code)}, {text, lists:flatten(Text)}]}; %% Result is a list of something: [something()] format_result(Elements, {Name, {list, ElementsDef}}) -> FormattedList = lists:map(fun (Element) -> format_result(Element, ElementsDef) end, Elements), {struct, [{Name, {array, FormattedList}}]}; %% Result is a tuple with several elements: {something1(), something2(), ...} format_result(ElementsTuple, {Name, {tuple, ElementsDef}}) -> ElementsList = tuple_to_list(ElementsTuple), ElementsAndDef = lists:zip(ElementsList, ElementsDef), FormattedList = lists:map(fun ({Element, ElementDef}) -> format_result(Element, ElementDef) end, ElementsAndDef), {struct, [{Name, {array, FormattedList}}]}; format_result(404, {Name, _}) -> {struct, [{Name, make_status(not_found)}]}. make_status(ok) -> 0; make_status(true) -> 0; make_status(false) -> 1; make_status(error) -> 1; make_status(_) -> 1. transform_listen_option({access_commands, ACOpts}, Opts) -> NewACOpts = lists:map( fun({AName, ACmds, AOpts}) -> {AName, [{commands, ACmds}, {options, AOpts}]}; (Opt) -> Opt end, ACOpts), [{access_commands, NewACOpts}|Opts]; transform_listen_option(Opt, Opts) -> [Opt|Opts]. ejabberd-16.01/src/ejabberd_odbc_sup.erl0000644000232200023220000001626312645157216020555 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_odbc_sup.erl %%% Author : Alexey Shchepin %%% Purpose : ODBC connections supervisor %%% Created : 22 Dec 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_odbc_sup). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -export([start_link/1, init/1, add_pid/2, remove_pid/2, get_pids/1, get_random_pid/1, transform_options/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -define(PGSQL_PORT, 5432). -define(MYSQL_PORT, 3306). -define(DEFAULT_POOL_SIZE, 10). -define(DEFAULT_ODBC_START_INTERVAL, 30). -define(CONNECT_TIMEOUT, 500). -record(sql_pool, {host, pid}). start_link(Host) -> mnesia:create_table(sql_pool, [{ram_copies, [node()]}, {type, bag}, {local_content, true}, {attributes, record_info(fields, sql_pool)}]), mnesia:add_table_copy(sql_pool, node(), ram_copies), F = fun () -> mnesia:delete({sql_pool, Host}) end, mnesia:ets(F), supervisor:start_link({local, gen_mod:get_module_proc(Host, ?MODULE)}, ?MODULE, [Host]). init([Host]) -> PoolSize = ejabberd_config:get_option( {odbc_pool_size, Host}, fun(I) when is_integer(I), I>0 -> I end, ?DEFAULT_POOL_SIZE), StartInterval = ejabberd_config:get_option( {odbc_start_interval, Host}, fun(I) when is_integer(I), I>0 -> I end, ?DEFAULT_ODBC_START_INTERVAL), Type = ejabberd_config:get_option({odbc_type, 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, {ok, {{one_for_one, PoolSize * 10, 1}, lists:map(fun (I) -> {I, {ejabberd_odbc, start_link, [Host, StartInterval * 1000]}, transient, 2000, worker, [?MODULE]} end, lists:seq(1, PoolSize))}}. get_pids(Host) -> Rs = mnesia:dirty_read(sql_pool, Host), [R#sql_pool.pid || R <- Rs]. get_random_pid(Host) -> case get_pids(Host) of [] -> none; Pids -> lists:nth(erlang:phash(p1_time_compat:unique_integer(), length(Pids)), Pids) end. add_pid(Host, Pid) -> F = fun () -> mnesia:write(#sql_pool{host = Host, pid = Pid}) end, mnesia:ets(F). remove_pid(Host, Pid) -> F = fun () -> mnesia:delete_object(#sql_pool{host = Host, pid = Pid}) end, mnesia:ets(F). transform_options(Opts) -> lists:foldl(fun transform_options/2, [], Opts). transform_options({odbc_server, {Type, Server, Port, DB, User, Pass}}, Opts) -> [{odbc_type, Type}, {odbc_server, Server}, {odbc_port, Port}, {odbc_database, DB}, {odbc_username, User}, {odbc_password, Pass}|Opts]; transform_options({odbc_server, {mysql, Server, DB, User, Pass}}, Opts) -> transform_options({odbc_server, {mysql, Server, ?MYSQL_PORT, DB, User, Pass}}, Opts); transform_options({odbc_server, {pgsql, Server, DB, User, Pass}}, Opts) -> transform_options({odbc_server, {pgsql, Server, ?PGSQL_PORT, DB, User, Pass}}, Opts); transform_options({odbc_server, {sqlite, DB}}, Opts) -> transform_options({odbc_server, {sqlite, DB}}, Opts); transform_options(Opt, Opts) -> [Opt|Opts]. check_sqlite_db(Host) -> DB = ejabberd_odbc:sqlite_db(Host), File = ejabberd_odbc:sqlite_file(Host), Ret = case filelib:ensure_dir(File) of ok -> case sqlite3:open(DB, [{file, File}]) of {ok, _Ref} -> ok; {error, {already_started, _Ref}} -> ok; {error, R} -> {error, R} end; Err -> Err end, case Ret of ok -> sqlite3:sql_exec(DB, "pragma foreign_keys = on"), case sqlite3:list_tables(DB) of [] -> create_sqlite_tables(DB), sqlite3:close(DB), ok; [_H | _] -> ok end; {error, Reason} -> ?INFO_MSG("Failed open sqlite database, reason ~p", [Reason]) end. create_sqlite_tables(DB) -> SqlDir = case code:priv_dir(ejabberd) of {error, _} -> ?SQL_DIR; PrivDir -> filename:join(PrivDir, "sql") end, File = filename:join(SqlDir, "lite.sql"), case file:open(File, [read, binary]) of {ok, Fd} -> Qs = read_lines(Fd, File, []), ok = sqlite3:sql_exec(DB, "begin"), [ok = sqlite3:sql_exec(DB, Q) || Q <- Qs], ok = sqlite3:sql_exec(DB, "commit"); {error, Reason} -> ?INFO_MSG("Failed to read SQLite schema file: ~s", [file:format_error(Reason)]) end. read_lines(Fd, File, Acc) -> case file:read_line(Fd) of {ok, Line} -> NewAcc = case str:strip(str:strip(Line, both, $\r), both, $\n) of <<"--", _/binary>> -> Acc; <<>> -> Acc; _ -> [Line|Acc] end, read_lines(Fd, File, NewAcc); eof -> QueryList = str:tokens(list_to_binary(lists:reverse(Acc)), <<";">>), lists:flatmap( fun(Query) -> case str:strip(str:strip(Query, both, $\r), both, $\n) of <<>> -> []; Q -> [<>] end end, QueryList); {error, _} = Err -> ?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; (mssql) -> mssql; (odbc) -> odbc end; opt_type(_) -> [odbc_pool_size, odbc_start_interval, odbc_type]. ejabberd-16.01/src/ejabberd_config.erl0000644000232200023220000012252212645157216020220 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_config.erl %%% Author : Alexey Shchepin %%% Purpose : Load config file %%% Created : 14 Dec 2002 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_config). -author('alexey@process-one.net'). -export([start/0, load_file/1, reload_file/0, read_file/1, add_global_option/2, add_local_option/2, get_global_option/2, get_local_option/2, get_global_option/3, get_local_option/3, get_option/2, get_option/3, add_option/2, get_vh_by_auth_method/1, is_file_readable/1, get_version/0, get_myhosts/0, get_mylang/0, 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, may_hide_data/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()} %% @type macro_key() = atom(). %% The atom must have all characters in uppercase. %% @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), Config = get_ejabberd_config_path(), State0 = read_file(Config), State = validate_opts(State0), %% This start time is used by mod_last: UnixTime = p1_time_compat:system_time(seconds), SharedKey = case erlang:get_cookie() of nocookie -> p1_sha:sha(randoms:get_string()); 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). %% @doc Get the filename of the ejabberd configuration file. %% The filename can be specified with: erl -config "/path/to/ejabberd.yml". %% It can also be specified with the environtment variable EJABBERD_CONFIG_PATH. %% If not specified, the default value 'ejabberd.yml' is assumed. %% @spec () -> string() get_ejabberd_config_path() -> case get_env_config() of {ok, Path} -> Path; undefined -> case os:getenv("EJABBERD_CONFIG_PATH") of false -> ?CONFIG_PATH; Path -> Path end end. -spec get_env_config() -> {ok, string()} | undefined. get_env_config() -> %% First case: the filename can be specified with: erl -config "/path/to/ejabberd.yml". case application:get_env(config) of R = {ok, _Path} -> R; undefined -> %% Second case for embbeding ejabberd in another app, for example for Elixir: %% config :ejabberd, %% file: "config/ejabberd.yml" application:get_env(ejabberd, file) end. %% @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{}. read_file(File) -> read_file(File, [{replace_macros, true}, {include_files, true}, {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), State = lists:foldl(fun search_hosts/2, #state{}, Terms), {Head, Tail} = lists:partition( fun({host_config, _}) -> false; ({append_host_config, _}) -> false; (_) -> true end, Terms), State1 = lists:foldl(fun process_term/2, State, Head ++ Tail), State1#state{opts = compact(State1#state.opts)}. -spec load_file(string()) -> ok. load_file(File) -> State = read_file(File), set_opts(State). -spec reload_file() -> ok. reload_file() -> Config = get_ejabberd_config_path(), load_file(Config). -spec convert_to_yaml(file:filename()) -> ok | {error, any()}. convert_to_yaml(File) -> convert_to_yaml(File, stdout). -spec convert_to_yaml(file:filename(), stdout | file:filename()) -> ok | {error, any()}. convert_to_yaml(File, Output) -> State = read_file(File, [{include_files, false}]), Opts = [{K, V} || #local_config{key = K, value = V} <- State#state.opts], {GOpts, HOpts} = split_by_hosts(Opts), NewOpts = GOpts ++ lists:map( fun({Host, Opts1}) -> {host_config, [{Host, Opts1}]} end, HOpts), Data = p1_yaml:encode(lists:reverse(NewOpts)), case Output of stdout -> io:format("~s~n", [Data]); FileName -> file:write_file(FileName, Data) end. %% Some Erlang apps expects env parameters to be list and not binary. %% For example, Mnesia is not able to start if mnesia dir is passed as a binary. %% However, binary is most common on Elixir, so it is easy to make a setup mistake. -spec env_binary_to_list(atom(), atom()) -> {ok, any()}|undefined. env_binary_to_list(Application, Parameter) -> %% Application need to be loaded to allow setting parameters application:load(Application), case application:get_env(Application, Parameter) of {ok, Val} when is_binary(Val) -> BVal = binary_to_list(Val), application:set_env(Application, Parameter, BVal), {ok, BVal}; Other -> Other end. %% @doc Read an ejabberd configuration file and return the terms. %% Input is an absolute or relative path to an ejabberd config file. %% Returns a list of plain terms, %% in which the options 'include_config_file' were parsed %% and the terms in those files were included. %% @spec(iolist()) -> [term()] get_plain_terms_file(File) -> get_plain_terms_file(File, [{include_files, true}]). get_plain_terms_file(File, Opts) when is_binary(File) -> get_plain_terms_file(binary_to_list(File), Opts); get_plain_terms_file(File1, Opts) -> File = get_absolute_path(File1), case consult(File) of {ok, Terms} -> BinTerms1 = strings_to_binary(Terms), ModInc = case proplists:get_bool(include_modules_configs, Opts) of true -> 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], case proplists:get_bool(include_files, Opts) of true -> include_config_files(BinTerms); false -> BinTerms end; {error, Reason} -> ?ERROR_MSG(Reason, []), exit_or_halt(Reason) end. 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 {ok, []} -> {ok, []}; {ok, [Document|_]} -> {ok, parserl(Document)}; {error, Err} -> Msg1 = "Cannot load " ++ File ++ ": ", Msg2 = p1_yaml:format_error(Err), {error, Msg1 ++ Msg2} end; _ -> case file:consult(File) of {ok, Terms} -> {ok, Terms}; {error, {LineNumber, erl_parse, _ParseMessage} = Reason} -> {error, describe_config_problem(File, Reason, LineNumber)}; {error, Reason} -> {error, describe_config_problem(File, Reason)} end end. parserl(<<"> ", Term/binary>>) -> {ok, A2, _} = erl_scan:string(binary_to_list(Term)), {ok, A3} = erl_parse:parse_term(A2), A3; parserl({A, B}) -> {parserl(A), parserl(B)}; parserl([El|Tail]) -> [parserl(El) | parserl(Tail)]; parserl(Other) -> Other. %% @doc Convert configuration filename to absolute path. %% Input is an absolute or relative path to an ejabberd configuration file. %% And returns an absolute path to the configuration file. %% @spec (string()) -> string() get_absolute_path(File) -> case filename:pathtype(File) of absolute -> File; relative -> {ok, Dir} = file:get_cwd(), filename:absname_join(Dir, File) end. search_hosts(Term, State) -> case Term of {host, Host} -> if State#state.hosts == [] -> add_hosts_to_option([Host], State); true -> ?ERROR_MSG("Can't load config file: " "too many hosts definitions", []), exit("too many hosts definitions") end; {hosts, Hosts} -> if State#state.hosts == [] -> add_hosts_to_option(Hosts, State); true -> ?ERROR_MSG("Can't load config file: " "too many hosts definitions", []), exit("too many hosts definitions") end; _ -> State end. add_hosts_to_option(Hosts, State) -> PrepHosts = normalize_hosts(Hosts), set_option({hosts, global}, PrepHosts, State#state{hosts = PrepHosts}). normalize_hosts(Hosts) -> normalize_hosts(Hosts,[]). normalize_hosts([], PrepHosts) -> lists:reverse(PrepHosts); normalize_hosts([Host|Hosts], PrepHosts) -> case jid:nodeprep(iolist_to_binary(Host)) of error -> ?ERROR_MSG("Can't load config file: " "invalid host name [~p]", [Host]), exit("invalid hostname"); PrepHost -> normalize_hosts(Hosts, [PrepHost|PrepHosts]) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Errors reading the config file describe_config_problem(Filename, Reason) -> Text1 = lists:flatten("Problem loading ejabberd config file " ++ Filename), Text2 = lists:flatten(" : " ++ file:format_error(Reason)), ExitText = Text1 ++ Text2, ExitText. describe_config_problem(Filename, Reason, LineNumber) -> Text1 = lists:flatten("Problem loading ejabberd config file " ++ Filename), Text2 = lists:flatten(" approximately in the line " ++ file:format_error(Reason)), ExitText = Text1 ++ Text2, Lines = get_config_lines(Filename, LineNumber, 10, 3), ?ERROR_MSG("The following lines from your configuration file might be" " relevant to the error: ~n~s", [Lines]), ExitText. get_config_lines(Filename, TargetNumber, PreContext, PostContext) -> {ok, Fd} = file:open(Filename, [read]), LNumbers = lists:seq(TargetNumber-PreContext, TargetNumber+PostContext), NextL = io:get_line(Fd, no_prompt), R = get_config_lines2(Fd, NextL, 1, LNumbers, []), file:close(Fd), R. get_config_lines2(_Fd, eof, _CurrLine, _LNumbers, R) -> lists:reverse(R); get_config_lines2(_Fd, _NewLine, _CurrLine, [], R) -> lists:reverse(R); get_config_lines2(Fd, Data, CurrLine, [NextWanted | LNumbers], R) when is_list(Data) -> NextL = io:get_line(Fd, no_prompt), if CurrLine >= NextWanted -> Line2 = [integer_to_list(CurrLine), ": " | Data], get_config_lines2(Fd, NextL, CurrLine+1, LNumbers, [Line2 | R]); true -> get_config_lines2(Fd, NextL, CurrLine+1, [NextWanted | LNumbers], R) end. %% If ejabberd isn't yet running in this node, then halt the node exit_or_halt(ExitText) -> case [Vsn || {ejabberd, _Desc, Vsn} <- application:which_applications()] of [] -> timer:sleep(1000), halt(string:substr(ExitText, 1, 199)); [_] -> exit(ExitText) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Support for 'include_config_file' get_config_option_key(Name, Val) -> if Name == listen -> 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 -> Val end. maps_to_lists(IMap) -> 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) -> [{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 orelse Name == append_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) -> {FileOpts, Terms1} = lists:mapfoldl( fun({include_config_file, _} = T, Ts) -> {[transform_include_option(T)], Ts}; ({include_config_file, _, _} = T, Ts) -> {[transform_include_option(T)], Ts}; (T, Ts) -> {[], [T|Ts]} end, [], Terms), Terms2 = lists:flatmap( fun({File, Opts}) -> include_config_file(File, Opts) end, lists:flatten(FileOpts)), 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) -> case is_string(File) of true -> {File, []}; false -> File end; transform_include_option({include_config_file, Filename}) -> {Filename, []}; transform_include_option({include_config_file, Filename, Options}) -> {Filename, Options}. include_config_file(Filename, Options) -> Included_terms = get_plain_terms_file(Filename), Disallow = proplists:get_value(disallow, Options, []), Included_terms2 = delete_disallowed(Disallow, Included_terms), Allow_only = proplists:get_value(allow_only, Options, all), keep_only_allowed(Allow_only, Included_terms2). %% @doc Filter from the list of terms the disallowed. %% Returns a sublist of Terms without the ones which first element is %% included in Disallowed. %% @spec (Disallowed::[atom()], Terms::[term()]) -> [term()] delete_disallowed(Disallowed, Terms) -> lists:foldl( fun(Dis, Ldis) -> delete_disallowed2(Dis, Ldis) end, Terms, Disallowed). delete_disallowed2(Disallowed, [H|T]) -> case element(1, H) of Disallowed -> ?WARNING_MSG("The option '~p' is disallowed, " "and will not be accepted", [Disallowed]), delete_disallowed2(Disallowed, T); _ -> [H|delete_disallowed2(Disallowed, T)] end; delete_disallowed2(_, []) -> []. %% @doc Keep from the list only the allowed terms. %% Returns a sublist of Terms with only the ones which first element is %% included in Allowed. %% @spec (Allowed::[atom()], Terms::[term()]) -> [term()] keep_only_allowed(all, Terms) -> Terms; keep_only_allowed(Allowed, Terms) -> {As, NAs} = lists:partition( fun(Term) -> lists:member(element(1, Term), Allowed) end, Terms), [?WARNING_MSG("This option is not allowed, " "and will not be accepted:~n~p", [NA]) || NA <- NAs], As. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Support for Macro %% @doc Replace the macros with their defined values. %% @spec (Terms::[term()]) -> [term()] replace_macros(Terms) -> {TermsOthers, Macros} = split_terms_macros(Terms), replace(TermsOthers, Macros). %% @doc Split Terms into normal terms and macro definitions. %% @spec (Terms) -> {Terms, Macros} %% Terms = [term()] %% Macros = [macro()] split_terms_macros(Terms) -> lists:foldl( fun(Term, {TOs, Ms}) -> case Term of {define_macro, Key, Value} -> case is_correct_macro({Key, Value}) of true -> {TOs, Ms++[{Key, Value}]}; false -> exit({macro_not_properly_defined, Term}) end; {define_macro, KeyVals} -> case lists:all(fun is_correct_macro/1, KeyVals) of true -> {TOs, Ms ++ KeyVals}; false -> exit({macros_not_properly_defined, Term}) end; Term -> {TOs ++ [Term], Ms} end end, {[], []}, Terms). is_correct_macro({Key, _Val}) -> is_atom(Key) and is_all_uppercase(Key); is_correct_macro(_) -> false. %% @doc Recursively replace in Terms macro usages with the defined value. %% @spec (Terms, Macros) -> Terms %% Terms = [term()] %% Macros = [macro()] replace([], _) -> []; replace([Term|Terms], Macros) -> [replace_term(Term, Macros) | replace(Terms, Macros)]; replace(Term, Macros) -> replace_term(Term, Macros). replace_term(Key, Macros) when is_atom(Key) -> case is_all_uppercase(Key) of true -> case proplists:get_value(Key, Macros) of undefined -> exit({undefined_macro, Key}); Value -> Value end; false -> Key end; replace_term({use_macro, Key, Value}, Macros) -> proplists:get_value(Key, Macros, Value); replace_term(Term, Macros) when is_list(Term) -> replace(Term, Macros); replace_term(Term, Macros) when is_tuple(Term) -> List = tuple_to_list(Term), List2 = replace(List, Macros), list_to_tuple(List2); replace_term(Term, _) -> Term. is_all_uppercase(Atom) -> String = erlang:atom_to_list(Atom), lists:all(fun(C) when C >= $a, C =< $z -> false; (_) -> true end, String). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Process terms process_term(Term, State) -> case Term of {host_config, HostTerms} -> lists:foldl( fun({Host, Terms}, AccState) -> lists:foldl(fun(T, S) -> process_host_term(T, Host, S, set) end, AccState, Terms) end, State, HostTerms); {append_host_config, HostTerms} -> lists:foldl( fun({Host, Terms}, AccState) -> lists:foldl(fun(T, S) -> process_host_term(T, Host, S, append) end, AccState, Terms) end, State, HostTerms); _ -> process_host_term(Term, global, State, set) end. process_host_term(Term, Host, State, Action) -> case Term of {modules, Modules} when Action == set -> set_option({modules, Host}, replace_modules(Modules), State); {modules, Modules} when Action == append -> append_option({modules, Host}, replace_modules(Modules), State); {host, _} -> State; {hosts, _} -> State; {Opt, Val} when Action == set -> set_option({Opt, Host}, Val, State); {Opt, Val} when Action == append -> append_option({Opt, Host}, Val, State); Opt -> ?WARNING_MSG("Ignore invalid (outdated?) option ~p", [Opt]), State end. set_option(Opt, Val, State) -> State#state{opts = [#local_config{key = Opt, value = Val} | State#state.opts]}. append_option({Opt, Host}, Val, State) -> GlobalVals = lists:flatmap( fun(#local_config{key = {O, global}, value = V}) when O == Opt -> if is_list(V) -> V; true -> [V] end; (_) -> [] end, State#state.opts), NewVal = if is_list(Val) -> Val ++ GlobalVals; true -> [Val|GlobalVals] end, set_option({Opt, Host}, NewVal, State). set_opts(State) -> Opts = State#state.opts, F = fun() -> lists:foreach(fun(R) -> mnesia:write(R) end, Opts) end, case mnesia:transaction(F) of {atomic, _} -> ok; {aborted,{no_exists,Table}} -> MnesiaDirectory = mnesia:system_info(directory), ?ERROR_MSG("Error reading Mnesia database spool files:~n" "The Mnesia database couldn't read the spool file for the table '~p'.~n" "ejabberd needs read and write access in the directory:~n ~s~n" "Maybe the problem is a change in the computer hostname,~n" "or a change in the Erlang node name, which is currently:~n ~p~n" "Check the ejabberd guide for details about changing the~n" "computer hostname or Erlang node name.~n", [Table, MnesiaDirectory, node()]), exit("Error reading Mnesia database") end. add_global_option(Opt, Val) -> add_option(Opt, Val). add_local_option(Opt, Val) -> add_option(Opt, Val). add_option(Opt, Val) when is_atom(Opt) -> add_option({Opt, global}, Val); add_option(Opt, Val) -> mnesia:transaction(fun() -> mnesia:write(#local_config{key = Opt, value = Val}) end). -spec prepare_opt_val(any(), any(), check_fun(), any()) -> any(). prepare_opt_val(Opt, Val, F, Default) -> Res = case F of {Mod, Fun} -> catch Mod:Fun(Val); _ -> catch F(Val) end, case Res of {'EXIT', _} -> ?INFO_MSG("Configuration problem:~n" "** Option: ~s~n" "** Invalid value: ~s~n" "** Using as fallback: ~s", [format_term(Opt), format_term(Val), format_term(Default)]), Default; _ -> Res end. -type check_fun() :: fun((any()) -> any()) | {module(), atom()}. -spec get_global_option(any(), check_fun()) -> any(). get_global_option(Opt, F) -> get_option(Opt, F, undefined). -spec get_global_option(any(), check_fun(), any()) -> any(). get_global_option(Opt, F, Default) -> get_option(Opt, F, Default). -spec get_local_option(any(), check_fun()) -> any(). get_local_option(Opt, F) -> get_option(Opt, F, undefined). -spec get_local_option(any(), check_fun(), any()) -> any(). get_local_option(Opt, F, Default) -> get_option(Opt, F, Default). -spec get_option(any(), check_fun()) -> any(). get_option(Opt, F) -> get_option(Opt, F, undefined). -spec get_option(any(), check_fun(), any()) -> any(). get_option(Opt, F, Default) when is_atom(Opt) -> get_option({Opt, global}, F, Default); get_option(Opt, F, Default) -> case Opt of {O, global} when is_atom(O) -> ok; {O, H} when is_atom(O), is_binary(H) -> ok; _ -> ?WARNING_MSG("Option ~p has invalid (outdated?) format. " "This is likely a bug", [Opt]) end, case ets:lookup(local_config, Opt) of [#local_config{value = Val}] -> prepare_opt_val(Opt, Val, F, Default); _ -> case Opt of {Key, Host} when Host /= global -> get_option({Key, global}, F, Default); _ -> Default end end. 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 Opts when is_list(Opts) -> lists:foldl( fun(Opt, Acc) -> dict:append(Opt, Mod, Acc) end, D, Opts); {'EXIT', {undef, _}} -> D end end, dict:new(), [?MODULE|ExtMods++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("unknown option '~s' will be likely" " ignored", [Opt]), true 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 get_vh_by_auth_method(AuthMethod) -> mnesia:dirty_select(local_config, [{#local_config{key = {auth_method, '$1'}, value=AuthMethod},[],['$1']}]). %% @spec (Path::string()) -> true | false is_file_readable(Path) -> case file:read_file_info(Path) of {ok, FileInfo} -> case {FileInfo#file_info.type, FileInfo#file_info.access} of {regular, read} -> true; {regular, read_write} -> true; _ -> false end; {error, _Reason} -> false end. get_version() -> case application:get_key(ejabberd, vsn) of undefined -> ""; {ok, Vsn} -> list_to_binary(Vsn) end. -spec get_myhosts() -> [binary()]. get_myhosts() -> get_option(hosts, fun(V) -> V end). -spec get_mylang() -> binary(). get_mylang() -> get_option( language, fun iolist_to_binary/1, <<"en">>). replace_module(mod_announce_odbc) -> {mod_announce, odbc}; replace_module(mod_blocking_odbc) -> {mod_blocking, odbc}; replace_module(mod_caps_odbc) -> {mod_caps, odbc}; replace_module(mod_irc_odbc) -> {mod_irc, odbc}; replace_module(mod_last_odbc) -> {mod_last, odbc}; replace_module(mod_muc_odbc) -> {mod_muc, odbc}; replace_module(mod_offline_odbc) -> {mod_offline, odbc}; replace_module(mod_privacy_odbc) -> {mod_privacy, odbc}; replace_module(mod_private_odbc) -> {mod_private, odbc}; 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); 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). %% Elixir module naming %% ==================== %% If module name start with uppercase letter, this is an Elixir module: is_elixir_module(Module) -> case atom_to_list(Module) of [H|_] when H >= 65, H =< 90 -> true; _ ->false end. %% We assume we know this is an elixir module expand_elixir_module(Module) -> case atom_to_list(Module) of %% Module name already specified as an Elixir from Erlang module name "Elixir." ++ _ -> Module; %% if start with uppercase letter, this is an Elixir module: Append 'Elixir.' to module name. ModuleString -> list_to_atom("Elixir." ++ ModuleString) end. strings_to_binary([]) -> []; strings_to_binary(L) when is_list(L) -> case is_string(L) of true -> list_to_binary(L); false -> strings_to_binary1(L) end; strings_to_binary({A, B, C, D}) when is_integer(A), is_integer(B), is_integer(C), is_integer(D) -> {A, B, C ,D}; strings_to_binary(T) when is_tuple(T) -> list_to_tuple(strings_to_binary1(tuple_to_list(T))); strings_to_binary(X) -> X. strings_to_binary1([El|L]) -> [strings_to_binary(El)|strings_to_binary1(L)]; strings_to_binary1([]) -> []; strings_to_binary1(T) -> T. is_string([C|T]) when (C >= 0) and (C =< 255) -> is_string(T); is_string([]) -> true; is_string(_) -> false. binary_to_strings(B) when is_binary(B) -> binary_to_list(B); binary_to_strings([H|T]) -> [binary_to_strings(H)|binary_to_strings(T)]; binary_to_strings(T) when is_tuple(T) -> list_to_tuple(binary_to_strings(tuple_to_list(T))); binary_to_strings(T) -> T. format_term(Bin) when is_binary(Bin) -> io_lib:format("\"~s\"", [Bin]); format_term(S) when is_list(S), S /= [] -> case lists:all(fun(C) -> (C>=0) and (C=<255) end, S) of true -> io_lib:format("\"~s\"", [S]); false -> io_lib:format("~p", [binary_to_strings(S)]) end; format_term(T) -> io_lib:format("~p", [binary_to_strings(T)]). transform_terms(Terms) -> %% We could check all ejabberd beams, but this %% slows down start-up procedure :( Mods = [mod_register, mod_last, ejabberd_s2s, ejabberd_listener, ejabberd_odbc_sup, shaper, ejabberd_s2s_out, acl, ejabberd_config], collect_options(transform_terms(Mods, Terms)). transform_terms([Mod|Mods], Terms) -> case catch Mod:transform_options(Terms) of {'EXIT', _} = Err -> ?ERROR_MSG("Failed to transform terms by ~p: ~p", [Mod, Err]), transform_terms(Mods, Terms); NewTerms -> transform_terms(Mods, NewTerms) end; transform_terms([], NewTerms) -> NewTerms. transform_module_options(Module, Opts) -> Opts1 = gen_iq_handler:transform_module_options(Opts), try Module:transform_module_options(Opts1) catch error:undef -> Opts1 end. compact(Cfg) -> Opts = [{K, V} || #local_config{key = K, value = V} <- Cfg], {GOpts, HOpts} = split_by_hosts(Opts), [#local_config{key = {O, global}, value = V} || {O, V} <- GOpts] ++ lists:flatmap( fun({Host, OptVal}) -> case lists:member(OptVal, GOpts) of true -> []; false -> [#local_config{key = {Opt, Host}, value = Val} || {Opt, Val} <- OptVal] end end, lists:flatten(HOpts)). split_by_hosts(Opts) -> Opts1 = orddict:to_list( lists:foldl( fun({{Opt, Host}, Val}, D) -> orddict:append(Host, {Opt, Val}, D) end, orddict:new(), Opts)), case lists:keytake(global, 1, Opts1) of {value, {global, GlobalOpts}, HostOpts} -> {GlobalOpts, HostOpts}; _ -> {[], Opts1} end. collect_options(Opts) -> {D, InvalidOpts} = lists:foldl( fun({K, V}, {D, Os}) when is_list(V) -> {orddict:append_list(K, V, D), Os}; ({K, V}, {D, Os}) -> {orddict:store(K, V, D), Os}; (Opt, {D, Os}) -> {D, [Opt|Os]} end, {orddict:new(), []}, Opts), InvalidOpts ++ orddict:to_list(D). transform_options(Opts) -> Opts1 = lists:foldl(fun transform_options/2, [], Opts), {HOpts, Opts2} = lists:mapfoldl( fun({host_config, O}, Os) -> {[O], Os}; (O, Os) -> {[], [O|Os]} end, [], Opts1), {AHOpts, Opts3} = lists:mapfoldl( fun({append_host_config, O}, Os) -> {[O], Os}; (O, Os) -> {[], [O|Os]} end, [], Opts2), HOpts1 = case collect_options(lists:flatten(HOpts)) of [] -> []; HOs -> [{host_config, [{H, transform_terms(O)} || {H, O} <- HOs]}] end, AHOpts1 = case collect_options(lists:flatten(AHOpts)) of [] -> []; AHOs -> [{append_host_config, [{H, transform_terms(O)} || {H, O} <- AHOs]}] end, HOpts1 ++ AHOpts1 ++ Opts3. transform_options({domain_certfile, Domain, CertFile}, Opts) -> ?WARNING_MSG("Option 'domain_certfile' now should be defined " "per virtual host or globally. The old format is " "still supported but it is better to fix your config", []), [{host_config, [{Domain, [{domain_certfile, CertFile}]}]}|Opts]; transform_options(Opt, Opts) when Opt == override_global; Opt == override_local; Opt == override_acls -> ?WARNING_MSG("Ignoring '~s' option which has no effect anymore", [Opt]), Opts; transform_options({host_config, Host, HOpts}, Opts) -> {AddOpts, HOpts1} = lists:mapfoldl( fun({{add, Opt}, Val}, Os) -> ?WARNING_MSG("Option 'add' is deprecated. " "The option is still supported " "but it is better to fix your config: " "use 'append_host_config' instead.", []), {[{Opt, Val}], Os}; (O, Os) -> {[], [O|Os]} end, [], HOpts), [{append_host_config, [{Host, lists:flatten(AddOpts)}]}, {host_config, [{Host, HOpts1}]}|Opts]; transform_options({define_macro, Macro, Val}, Opts) -> [{define_macro, [{Macro, Val}]}|Opts]; transform_options({include_config_file, _} = Opt, Opts) -> [{include_config_file, [transform_include_option(Opt)]} | Opts]; transform_options({include_config_file, _, _} = Opt, Opts) -> [{include_config_file, [transform_include_option(Opt)]} | Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. -spec convert_table_to_binary(atom(), [atom()], atom(), fun(), fun()) -> ok. convert_table_to_binary(Tab, Fields, Type, DetectFun, ConvertFun) -> case is_table_still_list(Tab, DetectFun) of true -> ?INFO_MSG("Converting '~s' table from strings to binaries.", [Tab]), TmpTab = list_to_atom(atom_to_list(Tab) ++ "_tmp_table"), catch mnesia:delete_table(TmpTab), case mnesia:create_table(TmpTab, [{disc_only_copies, [node()]}, {type, Type}, {local_content, true}, {record_name, Tab}, {attributes, Fields}]) of {atomic, ok} -> mnesia:transform_table(Tab, ignore, Fields), case mnesia:transaction( fun() -> mnesia:write_lock_table(TmpTab), mnesia:foldl( fun(R, _) -> NewR = ConvertFun(R), mnesia:dirty_write(TmpTab, NewR) end, ok, Tab) end) of {atomic, ok} -> mnesia:clear_table(Tab), case mnesia:transaction( fun() -> mnesia:write_lock_table(Tab), mnesia:foldl( fun(R, _) -> mnesia:dirty_write(R) end, ok, TmpTab) end) of {atomic, ok} -> mnesia:delete_table(TmpTab); Err -> report_and_stop(Tab, Err) end; Err -> report_and_stop(Tab, Err) end; Err -> report_and_stop(Tab, Err) end; false -> ok end. is_table_still_list(Tab, DetectFun) -> is_table_still_list(Tab, DetectFun, mnesia:dirty_first(Tab)). is_table_still_list(_Tab, _DetectFun, '$end_of_table') -> false; is_table_still_list(Tab, DetectFun, Key) -> Rs = mnesia:dirty_read(Tab, Key), Res = lists:foldl(fun(_, true) -> true; (_, false) -> false; (R, _) -> case DetectFun(R) of '$next' -> '$next'; El -> is_list(El) end end, '$next', Rs), case Res of true -> true; false -> false; '$next' -> is_table_still_list(Tab, DetectFun, mnesia:dirty_next(Tab, Key)) end. report_and_stop(Tab, Err) -> ErrTxt = lists:flatten( io_lib:format( "Failed to convert '~s' table to binary: ~p", [Tab, Err])), ?CRITICAL_MSG(ErrTxt, []), timer:sleep(1000), halt(string:substr(ErrTxt, 1, 199)). emit_deprecation_warning(Module, NewModule, DBType) -> ?WARNING_MSG("Module ~s is deprecated, use ~s with 'db_type: ~s'" " instead", [Module, NewModule, DBType]). emit_deprecation_warning(Module, NewModule) -> case is_elixir_module(NewModule) of %% Do not emit deprecation warning for Elixir true -> ok; false -> ?WARNING_MSG("Module ~s is deprecated, use ~s instead", [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( fun(H) -> iolist_to_binary(H) end, L) end; opt_type(language) -> fun iolist_to_binary/1; opt_type(_) -> [hide_sensitive_log_data, hosts, language]. -spec may_hide_data(string()) -> string(); (binary()) -> binary(). 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. ejabberd-16.01/src/mod_fail2ban.erl0000644000232200023220000001511112645157216017445 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author 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 %%% 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_fail2ban). -behaviour(gen_mod). -behaviour(gen_server). %% API -export([start_link/2, start/2, stop/1, c2s_auth_result/4, check_bl_c2s/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"). -include("logger.hrl"). -define(C2S_AUTH_BAN_LIFETIME, 3600). %% 1 hour -define(C2S_MAX_AUTH_FAILURES, 20). -define(CLEAN_INTERVAL, timer:minutes(10)). -record(state, {host = <<"">> :: binary()}). %%%=================================================================== %%% API %%%=================================================================== start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). c2s_auth_result(false, _User, LServer, {Addr, _Port}) -> 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 = 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}); [] -> ets:insert(failed_auth, {Addr, 1, UnbanTS, MaxFailures}) end end; c2s_auth_result(true, _User, _Server, _AddrPort) -> ok. check_bl_c2s(_Acc, Addr, Lang) -> case ets:lookup(failed_auth, Addr) of [{Addr, N, TS, MaxFailures}] when N >= MaxFailures -> case TS > p1_time_compat:system_time(seconds) of true -> IP = jlib:ip_to_list(Addr), UnbanDate = format_date( 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 " "will be unblocked at ~s UTC", [N, IP, UnbanDate]), ReasonT = io_lib:fwrite( translate:translate( Lang, <<"Too many (~p) failed authentications " "from this IP address (~s). The address " "will be unblocked at ~s UTC">>), [N, IP, UnbanDate]), {stop, {true, LogReason, ReasonT}}; false -> ets:delete(failed_auth, Addr), false end; _ -> false end. %%==================================================================== %% gen_mod callbacks %%==================================================================== start(Host, Opts) -> catch ets:new(failed_auth, [named_table, public]), Proc = gen_mod:get_module_proc(Host, ?MODULE), 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, ?MODULE), supervisor:terminate_child(ejabberd_sup, Proc), supervisor:delete_child(ejabberd_sup, Proc). %%%=================================================================== %%% gen_server callbacks %%%=================================================================== init([Host, _Opts]) -> ejabberd_hooks:add(c2s_auth_result, Host, ?MODULE, c2s_auth_result, 100), ejabberd_hooks:add(check_bl_c2s, ?MODULE, check_bl_c2s, 100), erlang:send_after(?CLEAN_INTERVAL, self(), clean), {ok, #state{host = Host}}. handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. handle_cast(_Msg, State) -> ?ERROR_MSG("got unexpected cast = ~p", [_Msg]), {noreply, State}. handle_info(clean, State) -> ?DEBUG("cleaning ~p ETS table", [failed_auth]), Now = p1_time_compat:system_time(seconds), ets:select_delete( failed_auth, ets:fun2ms(fun({_, _, UnbanTS, _}) -> UnbanTS =< Now end)), erlang:send_after(?CLEAN_INTERVAL, self(), clean), {noreply, State}; handle_info(_Info, State) -> ?ERROR_MSG("got unexpected info = ~p", [_Info]), {noreply, State}. terminate(_Reason, #state{host = Host}) -> ejabberd_hooks:delete(c2s_auth_result, Host, ?MODULE, c2s_auth_result, 100), case is_loaded_at_other_hosts(Host) of true -> ok; false -> ejabberd_hooks:delete(check_bl_c2s, ?MODULE, check_bl_c2s, 100), ets:delete(failed_auth) end. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%%=================================================================== %%% 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. is_loaded_at_other_hosts(Host) -> lists:any( fun(VHost) when VHost == Host -> false; (VHost) -> 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]). 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]. ejabberd-16.01/src/node_hometree.erl0000644000232200023220000001367412645157216017761 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_hometree.erl %%% Author : Christophe Romain %%% Purpose : Standard tree ordered node plugin %%% Created : 1 Dec 2007 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_hometree). -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]). 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) -> node_flat:terminate(Host, ServerHost). options() -> node_flat:options(). features() -> node_flat:features(). %% @doc Checks if the current user has the permission to create the requested node %%

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. 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 as a children of its %% parent node

create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> LOwner = 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}. create_node(Nidx, Owner) -> node_flat:create_node(Nidx, Owner). delete_node(Nodes) -> node_flat:delete_node(Nodes). 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). %% @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], <<"/">>)). ejabberd-16.01/src/ejabberd.erl0000644000232200023220000001144412645157216016673 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd.erl %%% Author : Alexey Shchepin %%% Purpose : ejabberd wrapper: start / stop %%% Created : 16 Nov 2002 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). -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]). -include("logger.hrl"). start() -> %%ejabberd_cover:start(), application:start(ejabberd). stop() -> application:stop(ejabberd). %%ejabberd_cover:stop(). %% @spec () -> false | string() get_pid_file() -> case os:getenv("EJABBERD_PID_PATH") of false -> false; "" -> false; Path -> Path end. start_app(App) -> start_app(App, temporary). start_app(App, Type) -> StartFlag = not is_loaded(), start_app(App, Type, StartFlag). check_app(App) -> StartFlag = not is_loaded(), spawn(fun() -> check_app_modules(App, StartFlag) end), ok. is_loaded() -> Apps = application:which_applications(), lists:keymember(ejabberd, 1, Apps). start_app(App, Type, StartFlag) when not is_list(App) -> start_app([App], Type, StartFlag); start_app([App|Apps], Type, StartFlag) -> case application:start(App) of ok -> spawn(fun() -> check_app_modules(App, StartFlag) end), start_app(Apps, Type, StartFlag); {error, {already_started, _}} -> start_app(Apps, Type, StartFlag); {error, {not_started, DepApp}} -> case lists:member(DepApp, [App|Apps]) of true -> Reason = io_lib:format( "failed to start application '~p': " "circular dependency on '~p' detected", [App, DepApp]), exit_or_halt(Reason, StartFlag); false -> start_app([DepApp,App|Apps], Type, StartFlag) end; Err -> Reason = io_lib:format("failed to start application '~p': ~p", [App, Err]), exit_or_halt(Reason, StartFlag) end; start_app([], _Type, _StartFlag) -> ok. check_app_modules(App, StartFlag) -> {A, B, C} = p1_time_compat:timestamp(), random:seed(A, B, C), sleep(5000), case application:get_key(App, modules) of {ok, Mods} -> lists:foreach( fun(Mod) -> case code:which(Mod) of non_existing -> File = get_module_file(App, Mod), Reason = io_lib:format( "couldn't find module ~s " "needed for application '~p'", [File, App]), exit_or_halt(Reason, StartFlag); _ -> sleep(10) end end, Mods); _ -> %% No modules? This is strange ok end. exit_or_halt(Reason, StartFlag) -> ?CRITICAL_MSG(Reason, []), if StartFlag -> %% Wait for the critical message is written in the console/log timer:sleep(1000), halt(string:substr(lists:flatten(Reason), 1, 199)); true -> erlang:error(application_start_failed) end. sleep(N) -> timer:sleep(random:uniform(N)). get_module_file(App, Mod) -> BaseName = atom_to_list(Mod), case code:lib_dir(App, ebin) of {error, _} -> BaseName; Dir -> filename:join([Dir, BaseName ++ ".beam"]) end. ejabberd-16.01/src/ejabberd_rdbms.erl0000644000232200023220000000640412645157216020062 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_rdbms.erl %%% Author : Mickael Remond %%% Purpose : Manage the start of the database modules when needed %%% Created : 31 Jan 2003 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_rdbms). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -export([start/0, opt_type/1]). -include("ejabberd.hrl"). -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 -> start_hosts(); false -> ok end. %% Start relationnal DB module on the nodes where it is needed start_hosts() -> lists:foreach(fun (Host) -> case needs_odbc(Host) of {true, App} -> start_odbc(Host, App); false -> ok end end, ?MYHOSTS). %% Start the ODBC module on the given host start_odbc(Host, App) -> ejabberd:start_app(App), Supervisor_name = gen_mod:get_module_proc(Host, ejabberd_odbc_sup), ChildSpec = {Supervisor_name, {ejabberd_odbc_sup, start_link, [Host]}, transient, infinity, supervisor, [ejabberd_odbc_sup]}, case supervisor:start_child(ejabberd_sup, ChildSpec) of {ok, _PID} -> ok; _Error -> ?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying." "..~n", [Supervisor_name, _Error]), start_odbc(Host, App) end. %% Returns {true, App} if we have configured odbc for the given host needs_odbc(Host) -> LHost = jid:nameprep(Host), case ejabberd_config:get_option({odbc_type, LHost}, 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. opt_type(odbc_type) -> fun (mysql) -> mysql; (pgsql) -> pgsql; (sqlite) -> sqlite; (mssql) -> mssql; (odbc) -> odbc end; opt_type(_) -> [odbc_type]. ejabberd-16.01/src/ejabberd_commands.erl0000644000232200023220000005562212645157216020562 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_commands.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. %%% %%%---------------------------------------------------------------------- %%% @headerfile "ejabberd_commands.hrl" %%% @doc Management of ejabberd commands. %%% %%% An ejabberd command is an abstract function identified by a name, %%% with a defined number and type of calling arguments and type of %%% result, that can be defined in any Erlang module and executed %%% using any valid frontend. %%% %%% %%% == Define a new ejabberd command == %%% %%% ejabberd commands can be defined and registered in %%% any Erlang module. %%% %%% Some commands are procedures; and their purpose is to perform an %%% action in the server, so the command result is only some result %%% code or result tuple. Other commands are inspectors, and their %%% purpose is to gather some information about the server and return %%% a detailed response: it can be integer, string, atom, tuple, list %%% or a mix of those ones. %%% %%% The arguments and result of an ejabberd command are strictly %%% defined. The number and format of the arguments provided when %%% calling an ejabberd command must match the definition of that %%% command. The format of the result provided by an ejabberd command %%% must be exactly its definition. For example, if a command is said %%% to return an integer, it must always return an integer (except in %%% case of a crash). %%% %%% If you are developing an Erlang module that will run inside %%% ejabberd and you want to provide a new ejabberd command to %%% administer some task related to your module, you only need to: %%% implement a function, define the command, and register it. %%% %%% %%% === Define a new ejabberd command === %%% %%% An ejabberd command is defined using the Erlang record %%% 'ejabberd_commands'. This record has several elements that you %%% must define. Note that 'tags', 'desc' and 'longdesc' are optional. %%% %%% For example let's define an ejabberd command 'pow' that gets the %%% integers 'base' and 'exponent'. Its result will be an integer %%% 'power': %%% %%%
#ejabberd_commands{name = pow, tags = [test],
%%%                 desc = "Return the power of base for exponent",
%%%                 longdesc = "This is an example command. The formula is:\n"
%%%                 "  power = base ^ exponent",
%%%                 module = ?MODULE, function = pow,
%%%                 args = [{base, integer}, {exponent, integer}],
%%%                 result = {power, integer}}
%%% %%% %%% === Implement the function associated to the command === %%% %%% Now implement a function in your module that matches the arguments %%% and result of the ejabberd command. %%% %%% For example the function calc_power gets two integers Base and %%% Exponent. It calculates the power and rounds to an integer: %%% %%%
calc_power(Base, Exponent) ->
%%%    PowFloat = math:pow(Base, Exponent),
%%%    round(PowFloat).
%%% %%% Since this function will be called by ejabberd_commands, it must be exported. %%% Add to your module: %%%
-export([calc_power/2]).
%%% %%% Only some types of result formats are allowed. %%% If the format is defined as 'rescode', then your function must return: %%% ok | true | atom() %%% where the atoms ok and true as considered positive answers, %%% and any other response atom is considered negative. %%% %%% If the format is defined as 'restuple', then the command must return: %%% {rescode(), string()} %%% %%% If the format is defined as '{list, something()}', then the command %%% must return a list of something(). %%% %%% %%% === Register the command === %%% %%% Define this function and put inside the #ejabberd_command you %%% defined in the beginning: %%% %%%
commands() ->
%%%    [
%%%
%%%    ].
%%% %%% You need to include this header file in order to use the record: %%% %%%
-include("ejabberd_commands.hrl").
%%% %%% When your module is initialized or started, register your commands: %%% %%%
ejabberd_commands:register_commands(commands()),
%%% %%% And when your module is stopped, unregister your commands: %%% %%%
ejabberd_commands:unregister_commands(commands()),
%%% %%% That's all! Now when your module is started, the command will be %%% registered and any frontend can access it. For example: %%% %%%
$ ejabberdctl help pow
%%%
%%%   Command Name: pow
%%%
%%%   Arguments: base::integer
%%%              exponent::integer
%%%
%%%   Returns: power::integer
%%%
%%%   Tags: test
%%%
%%%   Description: Return the power of base for exponent
%%%
%%% This is an example command. The formula is:
%%%  power = base ^ exponent
%%%
%%% $ ejabberdctl pow 3 4
%%% 81
%%% 
%%% %%% %%% == Execute an ejabberd command == %%% %%% ejabberd commands are mean to be executed using any valid %%% frontend. An ejabberd commands is implemented in a regular Erlang %%% function, so it is also possible to execute this function in any %%% Erlang module, without dealing with the associated ejabberd %%% commands. %%% %%% %%% == Frontend to ejabberd commands == %%% %%% Currently there are two frontends to ejabberd commands: the shell %%% script {@link ejabberd_ctl. ejabberdctl}, and the XML-RPC server %%% ejabberd_xmlrpc. %%% %%% %%% === ejabberdctl as a frontend to ejabberd commands === %%% %%% It is possible to use ejabberdctl to get documentation of any %%% command. But ejabberdctl does not support all the argument types %%% allowed in ejabberd commands, so there are some ejabberd commands %%% that cannot be executed using ejabberdctl. %%% %%% Also note that the ejabberdctl shell administration script also %%% manages ejabberdctl commands, which are unrelated to ejabberd %%% commands and can only be executed using ejabberdctl. %%% %%% %%% === ejabberd_xmlrpc as a frontend to ejabberd commands === %%% %%% ejabberd_xmlrpc provides an XML-RPC server to execute ejabberd commands. %%% ejabberd_xmlrpc is a contributed module published in ejabberd-modules SVN. %%% %%% Since ejabberd_xmlrpc does not provide any method to get documentation %%% of the ejabberd commands, please use ejabberdctl to know which %%% commands are available, and their usage. %%% %%% The number and format of the arguments provided when calling an %%% ejabberd command must match the definition of that command. Please %%% make sure the XML-RPC call provides the required arguments, with %%% the specified format. The order of the arguments in an XML-RPC %%% call is not important, because all the data is tagged and will be %%% correctly prepared by ejabberd_xmlrpc before executing the ejabberd %%% command. %%% TODO: consider this feature: %%% All commands are catched. If an error happens, return the restuple: %%% {error, flattened error string} %%% This means that ecomm call APIs (ejabberd_ctl, ejabberd_xmlrpc) need to allows this. %%% And ejabberd_xmlrpc must be prepared to handle such an unexpected response. -module(ejabberd_commands). -author('badlop@process-one.net'). -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, opt_type/1 ]). -include("ejabberd_commands.hrl"). -include("ejabberd.hrl"). -include("logger.hrl"). -define(POLICY_ACCESS, '$policy'). init() -> ets:new(ejabberd_commands, [named_table, set, public, {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. %% @doc Register ejabberd commands. %% If a command is already registered, a warning is printed and the old command is preserved. register_commands(Commands) -> lists:foreach( fun(Command) -> case ets:insert_new(ejabberd_commands, Command) of true -> ok; false -> ?DEBUG("This command is already defined:~n~p", [Command]) end end, Commands). -spec unregister_commands([ejabberd_commands()]) -> ok. %% @doc Unregister ejabberd commands. unregister_commands(Commands) -> lists:foreach( fun(Command) -> ets:delete_object(ejabberd_commands, Command) end, Commands). -spec list_commands() -> [{atom(), [aterm()], string()}]. %% @doc Get a list of all the available commands, arguments and description. list_commands() -> Commands = ets:match(ejabberd_commands, #ejabberd_commands{name = '$1', args = '$2', desc = '$3', _ = '_'}), [{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, user]] when Admin; Auth == noauth -> {[{user, binary}, {server, binary} | Args], Result}; [[Args, Result, _]] -> {Args, Result} end. -spec get_command_definition(atom()) -> ejabberd_commands() | command_not_found. %% @doc Get the definition record of a command. get_command_definition(Name) -> case ets:lookup(ejabberd_commands, Name) of [E] -> E; [] -> command_not_found end. %% @spec (Name::atom(), Arguments) -> ResultTerm | {error, command_unknown} %% @doc Execute a command. 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(), Admin::boolean()} %% | noauth %% | admin %% Method = atom() %% Arguments = [any()] %% Error = command_unknown | account_unprivileged | invalid_account_data | no_auth_provided 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(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( 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]). execute_command2(Command, Arguments) -> Module = Command#ejabberd_commands.module, Function = Command#ejabberd_commands.function, ?DEBUG("Executing command ~p:~p with Args=~p", [Module, Function, Arguments]), try apply(Module, Function, Arguments) of Response -> Response catch Problem -> {error, Problem} end. -spec get_tags_commands() -> [{string(), [string()]}]. %% @spec () -> [{Tag::string(), [CommandName::string()]}] %% @doc Get all the tags and associated commands. get_tags_commands() -> CommandTags = ets:match(ejabberd_commands, #ejabberd_commands{ name = '$1', tags = '$2', _ = '_'}), Dict = lists:foldl( fun([CommandNameAtom, CTags], D) -> CommandName = atom_to_list(CommandNameAtom), case CTags of [] -> orddict:append("untagged", CommandName, D); _ -> lists:foldl( fun(TagAtom, DD) -> Tag = atom_to_list(TagAtom), orddict:append(Tag, CommandName, DD) end, D, CTags) end end, orddict:new(), CommandTags), orddict:to_list(Dict). %% ----------------------------- %% Access verification %% ----------------------------- %% @spec (AccessCommands, Auth, Method, Command, Arguments) -> ok %% where %% AccessCommands = [ {Access, CommandNames, Arguments} ] %% Auth = {User::string(), Server::string(), Password::string()} | noauth %% Method = atom() %% Arguments = [any()] %% @doc Check access is allowed to that command. %% At least one AccessCommand must be satisfied. %% It may throw {error, Error} where: %% Error = account_unprivileged | invalid_account_data check_access_commands([], _Auth, _Method, _Command, _Arguments) -> ok; check_access_commands(AccessCommands, Auth, Method, Command1, Arguments) -> Command = case {Command1#ejabberd_commands.policy, Auth} of {user, {_, _, _}} -> Command1; {user, _} -> Command1#ejabberd_commands{ args = [{user, binary}, {server, binary} | Command1#ejabberd_commands.args]}; _ -> Command1 end, AccessCommandsAllowed = lists:filter( fun({Access, Commands, ArgumentRestrictions}) -> case check_access(Command, Access, Auth) of true -> check_access_command(Commands, Command, ArgumentRestrictions, Method, Arguments); false -> false end; ({Access, Commands}) -> ArgumentRestrictions = [], case check_access(Command, Access, Auth) of true -> check_access_command(Commands, Command, ArgumentRestrictions, Method, Arguments); false -> false end end, AccessCommands), case AccessCommandsAllowed of [] -> throw({error, account_unprivileged}); L when is_list(L) -> ok end. -spec check_auth(ejabberd_commands(), noauth) -> noauth_provided; (ejabberd_commands(), {binary(), binary(), binary(), boolean()}) -> {ok, binary(), binary()}. check_auth(_Command, noauth) -> no_auth_provided; 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(Command, ?POLICY_ACCESS, _) when Command#ejabberd_commands.policy == open -> true; check_access(_Command, _Access, admin) -> true; check_access(_Command, _Access, {_User, _Server, _, true}) -> false; check_access(Command, Access, Auth) when Access =/= ?POLICY_ACCESS; Command#ejabberd_commands.policy == open; Command#ejabberd_commands.policy == user -> case check_auth(Command, Auth) of {ok, User, Server} -> check_access2(Access, User, Server); _ -> false end; 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, jid:make(User, Server, <<"">>)) of allow -> true; deny -> false end. check_access_command(Commands, Command, ArgumentRestrictions, Method, Arguments) -> case Commands==all orelse lists:member(Method, Commands) of true -> check_access_arguments(Command, ArgumentRestrictions, Arguments); false -> false end. check_access_arguments(Command, ArgumentRestrictions, Arguments) -> ArgumentsTagged = tag_arguments(Command#ejabberd_commands.args, Arguments), lists:all( fun({ArgName, ArgAllowedValue}) -> %% If the call uses the argument, check the value is acceptable case lists:keysearch(ArgName, 1, ArgumentsTagged) of {value, {ArgName, ArgValue}} -> ArgValue == ArgAllowedValue; false -> true end end, ArgumentRestrictions). tag_arguments(ArgsDefs, Args) -> lists:zipwith( fun({ArgName, _ArgType}, ArgValue) -> {ArgName, ArgValue} end, ArgsDefs, Args). get_access_commands(undefined) -> Cmds = get_commands(), [{?POLICY_ACCESS, 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, jid:make(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]. ejabberd-16.01/src/ejabberd_auth_pam.erl0000644000232200023220000000737212645157216020556 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% File : ejabberd_auth_pam.erl %%% Author : Evgeniy Khramtsov %%% Purpose : PAM authentication %%% Created : 5 Jul 2007 by Evgeniy 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(ejabberd_auth_pam). -behaviour(ejabberd_config). -author('xram@jabber.ru'). -behaviour(ejabberd_auth). -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, opt_type/1]). start(_Host) -> ejabberd:start_app(p1_pam). set_password(_User, _Server, _Password) -> {error, not_allowed}. check_password(User, 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 end. try_register(_User, _Server, _Password) -> {error, not_allowed}. dirty_get_registered_users() -> []. get_vh_registered_users(_Host) -> []. get_vh_registered_users(_Host, _) -> []. get_vh_registered_users_number(_Host) -> 0. get_vh_registered_users_number(_Host, _) -> 0. get_password(_User, _Server) -> false. get_password_s(_User, _Server) -> <<"">>. %% @spec (User, Server) -> true | false | {error, Error} %% TODO: Improve this function to return an error instead of 'false' when connection to PAM failed is_user_exists(User, Host) -> Service = get_pam_service(Host), UserInfo = case get_pam_userinfotype(Host) of username -> User; jid -> <> end, case catch epam:acct_mgmt(Service, UserInfo) of true -> true; _ -> false end. remove_user(_User, _Server) -> {error, not_allowed}. remove_user(_User, _Server, _Password) -> not_allowed. plain_password_required() -> true. store_type() -> external. %%==================================================================== %% Internal functions %%==================================================================== get_pam_service(Host) -> ejabberd_config:get_option( {pam_service, Host}, fun iolist_to_binary/1, <<"ejabberd">>). get_pam_userinfotype(Host) -> ejabberd_config:get_option( {pam_userinfotype, Host}, fun(username) -> username; (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]. ejabberd-16.01/src/node_pep_odbc.erl0000644000232200023220000002153512645157216017717 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_pep_odbc.erl %%% Author : Christophe Romain %%% Purpose : Standard PubSub PEP plugin with ODBC backend %%% Created : 1 Dec 2007 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. %%% %%%---------------------------------------------------------------------- %%% @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("pubsub.hrl"). -include("jlib.hrl"). -include("logger.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, get_entity_subscriptions_for_send_last/2, get_last_items/3]). init(Host, ServerHost, Opts) -> node_flat_odbc:init(Host, ServerHost, Opts), complain_if_modcaps_disabled(ServerHost), ok. terminate(Host, ServerHost) -> node_flat_odbc:terminate(Host, ServerHost), ok. options() -> [{odbc, true}, {rsm, true} | node_pep:options()]. features() -> [<<"rsm">> | node_pep:features()]. 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_flat_odbc:create_node(Nidx, Owner), {result, {default, broadcast}}. delete_node(Nodes) -> {result, {_, _, Result}} = node_flat_odbc:delete_node(Nodes), {result, {[], Result}}. 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) -> 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_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) -> OwnerKey = jid:tolower(jid:remove_resource(Owner)), node_flat_odbc:get_entity_affiliations(OwnerKey, 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) -> 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), Query = case SubKey of 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_flat_odbc:decode_jid(H), Node = nodetree_tree_odbc:raw_to_node(O, [N, <<"">>, T, I]), {Node, node_flat_odbc:decode_subscriptions(S), node_flat_odbc:decode_jid(J)} end, RItems); _ -> [] end, {result, Reply}. get_entity_subscriptions_for_send_last(_Host, Owner) -> 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), Query = case SubKey of 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_flat_odbc:decode_jid(H), Node = nodetree_tree_odbc:raw_to_node(O, [N, <<"">>, T, I]), {Node, node_flat_odbc:decode_subscriptions(S), node_flat_odbc:decode_jid(J)} end, RItems); _ -> [] end, {result, Reply}. 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_last_items(Nidx, JID, Count) -> node_flat_odbc:get_last_items(Nidx, JID, Count). 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). %%% %%% Internal %%% %% @doc Check mod_caps is enabled, otherwise show warning. %% The PEP plugin for mod_pubsub requires mod_caps to be enabled in the host. %% 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) -> 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. ejabberd-16.01/src/mod_http_fileserver.erl0000644000232200023220000004420512645157216021202 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% File : mod_http_fileserver.erl %%% Author : Massimiliano Mirra %%% Purpose : Simple file server plugin for embedded ejabberd web server %%% Created : %%% %%% %%% 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_http_fileserver). -author('mmirra@process-one.net'). -behaviour(gen_mod). -behaviour(gen_server). %% gen_mod callbacks -export([start/2, stop/1]). %% API -export([start_link/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% 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"). -include("logger.hrl"). -include("ejabberd_http.hrl"). -include("jlib.hrl"). -include_lib("kernel/include/file.hrl"). -record(state, {host, docroot, accesslog, accesslogfd, directory_indices, custom_headers, default_content_type, content_types = []}). -define(PROCNAME, ejabberd_mod_http_fileserver). %% Response is {DataSize, Code, [{HeaderKey, HeaderValue}], Data} -define(HTTP_ERR_FILE_NOT_FOUND, {-1, 404, [], <<"Not found">>}). -define(HTTP_ERR_FORBIDDEN, {-1, 403, [], <<"Forbidden">>}). -define(DEFAULT_CONTENT_TYPE, <<"application/octet-stream">>). -define(DEFAULT_CONTENT_TYPES, [{<<".css">>, <<"text/css">>}, {<<".gif">>, <<"image/gif">>}, {<<".html">>, <<"text/html">>}, {<<".jar">>, <<"application/java-archive">>}, {<<".jpeg">>, <<"image/jpeg">>}, {<<".jpg">>, <<"image/jpeg">>}, {<<".js">>, <<"text/javascript">>}, {<<".png">>, <<"image/png">>}, {<<".svg">>, <<"image/svg+xml">>}, {<<".txt">>, <<"text/plain">>}, {<<".xml">>, <<"application/xml">>}, {<<".xpi">>, <<"application/x-xpinstall">>}, {<<".xul">>, <<"application/vnd.mozilla.xul+xml">>}]). %%==================================================================== %% gen_mod callbacks %%==================================================================== start(Host, Opts) -> Proc = get_proc_name(Host), ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, transient, % if process crashes abruptly, it gets restarted 1000, worker, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop(Host) -> Proc = get_proc_name(Host), gen_server:call(Proc, stop), supervisor:terminate_child(ejabberd_sup, Proc), supervisor:delete_child(ejabberd_sup, Proc). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link(Host, Opts) -> Proc = get_proc_name(Host), gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). %%==================================================================== %% gen_server callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- init([Host, Opts]) -> try initialize(Host, Opts) of {DocRoot, AccessLog, AccessLogFD, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes} -> {ok, #state{host = Host, accesslog = AccessLog, accesslogfd = AccessLogFD, docroot = DocRoot, directory_indices = DirectoryIndices, custom_headers = CustomHeaders, default_content_type = DefaultContentType, content_types = ContentTypes}} catch throw:Reason -> {stop, Reason} end. initialize(Host, Opts) -> DocRoot = gen_mod:get_opt(docroot, Opts, fun(A) -> A end, undefined), check_docroot_defined(DocRoot, Host), DRInfo = check_docroot_exists(DocRoot), check_docroot_is_dir(DRInfo, DocRoot), check_docroot_is_readable(DRInfo, DocRoot), AccessLog = gen_mod:get_opt(accesslog, Opts, fun iolist_to_binary/1, undefined), AccessLogFD = try_open_log(AccessLog, Host), DirectoryIndices = gen_mod:get_opt(directory_indices, Opts, fun(L) when is_list(L) -> L end, []), CustomHeaders = gen_mod:get_opt(custom_headers, Opts, fun(L) when is_list(L) -> L end, []), DefaultContentType = gen_mod:get_opt(default_content_type, Opts, fun iolist_to_binary/1, ?DEFAULT_CONTENT_TYPE), ContentTypes = build_list_content_types( gen_mod:get_opt(content_types, Opts, 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("known content types: ~s", [str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes], <<", ">>)]), {DocRoot, AccessLog, AccessLogFD, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes}. %% @spec (AdminCTs::[CT], Default::[CT]) -> [CT] %% where CT = {Extension::string(), Value} %% Value = string() | undefined %% @doc Return a unified list without duplicates. %% Elements of AdminCTs have more priority. %% If a CT is declared as 'undefined', then it is not included in the result. build_list_content_types(AdminCTsUnsorted, DefaultCTsUnsorted) -> AdminCTs = lists:ukeysort(1, AdminCTsUnsorted), DefaultCTs = lists:ukeysort(1, DefaultCTsUnsorted), CTsUnfiltered = lists:ukeymerge(1, AdminCTs, DefaultCTs), [{Extension, Value} || {Extension, Value} <- CTsUnfiltered, Value /= undefined]. check_docroot_defined(DocRoot, Host) -> case DocRoot of undefined -> throw({undefined_docroot_option, Host}); _ -> ok end. check_docroot_exists(DocRoot) -> case file:read_file_info(DocRoot) of {error, Reason} -> throw({error_access_docroot, DocRoot, Reason}); {ok, FI} -> FI end. check_docroot_is_dir(DRInfo, DocRoot) -> case DRInfo#file_info.type of directory -> ok; _ -> throw({docroot_not_directory, DocRoot}) end. check_docroot_is_readable(DRInfo, DocRoot) -> case DRInfo#file_info.access of read -> ok; read_write -> ok; _ -> throw({docroot_not_readable, DocRoot}) end. try_open_log(undefined, _Host) -> undefined; try_open_log(FN, Host) -> FD = try open_log(FN) of FD1 -> FD1 catch throw:{cannot_open_accesslog, FN, Reason} -> ?ERROR_MSG("Cannot open access log file: ~p~nReason: ~p", [FN, Reason]), undefined end, ejabberd_hooks:add(reopen_log_hook, Host, ?MODULE, reopen_log, 50), FD. %%-------------------------------------------------------------------- %% 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({serve, LocalPath}, _From, State) -> Reply = serve(LocalPath, State#state.docroot, State#state.directory_indices, State#state.custom_headers, State#state.default_content_type, State#state.content_types), {reply, Reply, State}; handle_call(_Request, _From, State) -> {reply, ok, State}. %%-------------------------------------------------------------------- %% Function: handle_cast(Msg, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- handle_cast({add_to_log, FileSize, Code, Request}, State) -> add_to_log(State#state.accesslogfd, FileSize, Code, Request), {noreply, State}; handle_cast(reopen_log, State) -> FD2 = reopen_log(State#state.accesslog, State#state.accesslogfd), {noreply, State#state{accesslogfd = FD2}}; 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) -> close_log(State#state.accesslogfd), ejabberd_hooks:delete(reopen_log_hook, State#state.host, ?MODULE, reopen_log, 50), ok. %%-------------------------------------------------------------------- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} %% Description: Convert process state when code is changed %%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%==================================================================== %% request_handlers callbacks %%==================================================================== %% @spec (LocalPath, Request) -> {HTTPCode::integer(), [Header], Page::string()} %% @doc Handle an HTTP request. %% LocalPath is the part of the requested URL path that is "local to the module". %% Returns the page to be sent back to the client and/or HTTP status code. process(LocalPath, Request) -> ?DEBUG("Requested ~p", [LocalPath]), try gen_server:call(get_proc_name(Request#request.host), {serve, LocalPath}) of {FileSize, Code, Headers, Contents} -> add_to_log(FileSize, Code, Request), {Code, Headers, Contents} catch exit:{noproc, _} -> ?ERROR_MSG("Received an HTTP request with Host ~p, but couldn't find the related " "ejabberd virtual host", [Request#request.host]), ejabberd_web:error(not_found) end. serve(LocalPath, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes) -> FileName = filename:join(filename:split(DocRoot) ++ LocalPath), case file:read_file_info(FileName) of {error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND; {error, enotdir} -> ?HTTP_ERR_FILE_NOT_FOUND; {error, eacces} -> ?HTTP_ERR_FORBIDDEN; {ok, #file_info{type = directory}} -> serve_index(FileName, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes); {ok, FileInfo} -> serve_file(FileInfo, FileName, CustomHeaders, DefaultContentType, ContentTypes) end. %% Troll through the directory indices attempting to find one which %% works, if none can be found, return a 404. serve_index(_FileName, [], _CH, _DefaultContentType, _ContentTypes) -> ?HTTP_ERR_FILE_NOT_FOUND; serve_index(FileName, [Index | T], CH, DefaultContentType, ContentTypes) -> IndexFileName = filename:join([FileName] ++ [Index]), case file:read_file_info(IndexFileName) of {error, _Error} -> serve_index(FileName, T, CH, DefaultContentType, ContentTypes); {ok, #file_info{type = directory}} -> serve_index(FileName, T, CH, DefaultContentType, ContentTypes); {ok, FileInfo} -> serve_file(FileInfo, IndexFileName, CH, DefaultContentType, ContentTypes) end. %% Assume the file exists if we got this far and attempt to read it in %% and serve it up. serve_file(FileInfo, FileName, CustomHeaders, DefaultContentType, ContentTypes) -> ?DEBUG("Delivering: ~s", [FileName]), ContentType = content_type(FileName, DefaultContentType, ContentTypes), {ok, FileContents} = file:read_file(FileName), {FileInfo#file_info.size, 200, [{<<"Server">>, <<"ejabberd">>}, {<<"Last-Modified">>, last_modified(FileInfo)}, {<<"Content-Type">>, ContentType} | CustomHeaders], FileContents}. %%---------------------------------------------------------------------- %% Log file %%---------------------------------------------------------------------- open_log(FN) -> case file:open(FN, [append]) of {ok, FD} -> FD; {error, Reason} -> throw({cannot_open_accesslog, FN, Reason}) end. close_log(FD) -> file:close(FD). reopen_log(undefined, undefined) -> ok; reopen_log(FN, FD) -> close_log(FD), open_log(FN). reopen_log(Host) -> gen_server:cast(get_proc_name(Host), reopen_log). add_to_log(FileSize, Code, Request) -> gen_server:cast(get_proc_name(Request#request.host), {add_to_log, FileSize, Code, Request}). add_to_log(undefined, _FileSize, _Code, _Request) -> ok; add_to_log(File, FileSize, Code, Request) -> {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(), IP = ip_to_string(element(1, Request#request.ip)), Path = join(Request#request.path, "/"), Query = case join(lists:map(fun(E) -> lists:concat([element(1, E), "=", binary_to_list(element(2, E))]) end, Request#request.q), "&") of [] -> ""; String -> [$? | String] end, UserAgent = find_header('User-Agent', Request#request.headers, "-"), Referer = find_header('Referer', Request#request.headers, "-"), %% Pseudo Combined Apache log format: %% 127.0.0.1 - - [28/Mar/2007:18:41:55 +0200] "GET / HTTP/1.1" 302 303 "-" "tsung" %% TODO some fields are harcoded/missing: %% The date/time integers should have always 2 digits. For example day "7" should be "07" %% Month should be 3*letter, not integer 1..12 %% Missing time zone = (`+' | `-') 4*digit %% Missing protocol version: HTTP/1.1 %% For reference: http://httpd.apache.org/docs/2.2/logs.html io:format(File, "~s - - [~p/~p/~p:~p:~p:~p] \"~s /~s~s\" ~p ~p ~p ~p~n", [IP, Day, Month, Year, Hour, Minute, Second, Request#request.method, Path, Query, Code, FileSize, Referer, UserAgent]). find_header(Header, Headers, Default) -> case lists:keysearch(Header, 1, Headers) of {value, {_, Value}} -> Value; false -> Default end. %%---------------------------------------------------------------------- %% Utilities %%---------------------------------------------------------------------- get_proc_name(Host) -> gen_mod:get_module_proc(Host, ?PROCNAME). join([], _) -> <<"">>; join([E], _) -> E; join([H | T], Separator) -> [H2 | T2] = case is_binary(H) of true -> [binary_to_list(I)||I<-[H|T]]; false -> [H | T] end, Res=lists:foldl(fun(E, Acc) -> lists:concat([Acc, Separator, E]) end, H2, T2), case is_binary(H) of true -> list_to_binary(Res); false -> Res end. content_type(Filename, DefaultContentType, ContentTypes) -> Extension = str:to_lower(filename:extension(Filename)), case lists:keysearch(Extension, 1, ContentTypes) of {value, {_, ContentType}} -> ContentType; false -> DefaultContentType end. last_modified(FileInfo) -> Then = FileInfo#file_info.mtime, httpd_util:rfc1123_date(Then). %% Convert IP address tuple to string representation. Accepts either %% IPv4 or IPv6 address tuples. ip_to_string(Address) when size(Address) == 4 -> join(tuple_to_list(Address), "."); 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]. ejabberd-16.01/src/mod_configure2.erl0000644000232200023220000001645312645157216020044 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_configure2.erl %%% Author : Alexey Shchepin %%% Purpose : Support for online configuration of ejabberd %%% Created : 26 Oct 2003 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(mod_configure2). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -define(NS_ECONFIGURE, <<"http://ejabberd.jabberstudio.org/protocol/con" "figure">>). 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_ECONFIGURE, ?MODULE, process_local_iq, IQDisc), ok. stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ECONFIGURE). process_local_iq(From, To, #iq{type = Type, lang = _Lang, sub_el = SubEl} = IQ) -> case acl:match_rule(To#jid.lserver, configure, From) of deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; allow -> 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#iq{type = result, %% sub_el = [{xmlelement, "query", %% [{"xmlns", XMLNS}], []}]}; %% "submit" -> %% XData = jlib:parse_xdata_submit(SubEl), %% case XData of %% invalid -> %% IQ#iq{type = error, %% sub_el = [SubEl, ?ERR_BAD_REQUEST]}; %% _ -> %% Node = %% string:tokens( %% xml:get_tag_attr_s("node", SubEl), %% "/"), %% case set_form(Node, Lang, XData) of %% {result, Res} -> %% IQ#iq{type = result, %% sub_el = [{xmlelement, "query", %% [{"xmlns", XMLNS}], %% Res %% }]}; %% {error, Error} -> %% IQ#iq{type = error, %% sub_el = [SubEl, Error]} %% end %% end; %% _ -> %% IQ#iq{type = error, %% sub_el = [SubEl, ?ERR_NOT_ALLOWED]} %%end; get -> case process_get(SubEl) of {result, Res} -> IQ#iq{type = result, sub_el = [Res]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end end end. process_get(#xmlel{name = <<"info">>}) -> S2SConns = ejabberd_s2s:dirty_get_connections(), TConns = lists:usort([element(2, C) || C <- S2SConns]), Attrs = [{<<"registered-users">>, iolist_to_binary(integer_to_list(mnesia:table_info(passwd, size)))}, {<<"online-users">>, iolist_to_binary(integer_to_list(mnesia:table_info(presence, size)))}, {<<"running-nodes">>, iolist_to_binary(integer_to_list(length(mnesia:system_info(running_db_nodes))))}, {<<"stopped-nodes">>, iolist_to_binary(integer_to_list(length(lists:usort(mnesia:system_info(db_nodes) ++ mnesia:system_info(extra_db_nodes)) -- mnesia:system_info(running_db_nodes))))}, {<<"outgoing-s2s-servers">>, iolist_to_binary(integer_to_list(length(TConns)))}], {result, #xmlel{name = <<"info">>, attrs = [{<<"xmlns">>, ?NS_ECONFIGURE} | Attrs], children = []}}; process_get(#xmlel{name = <<"welcome-message">>, attrs = Attrs}) -> {Subj, Body} = ejabberd_config:get_option( welcome_message, fun({Subj, Body}) -> {iolist_to_binary(Subj), iolist_to_binary(Body)} end, {<<"">>, <<"">>}), {result, #xmlel{name = <<"welcome-message">>, attrs = Attrs, children = [#xmlel{name = <<"subject">>, attrs = [], children = [{xmlcdata, Subj}]}, #xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Body}]}]}}; process_get(#xmlel{name = <<"registration-watchers">>, attrs = Attrs}) -> SubEls = ejabberd_config:get_option( 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, []), {result, #xmlel{name = <<"registration_watchers">>, attrs = Attrs, children = SubEls}}; process_get(#xmlel{name = <<"acls">>, attrs = Attrs}) -> Str = iolist_to_binary(io_lib:format("~p.", [ets:tab2list(acl)])), {result, #xmlel{name = <<"acls">>, attrs = Attrs, children = [{xmlcdata, Str}]}}; process_get(#xmlel{name = <<"access">>, attrs = Attrs}) -> Str = iolist_to_binary(io_lib:format("~p.", [ets:select(local_config, [{{local_config, {access, '$1'}, '$2'}, [], [{{access, '$1', '$2'}}]}])])), {result, #xmlel{name = <<"access">>, attrs = Attrs, children = [{xmlcdata, Str}]}}; process_get(#xmlel{name = <<"last">>, attrs = Attrs}) -> case catch mnesia:dirty_select(last_activity, [{{last_activity, '_', '$1', '_'}, [], ['$1']}]) of {'EXIT', _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; Vals -> TimeStamp = p1_time_compat:system_time(seconds), Str = list_to_binary( [[jlib:integer_to_binary(TimeStamp - V), <<" ">>] || V <- Vals]), {result, #xmlel{name = <<"last">>, attrs = Attrs, children = [{xmlcdata, Str}]}} end; %%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]. ejabberd-16.01/src/ejabberd_http_bind.erl0000644000232200023220000011142012645157216020721 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_http_bind.erl %%% Author : Stefan Strigler %%% Purpose : Implements XMPP over BOSH (XEP-0206) %%% Created : 21 Sep 2005 by Stefan Strigler %%% Modified: may 2009 by Mickael Remond, Alexey Schepin %%% %%% %%% 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). -protocol({xep, 124, '1.11'}). -protocol({xep, 206, '1.4'}). -behaviour(gen_fsm). %% External exports -export([start_link/4, init/1, handle_event/3, handle_sync_event/4, code_change/4, handle_info/3, terminate/3, send/2, send_xml/2, sockname/1, peername/1, setopts/2, controlling_process/2, become_controller/2, custom_receiver/1, reset_stream/1, change_shaper/2, monitor/1, close/1, start/5, handle_session_start/8, handle_http_put/7, http_put/7, http_get/2, prepare_response/4, process_request/3]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_http.hrl"). -include("http_bind.hrl"). -record(http_bind, {id, pid, to, hold, wait, process_delay, version}). -define(NULL_PEER, {{0, 0, 0, 0}, 0}). %% http binding request -record(hbr, {rid, key, out}). -record(state, {id, rid = none, key, socket, output = "", input = queue:new(), waiting_input = false, shaper_state, shaper_timer, last_receiver, last_poll, http_receiver, out_of_order_receiver = false, wait_timer, ctime = 0, timer, 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, max_pause, ip = ?NULL_PEER }). %% Internal request format: -record(http_put, {rid, attrs, payload, payload_size, hold, stream, ip}). %%-define(DBGFSM, true). -ifdef(DBGFSM). -define(FSMOPTS, [{debug, [trace]}]). -else. -define(FSMOPTS, []). -endif. %% Wait 100ms before continue processing, to allow the client provide more related stanzas. -define(BOSH_VERSION, <<"1.8">>). -define(NS_CLIENT, <<"jabber:client">>). -define(NS_BOSH, <<"urn:xmpp:xbosh">>). -define(NS_HTTP_BIND, <<"http://jabber.org/protocol/httpbind">>). -define(MAX_REQUESTS, 2). -define(MIN_POLLING, 2000000). -define(MAX_WAIT, 3600). -define(MAX_INACTIVITY, 30000). -define(MAX_PAUSE, 120). -define(PROCESS_DELAY_DEFAULT, 100). -define(PROCESS_DELAY_MIN, 0). -define(PROCESS_DELAY_MAX, 1000). -define(PROCNAME_MHB, ejabberd_mod_http_bind). start(XMPPDomain, Sid, Key, IP, HOpts) -> ?DEBUG("Starting session", []), case catch gen_fsm:start(?MODULE, [Sid, Key, IP, HOpts], ?FSMOPTS) of {ok, Pid} -> {ok, Pid}; _ -> check_bind_module(XMPPDomain), {error, "Cannot start HTTP bind session"} end. 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, {send, Packet}). send_xml({http_bind, FsmRef, _IP}, Packet) -> gen_fsm:sync_send_all_state_event(FsmRef, {send_xml, Packet}). setopts({http_bind, FsmRef, _IP}, Opts) -> case lists:member({active, once}, Opts) of true -> gen_fsm:send_all_state_event(FsmRef, {activate, self()}); _ -> ok end. controlling_process(_Socket, _Pid) -> ok. custom_receiver({http_bind, FsmRef, _IP}) -> {receiver, ?MODULE, FsmRef}. become_controller(FsmRef, C2SPid) -> gen_fsm:send_all_state_event(FsmRef, {become_controller, C2SPid}). reset_stream({http_bind, _FsmRef, _IP}) -> ok. change_shaper({http_bind, FsmRef, _IP}, Shaper) -> gen_fsm:send_all_state_event(FsmRef, {change_shaper, Shaper}). monitor({http_bind, FsmRef, _IP}) -> erlang:monitor(process, FsmRef). close({http_bind, FsmRef, _IP}) -> catch gen_fsm:sync_send_all_state_event(FsmRef, {stop, close}). sockname(_Socket) -> {ok, ?NULL_PEER}. peername({http_bind, _FsmRef, IP}) -> {ok, IP}. %% Entry point for data coming from client through ejabberd HTTP server: 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, Opts) of {value, {_, Size}} -> Size; _ -> infinity end, PayloadSize = iolist_size(Data), case catch parse_request(Data, PayloadSize, MaxStanzaSize) of %% No existing session: {ok, {<<"">>, Rid, Attrs, Payload}} -> case xml:get_attr_s(<<"to">>, Attrs) of <<"">> -> ?DEBUG("Session not created (Improper addressing)", []), {200, ?HEADER, <<"">>}; XmppDomain -> NXmppDomain = jid:nameprep(XmppDomain), Sid = p1_sha:sha(term_to_binary({p1_time_compat:monotonic_time(), make_ref()})), case start(NXmppDomain, Sid, <<"">>, IP, HOpts) of {error, _} -> {500, ?HEADER, <<"Internal Server Error">>}; {ok, Pid} -> handle_session_start(Pid, NXmppDomain, Sid, Rid, Attrs, Payload, PayloadSize, IP) end end; %% Existing session {ok, {Sid, Rid, Attrs, Payload1}} -> StreamStart = case xml:get_attr_s(<<"xmpp:restart">>, Attrs) of <<"true">> -> true; _ -> false end, Payload2 = case xml:get_attr_s(<<"type">>, Attrs) of <<"terminate">> -> Payload1 ++ [{xmlstreamend, <<"stream:stream">>}]; _ -> Payload1 end, handle_http_put(Sid, Rid, Attrs, Payload2, PayloadSize, StreamStart, IP); {size_limit, Sid} -> case mnesia:dirty_read({http_bind, Sid}) of {error, _} -> {404, ?HEADER, <<"">>}; {ok, #http_bind{pid = FsmRef}} -> gen_fsm:sync_send_all_state_event(FsmRef, {stop, close}), {200, ?HEADER, <<"Request Too Large">>} end; _ -> ?DEBUG("Received bad request: ~p", [Data]), {400, ?HEADER, <<"">>} end. 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">>, Attrs)) of {error, _} -> ?MAX_WAIT; {CWait, _} -> if CWait > (?MAX_WAIT) -> ?MAX_WAIT; true -> CWait end end, Hold = case str:to_integer(xml:get_attr_s(<<"hold">>, Attrs)) of {error, _} -> (?MAX_REQUESTS) - 1; {CHold, _} -> if CHold > (?MAX_REQUESTS) - 1 -> (?MAX_REQUESTS) - 1; true -> CHold end end, Pdelay = case str:to_integer(xml:get_attr_s(<<"process-delay">>, Attrs)) of {error, _} -> ?PROCESS_DELAY_DEFAULT; {CPdelay, _} when ((?PROCESS_DELAY_MIN) =< CPdelay) and (CPdelay =< (?PROCESS_DELAY_MAX)) -> CPdelay; {CPdelay, _} -> lists:max([lists:min([CPdelay, ?PROCESS_DELAY_MAX]), ?PROCESS_DELAY_MIN]) end, Version = case catch list_to_float(binary_to_list(xml:get_attr_s(<<"ver">>, Attrs))) of {'EXIT', _} -> 0.0; V -> V end, XmppVersion = xml:get_attr_s(<<"xmpp:version">>, Attrs), ?DEBUG("Create session: ~p", [Sid]), mnesia:dirty_write( #http_bind{id = Sid, pid = Pid, to = {XmppDomain, XmppVersion}, hold = Hold, wait = Wait, process_delay = Pdelay, version = Version }), handle_http_put(Sid, Rid, Attrs, Payload, PayloadSize, true, IP). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- init([Sid, Key, IP, HOpts]) -> ?DEBUG("started: ~p", [{Sid, Key, IP}]), Opts1 = ejabberd_c2s_config:get_c2s_limits(), 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), Opts = [{xml_socket, true} | SOpts ++ Opts1], Shaper = none, ShaperState = shaper:new(Shaper), Socket = {http_bind, self(), IP}, ejabberd_socket:start(ejabberd_c2s, ?MODULE, Socket, Opts), Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), {ok, loop, #state{id = Sid, key = Key, socket = Socket, shaper_state = ShaperState, max_inactivity = ?MAX_INACTIVITY, max_pause = ?MAX_PAUSE, timer = Timer}}. handle_event({become_controller, C2SPid}, StateName, StateData) -> case StateData#state.input of cancel -> {next_state, StateName, StateData#state{waiting_input = C2SPid}}; Input -> lists:foreach(fun (Event) -> C2SPid ! Event end, queue:to_list(Input)), {next_state, StateName, StateData#state{input = queue:new(), waiting_input = C2SPid}} end; handle_event({change_shaper, Shaper}, StateName, StateData) -> NewShaperState = shaper:new(Shaper), {next_state, StateName, StateData#state{shaper_state = NewShaperState}}; handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. handle_sync_event({send_xml, Packet}, _From, StateName, #state{http_receiver = undefined} = StateData) -> Output = [Packet | StateData#state.output], Reply = ok, {reply, Reply, StateName, StateData#state{output = Output}}; handle_sync_event({send_xml, Packet}, _From, StateName, #state{out_of_order_receiver = true} = StateData) -> Output = [Packet | StateData#state.output], Reply = ok, {reply, Reply, StateName, StateData#state{output = Output}}; handle_sync_event({send_xml, Packet}, _From, StateName, StateData) -> Output = [Packet | StateData#state.output], cancel_timer(StateData#state.timer), Timer = set_inactivity_timer(StateData#state.pause, StateData#state.max_inactivity), HTTPReply = {ok, Output}, gen_fsm:reply(StateData#state.http_receiver, HTTPReply), cancel_timer(StateData#state.wait_timer), Rid = StateData#state.rid, ReqList = [#hbr{rid = Rid, key = StateData#state.key, out = Output} | [El || El <- StateData#state.req_list, El#hbr.rid /= Rid]], Reply = ok, {reply, Reply, StateName, StateData#state{output = [], http_receiver = undefined, req_list = ReqList, wait_timer = undefined, timer = Timer}}; handle_sync_event({stop,close}, _From, _StateName, StateData) -> Reply = ok, {stop, normal, Reply, StateData}; handle_sync_event({stop,stream_closed}, _From, _StateName, StateData) -> Reply = ok, {stop, normal, Reply, StateData}; handle_sync_event({stop,Reason}, _From, _StateName, StateData) -> ?DEBUG("Closing bind session ~p - Reason: ~p", [StateData#state.id, Reason]), Reply = ok, {stop, normal, Reply, StateData}; %% HTTP PUT: Receive packets from the client handle_sync_event(#http_put{rid = Rid}, _From, StateName, StateData) when StateData#state.shaper_timer /= undefined -> Pause = case erlang:read_timer(StateData#state.shaper_timer) of false -> 0; P -> P end, Reply = {wait, Pause}, ?DEBUG("Shaper timer for RID ~p: ~p", [Rid, Reply]), {reply, Reply, StateName, StateData}; handle_sync_event(#http_put{payload_size = PayloadSize} = Request, _From, StateName, StateData) -> ?DEBUG("New request: ~p", [Request]), {NewShaperState, NewShaperTimer} = update_shaper(StateData#state.shaper_state, PayloadSize), handle_http_put_event(Request, StateName, StateData#state{shaper_state = NewShaperState, shaper_timer = NewShaperTimer}); %% HTTP GET: send packets to the client handle_sync_event({http_get, Rid, Wait, Hold}, From, StateName, StateData) -> 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 (StateData#state.rid =< Rid) and (StateData#state.pause == 0) -> send_receiver_reply(StateData#state.http_receiver, {ok, empty}), cancel_timer(StateData#state.wait_timer), WaitTimer = erlang:start_timer(Wait * 1000, self(), []), cancel_timer(StateData#state.timer), {next_state, StateName, StateData#state{ http_receiver = From, out_of_order_receiver = StateData#state.rid < Rid, wait_timer = WaitTimer, timer = undefined}}; true -> cancel_timer(StateData#state.timer), Reply = {ok, StateData#state.output}, ReqList = [#hbr{rid = Rid, key = StateData#state.key, out = StateData#state.output} | [El || El <- StateData#state.req_list, El#hbr.rid /= Rid]], if (StateData#state.http_receiver /= undefined) and StateData#state.out_of_order_receiver -> {reply, Reply, StateName, StateData#state{output = [], timer = undefined, req_list = ReqList, out_of_order_receiver = false}}; true -> send_receiver_reply(StateData#state.http_receiver, {ok, empty}), cancel_timer(StateData#state.wait_timer), Timer = set_inactivity_timer(StateData#state.pause, StateData#state.max_inactivity), {reply, Reply, StateName, StateData#state{output = [], http_receiver = undefined, wait_timer = undefined, timer = Timer, req_list = ReqList}} end end; handle_sync_event(peername, _From, StateName, StateData) -> Reply = {ok, StateData#state.ip}, {reply, Reply, StateName, StateData}; handle_sync_event(_Event, _From, StateName, StateData) -> Reply = ok, {reply, Reply, StateName, StateData}. code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. handle_info({timeout, Timer, _}, _StateName, #state{id = SID, timer = Timer} = StateData) -> ?INFO_MSG("Session timeout. Closing the HTTP bind " "session: ~p", [SID]), {stop, normal, StateData}; handle_info({timeout, WaitTimer, _}, StateName, #state{wait_timer = WaitTimer} = StateData) -> if StateData#state.http_receiver /= undefined -> cancel_timer(StateData#state.timer), Timer = set_inactivity_timer(StateData#state.pause, StateData#state.max_inactivity), gen_fsm:reply(StateData#state.http_receiver, {ok, empty}), Rid = StateData#state.rid, ReqList = [#hbr{rid = Rid, key = StateData#state.key, out = []} | [El || El <- StateData#state.req_list, El#hbr.rid /= Rid]], {next_state, StateName, StateData#state{http_receiver = undefined, req_list = ReqList, wait_timer = undefined, timer = Timer}}; true -> {next_state, StateName, StateData} end; handle_info({timeout, ShaperTimer, _}, StateName, #state{shaper_timer = ShaperTimer} = StateData) -> {next_state, StateName, StateData#state{shaper_timer = undefined}}; handle_info(_, StateName, StateData) -> {next_state, StateName, StateData}. terminate(_Reason, _StateName, StateData) -> ?DEBUG("terminate: Deleting session ~s", [StateData#state.id]), mnesia:dirty_delete({http_bind, StateData#state.id}), send_receiver_reply(StateData#state.http_receiver, {ok, terminate}), case StateData#state.waiting_input of false -> ok; C2SPid -> gen_fsm:send_event(C2SPid, closed) end, ok. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- %% PUT / Get processing: handle_http_put_event(#http_put{rid = Rid, attrs = Attrs, hold = Hold} = Request, StateName, StateData) -> ?DEBUG("New request: ~p", [Request]), RidAllow = rid_allow(StateData#state.rid, Rid, Attrs, Hold, StateData#state.max_pause), case RidAllow of buffer -> ?DEBUG("Buffered request: ~p", [Request]), PendingRequests = StateData#state.unprocessed_req_list, Requests = lists:keydelete(Rid, 2, PendingRequests), ReqList = [#hbr{rid = Rid, key = StateData#state.key, out = []} | [El || El <- StateData#state.req_list, El#hbr.rid > Rid - 1 - Hold]], ?DEBUG("reqlist: ~p", [ReqList]), UnprocessedReqList = [Request | Requests], cancel_timer(StateData#state.timer), Timer = set_inactivity_timer(0, StateData#state.max_inactivity), {reply, ok, StateName, StateData#state{unprocessed_req_list = UnprocessedReqList, req_list = ReqList, timer = Timer}, hibernate}; _ -> process_http_put(Request, StateName, StateData, RidAllow) end. process_http_put(#http_put{rid = Rid, attrs = Attrs, payload = Payload, hold = Hold, stream = StreamTo, ip = IP} = Request, StateName, StateData, RidAllow) -> ?DEBUG("Actually processing request: ~p", [Request]), Key = xml:get_attr_s(<<"key">>, Attrs), NewKey = xml:get_attr_s(<<"newkey">>, Attrs), KeyAllow = case RidAllow of repeat -> true; false -> false; {true, _} -> case StateData#state.key of <<"">> -> true; OldKey -> NextKey = p1_sha:sha(Key), ?DEBUG("Key/OldKey/NextKey: ~s/~s/~s", [Key, OldKey, NextKey]), if OldKey == NextKey -> true; true -> ?DEBUG("wrong key: ~s", [Key]), false end end end, TNow = p1_time_compat:system_time(micro_seconds), LastPoll = if Payload == [] -> TNow; true -> 0 end, if (Payload == []) and (Hold == 0) and (TNow - StateData#state.last_poll < (?MIN_POLLING)) -> Reply = {error, polling_too_frequently}, {reply, Reply, StateName, StateData}; KeyAllow -> case RidAllow of false -> Reply = {error, not_exists}, {reply, Reply, StateName, StateData}; repeat -> ?DEBUG("REPEATING ~p", [Rid]), case [El#hbr.out || El <- StateData#state.req_list, El#hbr.rid == Rid] of [] -> {error, not_exists}; [Out | _XS] -> if (Rid == StateData#state.rid) and (StateData#state.http_receiver /= undefined) -> {reply, ok, StateName, StateData}; true -> Reply = {repeat, lists:reverse(Out)}, {reply, Reply, StateName, StateData#state{last_poll = LastPoll}} end end; {true, Pause} -> SaveKey = if NewKey == <<"">> -> Key; true -> NewKey end, ?DEBUG(" -- SaveKey: ~s~n", [SaveKey]), ReqList1 = [El || El <- StateData#state.req_list, El#hbr.rid > Rid - 1 - Hold], ReqList = case lists:keymember(Rid, #hbr.rid, ReqList1) of true -> ReqList1; false -> [#hbr{rid = Rid, key = StateData#state.key, out = []} | ReqList1] end, ?DEBUG("reqlist: ~p", [ReqList]), cancel_timer(StateData#state.timer), Timer = set_inactivity_timer(Pause, StateData#state.max_inactivity), case StateData#state.waiting_input of false -> Input = lists:foldl(fun queue:in/2, StateData#state.input, Payload), Reply = ok, process_buffered_request(Reply, StateName, StateData#state{input = Input, rid = Rid, key = SaveKey, ctime = TNow, timer = Timer, pause = Pause, last_poll = LastPoll, req_list = ReqList, ip = IP}); C2SPid -> case StreamTo of {To, <<"">>} -> gen_fsm:send_event(C2SPid, {xmlstreamstart, <<"stream:stream">>, [{<<"to">>, To}, {<<"xmlns">>, ?NS_CLIENT}, {<<"xmlns:stream">>, ?NS_STREAM}]}); {To, Version} -> gen_fsm:send_event(C2SPid, {xmlstreamstart, <<"stream:stream">>, [{<<"to">>, To}, {<<"xmlns">>, ?NS_CLIENT}, {<<"version">>, Version}, {<<"xmlns:stream">>, ?NS_STREAM}]}); _ -> ok end, MaxInactivity = get_max_inactivity(StreamTo, StateData#state.max_inactivity), MaxPause = get_max_inactivity(StreamTo, StateData#state.max_pause), ?DEBUG("really sending now: ~p", [Payload]), lists:foreach(fun ({xmlstreamend, End}) -> gen_fsm:send_event(C2SPid, {xmlstreamend, End}); (El) -> gen_fsm:send_event(C2SPid, {xmlstreamelement, El}) end, Payload), Reply = ok, process_buffered_request(Reply, StateName, StateData#state{input = queue:new(), rid = Rid, key = SaveKey, ctime = TNow, timer = Timer, pause = Pause, last_poll = LastPoll, req_list = ReqList, max_inactivity = MaxInactivity, max_pause = MaxPause, ip = IP}) end end; true -> Reply = {error, bad_key}, {reply, Reply, StateName, StateData} end. process_buffered_request(Reply, StateName, StateData) -> Rid = StateData#state.rid, Requests = StateData#state.unprocessed_req_list, case lists:keysearch(Rid + 1, 2, Requests) of {value, Request} -> ?DEBUG("Processing buffered request: ~p", [Request]), NewRequests = lists:keydelete(Rid + 1, 2, Requests), handle_http_put_event(Request, StateName, StateData#state{unprocessed_req_list = NewRequests}); _ -> {reply, Reply, StateName, StateData, hibernate} end. handle_http_put(Sid, Rid, Attrs, Payload, PayloadSize, StreamStart, IP) -> case http_put(Sid, Rid, Attrs, Payload, PayloadSize, StreamStart, IP) of {error, not_exists} -> ?DEBUG("no session associated with sid: ~p", [Sid]), {404, ?HEADER, <<"">>}; {{error, Reason}, Sess} -> ?DEBUG("Error on HTTP put. Reason: ~p", [Reason]), handle_http_put_error(Reason, Sess); {{repeat, OutPacket}, Sess} -> ?DEBUG("http_put said 'repeat!' ...~nOutPacket: ~p", [OutPacket]), send_outpacket(Sess, OutPacket); {{wait, Pause}, _Sess} -> ?DEBUG("Trafic Shaper: Delaying request ~p", [Rid]), timer:sleep(Pause), handle_http_put(Sid, Rid, Attrs, Payload, PayloadSize, StreamStart, IP); {ok, Sess} -> prepare_response(Sess, Rid, [], StreamStart) end. http_put(Sid, Rid, Attrs, Payload, PayloadSize, StreamStart, IP) -> ?DEBUG("Looking for session: ~p", [Sid]), case mnesia:dirty_read({http_bind, Sid}) of [] -> {error, not_exists}; [#http_bind{pid = FsmRef, hold=Hold, to= {To, StreamVersion}} = Sess] -> NewStream = case StreamStart of true -> {To, StreamVersion}; _ -> <<"">> end, {gen_fsm:sync_send_all_state_event( FsmRef, #http_put{rid = Rid, attrs = Attrs, payload = Payload, payload_size = PayloadSize, hold = Hold, stream = NewStream, ip = IP}, 30000), Sess} end. handle_http_put_error(Reason, #http_bind{pid = FsmRef, version = Version}) when Version >= 0 -> gen_fsm:sync_send_all_state_event(FsmRef, {stop, {put_error, Reason}}), case Reason of not_exists -> {200, ?HEADER, xml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}, {<<"type">>, <<"terminate">>}, {<<"condition">>, <<"item-not-found">>}], children = []})}; bad_key -> {200, ?HEADER, xml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}, {<<"type">>, <<"terminate">>}, {<<"condition">>, <<"item-not-found">>}], children = []})}; polling_too_frequently -> {200, ?HEADER, xml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}, {<<"type">>, <<"terminate">>}, {<<"condition">>, <<"policy-violation">>}], children = []})} end; handle_http_put_error(Reason, #http_bind{pid = FsmRef}) -> gen_fsm:sync_send_all_state_event(FsmRef, {stop, {put_error_no_version, Reason}}), case Reason of not_exists -> %% bad rid ?DEBUG("Closing HTTP bind session (Bad rid).", []), {404, ?HEADER, <<"">>}; bad_key -> ?DEBUG("Closing HTTP bind session (Bad key).", []), {404, ?HEADER, <<"">>}; polling_too_frequently -> ?DEBUG("Closing HTTP bind session (User polling " "too frequently).", []), {403, ?HEADER, <<"">>} end. %% Control RID ordering rid_allow(none, _NewRid, _Attrs, _Hold, _MaxPause) -> {true, 0}; rid_allow(OldRid, NewRid, Attrs, Hold, MaxPause) -> ?DEBUG("Previous rid / New rid: ~p/~p", [OldRid, NewRid]), if %% 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">>, Attrs)) of {'EXIT', _} -> {true, 0}; Pause1 when Pause1 =< MaxPause -> ?DEBUG("got pause: ~p", [Pause1]), {true, Pause1}; _ -> {true, 0} end; %% We have missed packets, we need to cached it to process it later on: (OldRid < NewRid) and (NewRid =< OldRid + Hold + 1) -> buffer; (NewRid =< OldRid) and (NewRid > OldRid - Hold - 1) -> repeat; true -> false end. update_shaper(ShaperState, PayloadSize) -> {NewShaperState, Pause} = shaper:update(ShaperState, PayloadSize), if Pause > 0 -> ShaperTimer = erlang:start_timer(Pause, self(), activate), {NewShaperState, ShaperTimer}; true -> {NewShaperState, undefined} end. prepare_response(Sess, Rid, OutputEls, StreamStart) -> receive after Sess#http_bind.process_delay -> ok end, case catch http_get(Sess, Rid) of {ok, cancel} -> {200, ?HEADER, <<"">>}; {ok, empty} -> {200, ?HEADER, <<"">>}; {ok, terminate} -> {200, ?HEADER, <<"">>}; {ok, ROutPacket} -> OutPacket = lists:reverse(ROutPacket), ?DEBUG("OutPacket: ~p", [OutputEls ++ OutPacket]), prepare_outpacket_response(Sess, Rid, OutputEls ++ OutPacket, StreamStart); {'EXIT', {shutdown, _}} -> {200, ?HEADER, <<"">>}; {'EXIT', _Reason} -> {200, ?HEADER, <<"">>} end. %% Send output payloads on establised sessions prepare_outpacket_response(Sess, _Rid, OutPacket, false) -> case catch send_outpacket(Sess, OutPacket) of {'EXIT', _Reason} -> ?DEBUG("Error in sending packet ~p ", [_Reason]), {200, ?HEADER, <<"">>}; SendRes -> SendRes end; %% Handle a new session along with its output payload prepare_outpacket_response(#http_bind{id = Sid, wait = Wait, hold = Hold, to = To} = _Sess, _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), OutEls = case Els of [] -> []; [{xmlstreamelement, #xmlel{name = <<"stream:features">>, attrs = StreamAttribs, children = StreamEls}} | StreamTail] -> TypedTail = [check_default_xmlns(OEl) || {xmlstreamelement, OEl} <- StreamTail], [#xmlel{name = <<"stream:features">>, attrs = [{<<"xmlns:stream">>, ?NS_STREAM}] ++ StreamAttribs, children = StreamEls}] ++ TypedTail; StreamTail -> [check_default_xmlns(OEl) || {xmlstreamelement, OEl} <- StreamTail] end, case OutEls of [#xmlel{name = <<"stream:error">>}] -> {200, ?HEADER, <<"">>}; _ -> BOSH_attribs = [{<<"authid">>, AuthID}, {<<"xmlns:xmpp">>, ?NS_BOSH}, {<<"xmlns:stream">>, ?NS_STREAM}] ++ case OutEls of [] -> []; _ -> [{<<"xmpp:version">>, Version}] end, MaxInactivity = get_max_inactivity(To, ?MAX_INACTIVITY), MaxPause = get_max_pause(To), {200, ?HEADER, xml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}, {<<"sid">>, Sid}, {<<"wait">>, iolist_to_binary(integer_to_list(Wait))}, {<<"requests">>, iolist_to_binary(integer_to_list(Hold + 1))}, {<<"inactivity">>, iolist_to_binary(integer_to_list(trunc(MaxInactivity / 1000)))}, {<<"maxpause">>, iolist_to_binary(integer_to_list(MaxPause))}, {<<"polling">>, iolist_to_binary(integer_to_list(trunc((?MIN_POLLING) / 1000000)))}, {<<"ver">>, ?BOSH_VERSION}, {<<"from">>, From}, {<<"secure">>, <<"true">>}] ++ BOSH_attribs, children = OutEls})} end; _ -> {200, ?HEADER, <<"">>} end. http_get(#http_bind{pid = FsmRef, wait = Wait, hold = Hold}, Rid) -> gen_fsm:sync_send_all_state_event(FsmRef, {http_get, Rid, Wait, Hold}, 2 * (?MAX_WAIT) * 1000). send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> case OutPacket of [] -> {200, ?HEADER, <<"">>}; [{xmlstreamend, _}] -> gen_fsm:sync_send_all_state_event(FsmRef, {stop, stream_closed}), {200, ?HEADER, <<"">>}; _ -> AllElements = lists:all(fun ({xmlstreamelement, #xmlel{name = <<"stream:error">>}}) -> false; ({xmlstreamelement, _}) -> true; ({xmlstreamraw, _}) -> true; (_) -> false end, OutPacket), case AllElements of true -> TypedEls = lists:foldl(fun ({xmlstreamelement, El}, Acc) -> Acc ++ [xml:element_to_binary(check_default_xmlns(El))]; ({xmlstreamraw, R}, Acc) -> Acc ++ [R] end, [], OutPacket), Body = <<"", (iolist_to_binary(TypedEls))/binary, "">>, ?DEBUG(" --- outgoing data --- ~n~s~n --- END " "--- ~n", [Body]), {200, ?HEADER, Body}; false -> case OutPacket of [{xmlstreamstart, _, _} | SEls] -> OutEls = case SEls of [{xmlstreamelement, #xmlel{name = <<"stream:features">>, attrs = StreamAttribs, children = StreamEls}} | StreamTail] -> TypedTail = [check_default_xmlns(OEl) || {xmlstreamelement, OEl} <- StreamTail], [#xmlel{name = <<"stream:features">>, attrs = [{<<"xmlns:stream">>, ?NS_STREAM}] ++ StreamAttribs, children = StreamEls}] ++ TypedTail; StreamTail -> [check_default_xmlns(OEl) || {xmlstreamelement, OEl} <- StreamTail] end, {200, ?HEADER, xml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}], children = OutEls})}; _ -> SErrCond = lists:filter(fun ({xmlstreamelement, #xmlel{name = <<"stream:error">>}}) -> true; (_) -> false end, OutPacket), StreamErrCond = case SErrCond of [] -> null; [{xmlstreamelement, #xmlel{} = StreamErrorTag} | _] -> [StreamErrorTag] end, gen_fsm:sync_send_all_state_event(FsmRef, {stop, {stream_error, OutPacket}}), case StreamErrCond of null -> {200, ?HEADER, <<"">>}; _ -> {200, ?HEADER, <<"", (elements_to_string(StreamErrCond))/binary, "">>} end end end end. parse_request(Data, PayloadSize, MaxStanzaSize) -> ?DEBUG("--- incoming data --- ~n~s~n --- END " "--- ", [Data]), case xml_stream:parse_element(Data) of #xmlel{name = <<"body">>, attrs = Attrs, children = Els} -> Xmlns = xml: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">>, Attrs)) of {'EXIT', _} -> {error, bad_request}; Rid -> FixedEls = lists:filter(fun (I) -> case I of #xmlel{} -> true; _ -> false end end, Els), Sid = xml:get_attr_s(<<"sid">>, Attrs), if PayloadSize =< MaxStanzaSize -> {ok, {Sid, Rid, Attrs, FixedEls}}; true -> {size_limit, Sid} end end end; #xmlel{} -> {error, bad_request}; {error, _Reason} -> {error, bad_request} end. send_receiver_reply(undefined, _Reply) -> ok; send_receiver_reply(Receiver, Reply) -> gen_fsm:reply(Receiver, Reply). %% Cancel timer and empty message queue. cancel_timer(undefined) -> ok; cancel_timer(Timer) -> erlang:cancel_timer(Timer), receive {timeout, Timer, _} -> ok after 0 -> ok end. %% If client asked for a pause (pause > 0), we apply the pause value %% as inactivity timer: set_inactivity_timer(Pause, _MaxInactivity) when Pause > 0 -> erlang:start_timer(Pause * 1000, self(), []); %% Otherwise, we apply the max_inactivity value as inactivity timer: set_inactivity_timer(_Pause, MaxInactivity) -> erlang:start_timer(MaxInactivity, self(), []). elements_to_string([]) -> []; elements_to_string([El | Els]) -> [xml:element_to_binary(El) | elements_to_string(Els)]. %% @spec (To, Default::integer()) -> integer() %% where To = [] | {Host::string(), Version::string()} get_max_inactivity({Host, _}, Default) -> case gen_mod:get_module_opt(Host, mod_http_bind, max_inactivity, fun(I) when is_integer(I), I>0 -> I end, undefined) of Seconds when is_integer(Seconds) -> Seconds * 1000; undefined -> Default end; get_max_inactivity(_, Default) -> Default. get_max_pause({Host, _}) -> gen_mod:get_module_opt(Host, mod_http_bind, max_pause, fun(I) when is_integer(I), I>0 -> I end, ?MAX_PAUSE); 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 <<"">> -> #xmlel{name = Name, attrs = [{<<"xmlns">>, ?NS_CLIENT} | Attrs], children = Els}; _ -> El end; check_default_xmlns(El) -> El. %% Check that mod_http_bind has been defined in config file. %% Print a warning in log file if this is not the case. check_bind_module(XmppDomain) -> case gen_mod:is_loaded(XmppDomain, mod_http_bind) of true -> true; false -> ?ERROR_MSG("You are trying to use BOSH (HTTP Bind) " "in host ~p, but the module mod_http_bind " "is not started in that host. Configure " "your BOSH client to connect to the correct " "host, or add your desired host to the " "configuration, or check your 'modules' " "section in your ejabberd configuration " "file.", [XmppDomain]), false end. ejabberd-16.01/src/mod_register.erl0000644000232200023220000005622312645157216017624 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_register.erl %%% Author : Alexey Shchepin %%% Purpose : Inband registration support %%% Created : 8 Dec 2002 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(mod_register). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -protocol({xep, 77, '2.4'}). -behaviour(gen_mod). -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, mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). 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_REGISTER, ?MODULE, process_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_REGISTER, ?MODULE, process_iq, IQDisc), ejabberd_hooks:add(c2s_stream_features, Host, ?MODULE, stream_feature_register, 50), ejabberd_hooks:add(c2s_unauthenticated_iq, Host, ?MODULE, unauthenticated_iq_register, 50), mnesia:create_table(mod_register_ip, [{ram_copies, [node()]}, {local_content, true}, {attributes, [key, value]}]), mnesia:add_table_copy(mod_register_ip, node(), ram_copies), ok. stop(Host) -> ejabberd_hooks:delete(c2s_stream_features, Host, ?MODULE, stream_feature_register, 50), ejabberd_hooks:delete(c2s_unauthenticated_iq, Host, ?MODULE, unauthenticated_iq_register, 50), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_REGISTER), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_REGISTER). 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}], children = []} | Acc]; false -> Acc end. unauthenticated_iq_register(_Acc, Server, #iq{xmlns = ?NS_REGISTER} = IQ, IP) -> Address = case IP of {A, _Port} -> A; _ -> undefined end, ResIQ = process_iq(jid:make(<<"">>, <<"">>, <<"">>), jid:make(<<"">>, Server, <<"">>), IQ, Address), Res1 = jlib:replace_from_to(jid:make(<<"">>, Server, <<"">>), 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, jid:tolower(From)). process_iq(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl, id = ID} = IQ, Source) -> IsCaptchaEnabled = case gen_mod:get_module_opt(To#jid.lserver, ?MODULE, captcha_protected, fun(B) when is_boolean(B) -> B end, false) of true -> true; _ -> false end, case Type of set -> UTag = xml:get_subtag(SubEl, <<"username">>), PTag = xml:get_subtag(SubEl, <<"password">>), RTag = xml: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, all), AllowRemove = allow == acl:match_rule(Server, Access, From), if (UTag /= false) and (RTag /= false) and AllowRemove -> User = xml: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), case ejabberd_auth:remove_user(User, Server, Password) of ok -> IQ#iq{type = result, sub_el = []}; %% TODO FIXME: This piece of %% code does not work since %% the code have been changed %% to allow several auth %% modules. lists:foreach can %% only return ok: not_allowed -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; not_exists -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}; _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} end; true -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end end; (UTag == false) and (RTag /= false) and AllowRemove -> case From of #jid{user = User, lserver = Server, resource = Resource} -> ResIQ = #iq{type = result, xmlns = ?NS_REGISTER, id = ID, sub_el = []}, ejabberd_router:route(jid:make(User, Server, Resource), jid:make(User, Server, Resource), jlib:iq_to_xml(ResIQ)), ejabberd_auth:remove_user(User, Server), ignore; _ -> 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), try_register_or_set_password(User, Server, Password, From, IQ, SubEl, Source, Lang, not IsCaptchaEnabled); IsCaptchaEnabled -> case ejabberd_captcha:process_reply(SubEl) of ok -> case process_xdata_submit(SubEl) of {ok, User, Password} -> try_register_or_set_password(User, Server, Password, From, IQ, SubEl, Source, Lang, true); _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end; {error, malformed} -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; _ -> ErrText = <<"The CAPTCHA verification has failed">>, IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ALLOWED(Lang, ErrText)]} end; true -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end; get -> {IsRegistered, UsernameSubels, QuerySubels} = case From of #jid{user = User, lserver = Server} -> case ejabberd_auth:is_user_exists(User, Server) of true -> {true, [{xmlcdata, User}], [#xmlel{name = <<"registered">>, attrs = [], children = []}]}; false -> {false, [{xmlcdata, User}], []} end; _ -> {false, [], []} end, if IsCaptchaEnabled and not IsRegistered -> TopInstrEl = #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"You need a client that supports x:data " "and CAPTCHA to register">>)}]}, InstrEl = #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Choose a username and password to register " "with this server">>)}]}, UField = #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-single">>}, {<<"label">>, translate:translate(Lang, <<"User">>)}, {<<"var">>, <<"username">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}, PField = #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-private">>}, {<<"label">>, translate:translate(Lang, <<"Password">>)}, {<<"var">>, <<"password">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}, case ejabberd_captcha:create_captcha_x(ID, To, Lang, Source, [InstrEl, UField, PField]) of {ok, CaptchaEls} -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_REGISTER}], children = [TopInstrEl | CaptchaEls]}]}; {error, limit} -> ErrText = <<"Too many CAPTCHA requests">>, IQ#iq{type = error, sub_el = [SubEl, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)]}; _Err -> ErrText = <<"Unable to generate a CAPTCHA">>, IQ#iq{type = error, sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)]} end; true -> IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_REGISTER}], children = [#xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, translate:translate(Lang, <<"Choose a username and password to register " "with this server">>)}]}, #xmlel{name = <<"username">>, attrs = [], children = UsernameSubels}, #xmlel{name = <<"password">>, attrs = [], children = []} | QuerySubels]}]} end end. try_register_or_set_password(User, Server, Password, From, IQ, SubEl, Source, Lang, CaptchaSucceed) -> case From of #jid{user = User, lserver = Server} -> try_set_password(User, Server, Password, IQ, SubEl, Lang); _ when CaptchaSucceed -> case check_from(From, Server) of allow -> case try_register(User, Server, Password, Source, Lang) of ok -> IQ#iq{type = result, sub_el = []}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end; deny -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} end; _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} end. %% @doc Try to change password and return IQ response try_set_password(User, Server, Password, IQ, SubEl, Lang) -> case is_strong_password(Server, Password) of true -> case ejabberd_auth:set_password(User, Server, Password) of ok -> IQ#iq{type = result, sub_el = []}; {error, empty_password} -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; {error, not_allowed} -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; {error, invalid_jid} -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}; _ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} end; false -> ErrText = <<"The password is too weak">>, IQ#iq{type = error, sub_el = [SubEl, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)]} end. try_register(User, Server, Password, SourceRaw, Lang) -> case jid:is_nodename(User) of false -> {error, ?ERR_BAD_REQUEST}; _ -> JID = jid:make(User, Server, <<"">>), Access = gen_mod:get_module_opt(Server, ?MODULE, access, fun(A) when is_atom(A) -> A end, all), IPAccess = get_ip_access(Server), case {acl:match_rule(Server, Access, JID), check_ip_access(SourceRaw, IPAccess)} of {deny, _} -> {error, ?ERR_FORBIDDEN}; {_, deny} -> {error, ?ERR_FORBIDDEN}; {allow, allow} -> Source = may_remove_resource(SourceRaw), case check_timeout(Source) of true -> case is_strong_password(Server, Password) of true -> case ejabberd_auth:try_register(User, Server, Password) of {atomic, ok} -> send_welcome_message(JID), send_registration_notifications( ?MODULE, JID, Source), ok; Error -> remove_timeout(Source), case Error of {atomic, exists} -> {error, ?ERR_CONFLICT}; {error, invalid_jid} -> {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 end; false -> ErrText = <<"The password is too weak">>, {error, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)} end; false -> ErrText = <<"Users are not allowed to register accounts " "so quickly">>, {error, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)} end end end. send_welcome_message(JID) -> Host = JID#jid.lserver, case gen_mod:get_module_opt(Host, ?MODULE, 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, {<<"">>, <<"">>}) of {<<"">>, <<"">>} -> ok; {Subj, Body} -> ejabberd_router:route(jid:make(<<"">>, Host, <<"">>), JID, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"normal">>}], children = [#xmlel{name = <<"subject">>, attrs = [], children = [{xmlcdata, Subj}]}, #xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Body}]}]}); _ -> ok end. send_registration_notifications(Mod, UJID, Source) -> Host = UJID#jid.lserver, case gen_mod:get_module_opt( Host, Mod, registration_watchers, fun(Ss) -> [#jid{} = jid:from_string(iolist_to_binary(S)) || S <- Ss] end, []) of [] -> ok; JIDs when is_list(JIDs) -> Body = iolist_to_binary(io_lib:format("[~s] The account ~s was registered from " "IP address ~s on node ~w using ~p.", [get_time_string(), jid:to_string(UJID), ip_to_string(Source), node(), Mod])), lists:foreach( fun(JID) -> ejabberd_router:route( jid:make(<<"">>, Host, <<"">>), JID, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata,Body}]}]}) end, JIDs) end. check_from(#jid{user = <<"">>, server = <<"">>}, _Server) -> allow; check_from(JID, Server) -> Access = gen_mod:get_module_opt(Server, ?MODULE, access_from, fun(A) when is_atom(A) -> A end, none), acl:match_rule(Server, Access, JID). check_timeout(undefined) -> true; check_timeout(Source) -> Timeout = ejabberd_config:get_option( registration_timeout, fun(TO) when is_integer(TO), TO > 0 -> TO; (infinity) -> infinity; (unlimited) -> infinity end, 600), if is_integer(Timeout) -> Priority = -p1_time_compat:system_time(seconds), CleanPriority = Priority + Timeout, F = fun () -> Treap = case mnesia:read(mod_register_ip, treap, write) of [] -> treap:empty(); [{mod_register_ip, treap, T}] -> T end, Treap1 = clean_treap(Treap, CleanPriority), case treap:lookup(Source, Treap1) of error -> Treap2 = treap:insert(Source, Priority, [], Treap1), mnesia:write({mod_register_ip, treap, Treap2}), true; {ok, _, _} -> mnesia:write({mod_register_ip, treap, Treap1}), false end end, case mnesia:transaction(F) of {atomic, Res} -> Res; {aborted, Reason} -> ?ERROR_MSG("mod_register: timeout check error: ~p~n", [Reason]), true end; true -> true end. clean_treap(Treap, CleanPriority) -> case treap:is_empty(Treap) of true -> Treap; false -> {_Key, Priority, _Value} = treap:get_root(Treap), if Priority > CleanPriority -> clean_treap(treap:delete_root(Treap), CleanPriority); true -> Treap end end. remove_timeout(undefined) -> true; remove_timeout(Source) -> Timeout = ejabberd_config:get_option( registration_timeout, fun(TO) when is_integer(TO), TO > 0 -> TO; (infinity) -> infinity; (unlimited) -> infinity end, 600), if is_integer(Timeout) -> F = fun () -> Treap = case mnesia:read(mod_register_ip, treap, write) of [] -> treap:empty(); [{mod_register_ip, treap, T}] -> T end, Treap1 = treap:delete(Source, Treap), mnesia:write({mod_register_ip, treap, Treap1}), ok end, case mnesia:transaction(F) of {atomic, ok} -> ok; {aborted, Reason} -> ?ERROR_MSG("mod_register: timeout remove error: " "~p~n", [Reason]), ok end; true -> ok end. ip_to_string(Source) when is_tuple(Source) -> jlib:ip_to_list(Source); ip_to_string(undefined) -> <<"undefined">>; ip_to_string(_) -> <<"unknown">>. get_time_string() -> write_time(erlang:localtime()). %% Function copied from ejabberd_logger_h.erl and customized write_time({{Y, Mo, D}, {H, Mi, S}}) -> io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w", [Y, Mo, D, H, Mi, S]). process_xdata_submit(El) -> case xml:get_subtag(El, <<"x">>) of false -> error; Xdata -> Fields = jlib:parse_xdata_submit(Xdata), case catch {proplists:get_value(<<"username">>, Fields), proplists:get_value(<<"password">>, Fields)} of {[User | _], [Pass | _]} -> {ok, User, Pass}; _ -> error end end. is_strong_password(Server, Password) -> 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 0 -> true; Entropy -> ejabberd_auth:entropy(Password) >= Entropy end. transform_options(Opts) -> Opts1 = transform_ip_access(Opts), transform_module_options(Opts1). transform_ip_access(Opts) -> try {value, {modules, ModOpts}, Opts1} = lists:keytake(modules, 1, Opts), {value, {?MODULE, RegOpts}, ModOpts1} = lists:keytake(?MODULE, 1, ModOpts), {value, {ip_access, L}, RegOpts1} = lists:keytake(ip_access, 1, RegOpts), true = is_list(L), ?WARNING_MSG("Old 'ip_access' format detected. " "The old format is still supported " "but it is better to fix your config: " "use access rules instead.", []), ACLs = lists:flatmap( fun({Action, S}) -> ACLName = jlib:binary_to_atom( iolist_to_binary( ["ip_", S])), [{Action, ACLName}, {acl, ACLName, {ip, S}}] end, L), Access = {access, mod_register_networks, [{Action, ACLName} || {Action, ACLName} <- ACLs]}, [ACL || {acl, _, _} = ACL <- ACLs] ++ [Access, {modules, [{mod_register, [{ip_access, mod_register_networks}|RegOpts1]} | ModOpts1]}|Opts1] catch error:{badmatch, false} -> Opts end. transform_module_options(Opts) -> lists:flatmap( fun({welcome_message, {Subj, Body}}) -> ?WARNING_MSG("Old 'welcome_message' format detected. " "The old format is still supported " "but it is better to fix your config: " "change it to {welcome_message, " "[{subject, Subject}, {body, Body}]}", []), [{welcome_message, [{subject, Subj}, {body, Body}]}]; (Opt) -> [Opt] end, Opts). %%% %%% ip_access management %%% may_remove_resource({_, _, _} = From) -> jid:remove_resource(From); may_remove_resource(From) -> From. get_ip_access(Host) -> gen_mod:get_module_opt(Host, ?MODULE, ip_access, fun(A) when is_atom(A) -> A end, all). check_ip_access({User, Server, Resource}, IPAccess) -> case ejabberd_sm:get_user_ip(User, Server, Resource) of {IPAddress, _PortNumber} -> check_ip_access(IPAddress, IPAccess); _ -> deny end; 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{} = jid:from_string(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]. ejabberd-16.01/src/node_buddy.erl0000644000232200023220000001313112645157216017244 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_buddy.erl %%% Author : Christophe Romain %%% Purpose : %%% Created : 1 Dec 2007 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_buddy). -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]). 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, 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_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). ejabberd-16.01/src/adhoc.erl0000644000232200023220000001157012645157216016213 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : adhoc.erl %%% Author : Magnus Henoch %%% Purpose : Provide helper functions for ad-hoc commands (XEP-0050) %%% Created : 31 Oct 2005 by Magnus Henoch %%% %%% %%% 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(adhoc). -author('henoch@dtek.chalmers.se'). -export([ parse_request/1, produce_response/2, produce_response/1 ]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("adhoc.hrl"). %% Parse an ad-hoc request. Return either an adhoc_request record or %% an {error, ErrorType} tuple. %% -spec(parse_request/1 :: ( IQ :: iq_request()) -> adhoc_response() %% | {error, _} ). 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), XData = find_xdata_el(SubEl), #xmlel{children = AllEls} = SubEl, Others = case XData of false -> AllEls; _ -> lists:delete(XData, AllEls) end, #adhoc_request{ lang = Lang, node = Node, sessionid = SessionID, action = Action, xdata = XData, others = Others }; parse_request(_) -> {error, ?ERR_BAD_REQUEST}. %% Borrowed from mod_vcard.erl find_xdata_el(#xmlel{children = SubEls}) -> find_xdata_el1(SubEls). find_xdata_el1([]) -> false; find_xdata_el1([El | Els]) when is_record(El, xmlel) -> case xml:get_tag_attr_s(<<"xmlns">>, El) of ?NS_XDATA -> El; _ -> find_xdata_el1(Els) end; find_xdata_el1([_ | Els]) -> find_xdata_el1(Els). %% Produce a node to use as response from an adhoc_response %% record, filling in values for language, node and session id from %% the request. %% -spec(produce_response/2 :: ( Adhoc_Request :: adhoc_request(), Adhoc_Response :: adhoc_response()) -> Xmlel::xmlel() ). %% Produce a node to use as response from an adhoc_response %% record. produce_response(#adhoc_request{lang = Lang, node = Node, sessionid = SessionID}, Adhoc_Response) -> produce_response(Adhoc_Response#adhoc_response{ lang = Lang, node = Node, sessionid = SessionID }). %% -spec(produce_response/1 :: ( Adhoc_Response::adhoc_response()) -> Xmlel::xmlel() ). produce_response( #adhoc_response{ %lang = _Lang, node = Node, sessionid = ProvidedSessionID, status = Status, defaultaction = DefaultAction, actions = Actions, notes = Notes, elements = Elements }) -> SessionID = if is_binary(ProvidedSessionID), ProvidedSessionID /= <<"">> -> ProvidedSessionID; true -> jlib:now_to_utc_string(p1_time_compat:timestamp()) end, case Actions of [] -> ActionsEls = []; _ -> case DefaultAction of <<"">> -> ActionsElAttrs = []; _ -> ActionsElAttrs = [{<<"execute">>, DefaultAction}] end, ActionsEls = [ #xmlel{ name = <<"actions">>, attrs = ActionsElAttrs, children = [ #xmlel{name = Action, attrs = [], children = []} || Action <- Actions] } ] end, NotesEls = lists:map(fun({Type, Text}) -> #xmlel{ name = <<"note">>, attrs = [{<<"type">>, Type}], children = [{xmlcdata, Text}] } end, Notes), #xmlel{ name = <<"command">>, attrs = [ {<<"xmlns">>, ?NS_COMMANDS}, {<<"sessionid">>, SessionID}, {<<"node">>, Node}, {<<"status">>, iolist_to_binary(atom_to_list(Status))} ], children = ActionsEls ++ NotesEls ++ Elements }. ejabberd-16.01/src/node_flat_odbc.erl0000644000232200023220000010603212645157216020055 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_flat_odbc.erl %%% Author : Christophe Romain %%% Purpose : Standard PubSub node plugin with ODBC backend %%% Created : 1 Dec 2007 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. %%% %%%---------------------------------------------------------------------- %%% @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'). -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, 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(), ok. terminate(_Host, _ServerHost) -> ok. options() -> [{odbc, true}, {rsm, true} | node_flat:options()]. features() -> [<<"rsm">> | 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) -> {_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), <<");">>]), {result, {default, broadcast}}. 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) -> 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 ({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, 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, 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) -> 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; 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. 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 = 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); _ -> 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 = {p1_time_compat:timestamp(), SubKey}, set_item(#pubsub_item{itemid = {ItemId, Nidx}, creation = {p1_time_compat:timestamp(), 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) -> NewItems = lists:sublist(ItemIds, MaxItems), OldItems = lists:nthtail(length(NewItems), ItemIds), del_items(Nidx, OldItems), {result, {NewItems, OldItems}}. delete_item(Nidx, Publisher, PublishModel, ItemId) -> SubKey = jid:tolower(Publisher), GenKey = 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) -> SubKey = jid:tolower(Owner), GenKey = 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) -> SubKey = jid:tolower(Owner), GenKey = 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) -> 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) -> 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 " "where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) of {selected, [<<"affiliation">>], [[A]]} -> decode_affiliation(A); _ -> none end, {result, Reply}. set_affiliation(Nidx, Owner, Affiliation) -> SubKey = jid:tolower(Owner), GenKey = 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) -> SubKey = jid:tolower(Owner), GenKey = 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) -> SubKey = jid:tolower(Owner), GenKey = 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) -> 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) -> SubKey = 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) -> SubKey = 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, []), 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), 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) -> GenKey = jid:remove_resource(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) -> 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) -> 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) -> {_, 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, RSM) -> 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 == "", ?? -> %% 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. 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) -> 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 == "", ?? -> %% 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) -> {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. 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='">>, Nidx, <<"';">>]). get_item_name(_Host, _Node, Id) -> Id. node_to_path(Node) -> node_flat:node_to_path(Node). path_to_node(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) -> jid:tolower(jid:from_string(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(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}. ejabberd-16.01/src/mod_blocking.erl0000644000232200023220000003603012645157216017562 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_blocking.erl %%% Author : Stephan Maka %%% Purpose : XEP-0191: Simple Communications Blocking %%% Created : 24 Aug 2008 by Stephan Maka %%% %%% %%% 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_blocking). -behaviour(gen_mod). -protocol({xep, 191, '1.2'}). -export([start/2, stop/1, process_iq/3, process_iq_set/4, process_iq_get/5, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("mod_privacy.hrl"). start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, one_queue), ejabberd_hooks:add(privacy_iq_get, Host, ?MODULE, process_iq_get, 40), ejabberd_hooks:add(privacy_iq_set, Host, ?MODULE, process_iq_set, 40), mod_disco:register_feature(Host, ?NS_BLOCKING), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING, ?MODULE, process_iq, IQDisc). stop(Host) -> ejabberd_hooks:delete(privacy_iq_get, Host, ?MODULE, process_iq_get, 40), ejabberd_hooks:delete(privacy_iq_set, Host, ?MODULE, process_iq_set, 40), mod_disco:unregister_feature(Host, ?NS_BLOCKING), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING). process_iq(_From, _To, IQ) -> SubEl = IQ#iq.sub_el, IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. process_iq_get(_, From, _To, #iq{xmlns = ?NS_BLOCKING, sub_el = #xmlel{name = <<"blocklist">>}}, _) -> #jid{luser = LUser, lserver = LServer} = From, {stop, process_blocklist_get(LUser, LServer)}; process_iq_get(Acc, _, _, _, _) -> Acc. process_iq_set(_, From, _To, #iq{xmlns = ?NS_BLOCKING, sub_el = #xmlel{name = SubElName, children = SubEls}}) -> #jid{luser = LUser, lserver = LServer} = From, Res = case {SubElName, xml:remove_cdata(SubEls)} of {<<"block">>, []} -> {error, ?ERR_BAD_REQUEST}; {<<"block">>, Els} -> JIDs = parse_blocklist_items(Els, []), process_blocklist_block(LUser, LServer, JIDs); {<<"unblock">>, []} -> process_blocklist_unblock_all(LUser, LServer); {<<"unblock">>, Els} -> JIDs = parse_blocklist_items(Els, []), process_blocklist_unblock(LUser, LServer, JIDs); _ -> {error, ?ERR_BAD_REQUEST} end, {stop, Res}; process_iq_set(Acc, _, _, _) -> Acc. list_to_blocklist_jids([], JIDs) -> JIDs; list_to_blocklist_jids([#listitem{type = jid, action = deny, value = JID} = Item | Items], JIDs) -> case Item of #listitem{match_all = true} -> Match = true; #listitem{match_iq = true, match_message = true, match_presence_in = true, match_presence_out = true} -> Match = true; _ -> Match = false end, if Match -> list_to_blocklist_jids(Items, [JID | JIDs]); true -> list_to_blocklist_jids(Items, JIDs) end; % Skip Privacy List items than cannot be mapped to Blocking items list_to_blocklist_jids([_ | Items], JIDs) -> list_to_blocklist_jids(Items, JIDs). parse_blocklist_items([], JIDs) -> JIDs; parse_blocklist_items([#xmlel{name = <<"item">>, attrs = Attrs} | Els], JIDs) -> case xml:get_attr(<<"jid">>, Attrs) of {value, JID1} -> JID = jid:tolower(jid:from_string(JID1)), parse_blocklist_items(Els, [JID | JIDs]); false -> parse_blocklist_items(Els, JIDs) end; parse_blocklist_items([_ | Els], JIDs) -> parse_blocklist_items(Els, JIDs). process_blocklist_block(LUser, LServer, JIDs) -> Filter = fun (List) -> AlreadyBlocked = list_to_blocklist_jids(List, []), lists:foldr(fun (JID, List1) -> case lists:member(JID, AlreadyBlocked) of true -> List1; false -> [#listitem{type = jid, value = JID, action = deny, order = 0, match_all = true} | List1] end end, List, JIDs) end, case process_blocklist_block(LUser, LServer, Filter, gen_mod:db_type(LServer, mod_privacy)) of {atomic, {ok, Default, List}} -> UserList = make_userlist(Default, List), broadcast_list_update(LUser, LServer, Default, UserList), broadcast_blocklist_event(LUser, LServer, {block, JIDs}), {result, [], UserList}; _Err -> ?ERROR_MSG("Error processing ~p: ~p", [{LUser, LServer, JIDs}, _Err]), {error, ?ERR_INTERNAL_SERVER_ERROR} end. process_blocklist_block(LUser, LServer, Filter, mnesia) -> F = fun () -> case mnesia:wread({privacy, {LUser, LServer}}) of [] -> P = #privacy{us = {LUser, LServer}}, NewDefault = <<"Blocked contacts">>, NewLists1 = [], List = []; [#privacy{default = Default, lists = Lists} = P] -> case lists:keysearch(Default, 1, Lists) of {value, {_, List}} -> NewDefault = Default, NewLists1 = lists:keydelete(Default, 1, Lists); false -> NewDefault = <<"Blocked contacts">>, NewLists1 = Lists, List = [] end end, NewList = Filter(List), NewLists = [{NewDefault, NewList} | NewLists1], mnesia:write(P#privacy{default = NewDefault, lists = NewLists}), {ok, NewDefault, NewList} end, mnesia:transaction(F); process_blocklist_block(LUser, LServer, Filter, riak) -> {atomic, begin case ejabberd_riak:get(privacy, mod_privacy:privacy_schema(), {LUser, LServer}) of {ok, #privacy{default = Default, lists = Lists} = P} -> case lists:keysearch(Default, 1, Lists) of {value, {_, List}} -> NewDefault = Default, NewLists1 = lists:keydelete(Default, 1, Lists); false -> NewDefault = <<"Blocked contacts">>, NewLists1 = Lists, List = [] end; {error, _} -> P = #privacy{us = {LUser, LServer}}, NewDefault = <<"Blocked contacts">>, NewLists1 = [], List = [] end, NewList = Filter(List), NewLists = [{NewDefault, NewList} | NewLists1], case ejabberd_riak:put(P#privacy{default = NewDefault, lists = NewLists}, mod_privacy:privacy_schema()) of ok -> {ok, NewDefault, NewList}; Err -> Err end end}; process_blocklist_block(LUser, LServer, Filter, odbc) -> F = fun () -> Default = case mod_privacy:sql_get_default_privacy_list_t(LUser) of {selected, [<<"name">>], []} -> 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 end, {selected, [<<"id">>], [[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 = [_ | _]} -> List = lists:flatmap(fun mod_privacy:raw_to_item/1, RItems); _ -> List = [] end, NewList = Filter(List), NewRItems = lists:map(fun mod_privacy:item_to_raw/1, NewList), mod_privacy:sql_set_privacy_list(ID, NewRItems), {ok, Default, NewList} end, ejabberd_odbc:sql_transaction(LServer, F). process_blocklist_unblock_all(LUser, LServer) -> Filter = fun (List) -> lists:filter(fun (#listitem{action = A}) -> A =/= deny end, List) end, DBType = gen_mod:db_type(LServer, mod_privacy), case unblock_by_filter(LUser, LServer, Filter, DBType) of {atomic, ok} -> {result, []}; {atomic, {ok, Default, List}} -> UserList = make_userlist(Default, List), broadcast_list_update(LUser, LServer, Default, UserList), broadcast_blocklist_event(LUser, LServer, unblock_all), {result, [], UserList}; _Err -> ?ERROR_MSG("Error processing ~p: ~p", [{LUser, LServer}, _Err]), {error, ?ERR_INTERNAL_SERVER_ERROR} end. process_blocklist_unblock(LUser, LServer, JIDs) -> Filter = fun (List) -> lists:filter(fun (#listitem{action = deny, type = jid, value = JID}) -> not lists:member(JID, JIDs); (_) -> true end, List) end, DBType = gen_mod:db_type(LServer, mod_privacy), case unblock_by_filter(LUser, LServer, Filter, DBType) of {atomic, ok} -> {result, []}; {atomic, {ok, Default, List}} -> UserList = make_userlist(Default, List), broadcast_list_update(LUser, LServer, Default, UserList), broadcast_blocklist_event(LUser, LServer, {unblock, JIDs}), {result, [], UserList}; _Err -> ?ERROR_MSG("Error processing ~p: ~p", [{LUser, LServer, JIDs}, _Err]), {error, ?ERR_INTERNAL_SERVER_ERROR} end. unblock_by_filter(LUser, LServer, Filter, mnesia) -> F = fun () -> case mnesia:read({privacy, {LUser, LServer}}) of [] -> % No lists, nothing to unblock ok; [#privacy{default = Default, lists = Lists} = P] -> case lists:keysearch(Default, 1, Lists) of {value, {_, List}} -> NewList = Filter(List), NewLists1 = lists:keydelete(Default, 1, Lists), NewLists = [{Default, NewList} | NewLists1], mnesia:write(P#privacy{lists = NewLists}), {ok, Default, NewList}; false -> % No default list, nothing to unblock ok end end end, mnesia:transaction(F); unblock_by_filter(LUser, LServer, Filter, riak) -> {atomic, case ejabberd_riak:get(privacy, mod_privacy:privacy_schema(), {LUser, LServer}) of {error, _} -> %% No lists, nothing to unblock ok; {ok, #privacy{default = Default, lists = Lists} = P} -> case lists:keysearch(Default, 1, Lists) of {value, {_, List}} -> NewList = Filter(List), NewLists1 = lists:keydelete(Default, 1, Lists), NewLists = [{Default, NewList} | NewLists1], case ejabberd_riak:put(P#privacy{lists = NewLists}, mod_privacy:privacy_schema()) of ok -> {ok, Default, NewList}; Err -> Err end; false -> %% No default list, nothing to unblock ok end end}; 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]]} = 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 = [_ | _]} -> List = lists:flatmap(fun mod_privacy:raw_to_item/1, RItems), NewList = Filter(List), NewRItems = lists:map(fun mod_privacy:item_to_raw/1, NewList), mod_privacy:sql_set_privacy_list(ID, NewRItems), {ok, Default, NewList}; _ -> ok end; _ -> ok end end, ejabberd_odbc:sql_transaction(LServer, F). make_userlist(Name, List) -> NeedDb = mod_privacy:is_list_needdb(List), #userlist{name = Name, list = List, needdb = NeedDb}. broadcast_list_update(LUser, LServer, Name, UserList) -> ejabberd_sm:route(jid:make(LUser, LServer, <<"">>), jid:make(LUser, LServer, <<"">>), {broadcast, {privacy_list, UserList, Name}}). broadcast_blocklist_event(LUser, LServer, Event) -> JID = jid:make(LUser, LServer, <<"">>), ejabberd_sm:route(JID, JID, {broadcast, {blocking, Event}}). process_blocklist_get(LUser, LServer) -> case process_blocklist_get(LUser, LServer, gen_mod:db_type(LServer, mod_privacy)) of error -> {error, ?ERR_INTERNAL_SERVER_ERROR}; List -> JIDs = list_to_blocklist_jids(List, []), Items = lists:map(fun (JID) -> ?DEBUG("JID: ~p", [JID]), #xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string(JID)}], children = []} end, JIDs), {result, [#xmlel{name = <<"blocklist">>, attrs = [{<<"xmlns">>, ?NS_BLOCKING}], children = Items}]} end. process_blocklist_get(LUser, LServer, mnesia) -> case catch mnesia:dirty_read(privacy, {LUser, LServer}) of {'EXIT', _Reason} -> error; [] -> []; [#privacy{default = Default, lists = Lists}] -> case lists:keysearch(Default, 1, Lists) of {value, {_, List}} -> List; _ -> [] end end; process_blocklist_get(LUser, LServer, riak) -> case ejabberd_riak:get(privacy, mod_privacy:privacy_schema(), {LUser, LServer}) of {ok, #privacy{default = Default, lists = Lists}} -> case lists:keysearch(Default, 1, Lists) of {value, {_, List}} -> List; _ -> [] end; {error, notfound} -> []; {error, _} -> error end; process_blocklist_get(LUser, LServer, odbc) -> case catch mod_privacy:sql_get_default_privacy_list(LUser, LServer) of {selected, [<<"name">>], []} -> []; {selected, [<<"name">>], [[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} -> lists:flatmap(fun mod_privacy:raw_to_item/1, RItems); {'EXIT', _} -> error end; {'EXIT', _} -> error end. mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; mod_opt_type(_) -> [iqdisc]. ejabberd-16.01/src/mod_sip_registrar.erl0000644000232200023220000004150712645157216020654 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author 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 %%% 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_sip_registrar). -define(GEN_SERVER, p1_server). -behaviour(?GEN_SERVER). %% API -export([start_link/0, request/2, find_sockets/2, ping/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("ejabberd.hrl"). -include("logger.hrl"). -include_lib("esip/include/esip.hrl"). -define(CALL_TIMEOUT, timer:seconds(30)). -define(DEFAULT_EXPIRES, 3600). -define(FLOW_TIMEOUT_UDP, 29). -define(FLOW_TIMEOUT_TCP, 120). -record(sip_session, {us = {<<"">>, <<"">>} :: {binary(), binary()}, socket = #sip_socket{} :: #sip_socket{}, call_id = <<"">> :: binary(), cseq = 0 :: non_neg_integer(), timestamp = p1_time_compat:timestamp() :: erlang:timestamp(), contact :: {binary(), #uri{}, [{binary(), binary()}]}, flow_tref :: reference(), reg_tref = make_ref() :: reference(), conn_mref = make_ref() :: reference(), expires = 0 :: non_neg_integer()}). -record(state, {}). %%%=================================================================== %%% API %%%=================================================================== start_link() -> ?GEN_SERVER:start_link({local, ?MODULE}, ?MODULE, [], []). request(#sip{hdrs = Hdrs} = Req, SIPSock) -> {_, #uri{user = U, host = S}, _} = esip:get_hdr('to', Hdrs), LUser = jid:nodeprep(U), LServer = jid:nameprep(S), {PeerIP, _} = SIPSock#sip_socket.peer, US = {LUser, LServer}, CallID = esip:get_hdr('call-id', Hdrs), CSeq = esip:get_hdr('cseq', Hdrs), Expires = esip:get_hdr('expires', Hdrs, ?DEFAULT_EXPIRES), Supported = esip:get_hdrs('supported', Hdrs), IsOutboundSupported = lists:member(<<"outbound">>, Supported), case esip:get_hdrs('contact', Hdrs) of [<<"*">>] when Expires == 0 -> case unregister_session(US, CallID, CSeq) of {ok, ContactsWithExpires} -> ?INFO_MSG("unregister SIP session for user ~s@~s from ~s", [LUser, LServer, inet_parse:ntoa(PeerIP)]), Cs = prepare_contacts_to_send(ContactsWithExpires), mod_sip:make_response( Req, #sip{type = response, status = 200, hdrs = [{'contact', Cs}]}); {error, Why} -> {Status, Reason} = make_status(Why), mod_sip:make_response( Req, #sip{type = response, status = Status, reason = Reason}) end; [{_, _URI, _Params}|_] = Contacts -> ContactsWithExpires = make_contacts_with_expires(Contacts, Expires), ContactsHaveManyRegID = contacts_have_many_reg_id(Contacts), Expires1 = lists:max([E || {_, E} <- ContactsWithExpires]), MinExpires = min_expires(), if Expires1 > 0, Expires1 < MinExpires -> mod_sip:make_response( Req, #sip{type = response, status = 423, hdrs = [{'min-expires', MinExpires}]}); ContactsHaveManyRegID -> mod_sip:make_response( Req, #sip{type = response, status = 400, reason = <<"Multiple 'reg-id' parameter">>}); true -> case register_session(US, SIPSock, CallID, CSeq, IsOutboundSupported, ContactsWithExpires) of {ok, Res} -> ?INFO_MSG("~s SIP session for user ~s@~s from ~s", [Res, LUser, LServer, inet_parse:ntoa(PeerIP)]), Cs = prepare_contacts_to_send(ContactsWithExpires), Require = case need_ob_hdrs( Contacts, IsOutboundSupported) of true -> [{'require', [<<"outbound">>]}, {'flow-timer', get_flow_timeout(LServer, SIPSock)}]; false -> [] end, mod_sip:make_response( Req, #sip{type = response, status = 200, hdrs = [{'contact', Cs}|Require]}); {error, Why} -> {Status, Reason} = make_status(Why), mod_sip:make_response( Req, #sip{type = response, status = Status, reason = Reason}) end end; [] -> case mnesia:dirty_read(sip_session, US) of [_|_] = Sessions -> ContactsWithExpires = lists:map( fun(#sip_session{contact = Contact, expires = Es}) -> {Contact, Es} end, Sessions), Cs = prepare_contacts_to_send(ContactsWithExpires), mod_sip:make_response( Req, #sip{type = response, status = 200, hdrs = [{'contact', Cs}]}); [] -> {Status, Reason} = make_status(notfound), mod_sip:make_response( Req, #sip{type = response, status = Status, reason = Reason}) end; _ -> mod_sip:make_response(Req, #sip{type = response, status = 400}) end. find_sockets(U, S) -> case mnesia:dirty_read(sip_session, {U, S}) of [_|_] = Sessions -> lists:map( fun(#sip_session{contact = {_, URI, _}, socket = Socket}) -> {Socket, URI} end, Sessions); [] -> [] end. ping(SIPSocket) -> call({ping, SIPSocket}). %%%=================================================================== %%% gen_server callbacks %%%=================================================================== init([]) -> update_table(), mnesia:create_table(sip_session, [{ram_copies, [node()]}, {type, bag}, {attributes, record_info(fields, sip_session)}]), mnesia:add_table_index(sip_session, conn_mref), mnesia:add_table_index(sip_session, socket), mnesia:add_table_copy(sip_session, node(), ram_copies), {ok, #state{}}. handle_call({write, Sessions, Supported}, _From, State) -> Res = write_session(Sessions, Supported), {reply, Res, State}; handle_call({delete, US, CallID, CSeq}, _From, State) -> Res = delete_session(US, CallID, CSeq), {reply, Res, State}; handle_call({ping, SIPSocket}, _From, State) -> Res = process_ping(SIPSocket), {reply, Res, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({write, Sessions, Supported}, State) -> write_session(Sessions, Supported), {noreply, State}; handle_info({delete, US, CallID, CSeq}, State) -> delete_session(US, CallID, CSeq), {noreply, State}; handle_info({timeout, TRef, US}, State) -> delete_expired_session(US, TRef), {noreply, State}; handle_info({'DOWN', MRef, process, _Pid, _Reason}, State) -> case mnesia:dirty_index_read(sip_session, MRef, #sip_session.conn_mref) of [Session] -> mnesia:dirty_delete_object(Session); _ -> ok end, {noreply, State}; handle_info(_Info, State) -> ?ERROR_MSG("got unexpected info: ~p", [_Info]), {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%%=================================================================== %%% Internal functions %%%=================================================================== register_session(US, SIPSocket, CallID, CSeq, IsOutboundSupported, ContactsWithExpires) -> Sessions = lists:map( fun({Contact, Expires}) -> #sip_session{us = US, socket = SIPSocket, call_id = CallID, cseq = CSeq, timestamp = p1_time_compat:timestamp(), contact = Contact, expires = Expires} end, ContactsWithExpires), Msg = {write, Sessions, IsOutboundSupported}, call(Msg). unregister_session(US, CallID, CSeq) -> Msg = {delete, US, CallID, CSeq}, call(Msg). write_session([#sip_session{us = {U, S} = US}|_] = NewSessions, IsOutboundSupported) -> PrevSessions = mnesia:dirty_read(sip_session, US), Res = lists:foldl( fun(_, {error, _} = Err) -> Err; (#sip_session{call_id = CallID, expires = Expires, cseq = CSeq} = Session, {Add, Del}) -> case find_session(Session, PrevSessions, IsOutboundSupported) of {ok, normal, #sip_session{call_id = CallID, cseq = PrevCSeq}} when PrevCSeq > CSeq -> {error, cseq_out_of_order}; {ok, _Type, PrevSession} when Expires == 0 -> {Add, [PrevSession|Del]}; {ok, _Type, PrevSession} -> {[Session|Add], [PrevSession|Del]}; {error, notfound} when Expires == 0 -> {error, notfound}; {error, notfound} -> {[Session|Add], Del} end end, {[], []}, NewSessions), MaxSessions = ejabberd_sm:get_max_user_sessions(U, S), case Res of {error, Why} -> {error, Why}; {AddSessions, DelSessions} -> MaxSessions = ejabberd_sm:get_max_user_sessions(U, S), AllSessions = AddSessions ++ PrevSessions -- DelSessions, if length(AllSessions) > MaxSessions -> {error, too_many_sessions}; true -> lists:foreach(fun delete_session/1, DelSessions), lists:foreach( fun(Session) -> NewSession = set_monitor_and_timer( Session, IsOutboundSupported), mnesia:dirty_write(NewSession) end, AddSessions), case {AllSessions, AddSessions} of {[], _} -> {ok, unregister}; {_, []} -> {ok, unregister}; _ -> {ok, register} end end end. delete_session(US, CallID, CSeq) -> case mnesia:dirty_read(sip_session, US) of [_|_] = Sessions -> case lists:all( fun(S) when S#sip_session.call_id == CallID, S#sip_session.cseq > CSeq -> false; (_) -> true end, Sessions) of true -> ContactsWithExpires = lists:map( fun(#sip_session{contact = Contact} = Session) -> delete_session(Session), {Contact, 0} end, Sessions), {ok, ContactsWithExpires}; false -> {error, cseq_out_of_order} end; [] -> {error, notfound} end. delete_expired_session(US, TRef) -> case mnesia:dirty_read(sip_session, US) of [_|_] = Sessions -> lists:foreach( fun(#sip_session{reg_tref = T1, flow_tref = T2} = Session) when T1 == TRef; T2 == TRef -> if T2 /= undefined -> close_socket(Session); true -> ok end, delete_session(Session); (_) -> ok end, Sessions); [] -> ok end. min_expires() -> 60. to_integer(Bin, Min, Max) -> case catch list_to_integer(binary_to_list(Bin)) of N when N >= Min, N =< Max -> {ok, N}; _ -> error end. call(Msg) -> case catch ?GEN_SERVER:call(?MODULE, Msg, ?CALL_TIMEOUT) of {'EXIT', {timeout, _}} -> {error, timeout}; {'EXIT', Why} -> {error, Why}; Reply -> Reply end. make_contacts_with_expires(Contacts, Expires) -> lists:map( fun({Name, URI, Params}) -> E1 = case to_integer(esip:get_param(<<"expires">>, Params), 0, (1 bsl 32)-1) of {ok, E} -> E; _ -> Expires end, Params1 = lists:keydelete(<<"expires">>, 1, Params), {{Name, URI, Params1}, E1} end, Contacts). prepare_contacts_to_send(ContactsWithExpires) -> lists:map( fun({{Name, URI, Params}, Expires}) -> Params1 = esip:set_param(<<"expires">>, list_to_binary( integer_to_list(Expires)), Params), {Name, URI, Params1} end, ContactsWithExpires). contacts_have_many_reg_id(Contacts) -> Sum = lists:foldl( fun({_Name, _URI, Params}, Acc) -> case get_ob_params(Params) of error -> Acc; {_, _} -> Acc + 1 end end, 0, Contacts), if Sum > 1 -> true; true -> false end. find_session(#sip_session{contact = {_, URI, Params}}, Sessions, IsOutboundSupported) -> if IsOutboundSupported -> case get_ob_params(Params) of {InstanceID, RegID} -> find_session_by_ob({InstanceID, RegID}, Sessions); error -> find_session_by_uri(URI, Sessions) end; true -> find_session_by_uri(URI, Sessions) end. find_session_by_ob({InstanceID, RegID}, [#sip_session{contact = {_, _, Params}} = Session|Sessions]) -> case get_ob_params(Params) of {InstanceID, RegID} -> {ok, flow, Session}; _ -> find_session_by_ob({InstanceID, RegID}, Sessions) end; find_session_by_ob(_, []) -> {error, notfound}. find_session_by_uri(URI1, [#sip_session{contact = {_, URI2, _}} = Session|Sessions]) -> case cmp_uri(URI1, URI2) of true -> {ok, normal, Session}; false -> find_session_by_uri(URI1, Sessions) end; find_session_by_uri(_, []) -> {error, notfound}. %% TODO: this is *totally* wrong. %% Rewrite this using URI comparison rules cmp_uri(#uri{user = U, host = H, port = P}, #uri{user = U, host = H, port = P}) -> true; cmp_uri(_, _) -> false. make_status(notfound) -> {404, esip:reason(404)}; make_status(cseq_out_of_order) -> {500, <<"CSeq is Out of Order">>}; make_status(timeout) -> {408, esip:reason(408)}; make_status(too_many_sessions) -> {503, <<"Too Many Registered Sessions">>}; make_status(_) -> {500, esip:reason(500)}. get_ob_params(Params) -> case esip:get_param(<<"+sip.instance">>, Params) of <<>> -> error; InstanceID -> case to_integer(esip:get_param(<<"reg-id">>, Params), 0, (1 bsl 32)-1) of {ok, RegID} -> {InstanceID, RegID}; error -> error end end. need_ob_hdrs(_Contacts, _IsOutboundSupported = false) -> false; need_ob_hdrs(Contacts, _IsOutboundSupported = true) -> lists:any( fun({_Name, _URI, Params}) -> case get_ob_params(Params) of error -> false; {_, _} -> true end end, Contacts). get_flow_timeout(LServer, #sip_socket{type = Type}) -> 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), case catch mnesia:table_info(sip_session, attributes) of Fields -> ok; [_|_] -> mnesia:delete_table(sip_session); {'EXIT', _} -> ok end. set_monitor_and_timer(#sip_session{socket = #sip_socket{type = Type, pid = Pid} = SIPSock, conn_mref = MRef, expires = Expires, us = {_, LServer}, contact = {_, _, Params}} = Session, IsOutboundSupported) -> RegTRef = set_timer(Session, Expires), Session1 = Session#sip_session{reg_tref = RegTRef}, if IsOutboundSupported -> case get_ob_params(Params) of error -> Session1; {_, _} -> FlowTimeout = get_flow_timeout(LServer, SIPSock), FlowTRef = set_timer(Session1, FlowTimeout), NewMRef = if Type == udp -> MRef; true -> erlang:monitor(process, Pid) end, Session1#sip_session{conn_mref = NewMRef, flow_tref = FlowTRef} end; true -> Session1 end. set_timer(#sip_session{us = US}, Timeout) -> erlang:start_timer(Timeout * 1000, self(), US). close_socket(#sip_session{socket = SIPSocket}) -> if SIPSocket#sip_socket.type /= udp -> esip_socket:close(SIPSocket); true -> ok end. delete_session(#sip_session{reg_tref = RegTRef, flow_tref = FlowTRef, conn_mref = MRef} = Session) -> erlang:cancel_timer(RegTRef), catch erlang:cancel_timer(FlowTRef), catch erlang:demonitor(MRef, [flush]), mnesia:dirty_delete_object(Session). process_ping(SIPSocket) -> ErrResponse = if SIPSocket#sip_socket.type == udp -> pang; true -> drop end, Sessions = mnesia:dirty_index_read( sip_session, SIPSocket, #sip_session.socket), lists:foldl( fun(#sip_session{flow_tref = TRef, us = {_, LServer}} = Session, _) when TRef /= undefined -> erlang:cancel_timer(TRef), mnesia:dirty_delete_object(Session), Timeout = get_flow_timeout(LServer, SIPSocket), NewTRef = set_timer(Session, Timeout), case mnesia:dirty_write( Session#sip_session{flow_tref = NewTRef}) of ok -> pong; _Err -> pang end; (_, Acc) -> Acc end, ErrResponse, Sessions). ejabberd-16.01/src/mod_sip_proxy.erl0000644000232200023220000003325612645157216020035 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author 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 %%% 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_sip_proxy). -behaviour(ejabberd_config). -define(GEN_FSM, p1_fsm). -behaviour(?GEN_FSM). %% API -export([start/2, start_link/2, route/3, route/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"). -include_lib("esip/include/esip.hrl"). -define(SIGN_LIFETIME, 300). %% in seconds. -record(state, {host = <<"">> :: binary(), opts = [] :: [{certfile, binary()}], orig_trid, responses = [] :: [#sip{}], tr_ids = [] :: list(), orig_req :: #sip{}}). %%%=================================================================== %%% API %%%=================================================================== start(LServer, Opts) -> supervisor:start_child(mod_sip_proxy_sup, [LServer, Opts]). start_link(LServer, Opts) -> ?GEN_FSM:start_link(?MODULE, [LServer, Opts], []). route(SIPMsg, _SIPSock, TrID, Pid) -> ?GEN_FSM:send_event(Pid, {SIPMsg, TrID}). route(#sip{hdrs = Hdrs} = Req, LServer, Opts) -> case proplists:get_bool(authenticated, Opts) of true -> route_statelessly(Req, LServer, Opts); false -> ConfiguredRRoute = get_configured_record_route(LServer), case esip:get_hdrs('route', Hdrs) of [{_, URI, _}|_] -> case cmp_uri(URI, ConfiguredRRoute) of true -> case is_signed_by_me(URI#uri.user, Hdrs) of true -> route_statelessly(Req, LServer, Opts); false -> error end; false -> error end; [] -> error end end. route_statelessly(Req, LServer, Opts) -> Req1 = prepare_request(LServer, Req), case connect(Req1, add_certfile(LServer, Opts)) of {ok, SIPSocketsWithURIs} -> lists:foreach( fun({SIPSocket, _URI}) -> Req2 = add_via(SIPSocket, LServer, Req1), esip:send(SIPSocket, Req2) end, SIPSocketsWithURIs); _ -> error end. %%%=================================================================== %%% gen_fsm callbacks %%%=================================================================== init([Host, Opts]) -> Opts1 = add_certfile(Host, Opts), {ok, wait_for_request, #state{opts = Opts1, host = Host}}. wait_for_request({#sip{type = request} = Req, TrID}, State) -> Opts = State#state.opts, Req1 = prepare_request(State#state.host, Req), case connect(Req1, Opts) of {ok, SIPSocketsWithURIs} -> NewState = lists:foldl( fun(_SIPSocketWithURI, {error, _} = Err) -> Err; ({SIPSocket, URI}, #state{tr_ids = TrIDs} = AccState) -> Req2 = add_record_route_and_set_uri( URI, State#state.host, Req1), Req3 = add_via(SIPSocket, State#state.host, Req2), case esip:request(SIPSocket, Req3, {?MODULE, route, [self()]}) of {ok, ClientTrID} -> NewTrIDs = [ClientTrID|TrIDs], AccState#state{tr_ids = NewTrIDs}; Err -> cancel_pending_transactions(AccState), Err end end, State, SIPSocketsWithURIs), case NewState of {error, _} = Err -> {Status, Reason} = esip:error_status(Err), esip:reply(TrID, mod_sip:make_response( Req, #sip{type = response, status = Status, reason = Reason})), {stop, normal, State}; _ -> {next_state, wait_for_response, NewState#state{orig_req = Req, orig_trid = TrID}} end; {error, notfound} -> esip:reply(TrID, mod_sip:make_response( Req, #sip{type = response, status = 480, reason = esip:reason(480)})), {stop, normal, State}; Err -> {Status, Reason} = esip:error_status(Err), esip:reply(TrID, mod_sip:make_response( Req, #sip{type = response, status = Status, reason = Reason})), {stop, normal, State} end; wait_for_request(_Event, State) -> {next_state, wait_for_request, State}. wait_for_response({#sip{method = <<"CANCEL">>, type = request}, _TrID}, State) -> cancel_pending_transactions(State), {next_state, wait_for_response, State}; wait_for_response({Resp, TrID}, #state{orig_req = #sip{method = Method} = Req} = State) -> case Resp of {error, timeout} when Method /= <<"INVITE">> -> %% Absorb useless 408. See RFC4320 choose_best_response(State), esip:stop_transaction(State#state.orig_trid), {stop, normal, State}; {error, _} -> {Status, Reason} = esip:error_status(Resp), State1 = mark_transaction_as_complete(TrID, State), SIPResp = mod_sip:make_response(Req, #sip{type = response, status = Status, reason = Reason}), State2 = collect_response(SIPResp, State1), case State2#state.tr_ids of [] -> choose_best_response(State2), {stop, normal, State2}; _ -> {next_state, wait_for_response, State2} end; #sip{status = 100} -> {next_state, wait_for_response, State}; #sip{status = Status} -> {[_|Vias], NewHdrs} = esip:split_hdrs('via', Resp#sip.hdrs), NewResp = case Vias of [] -> Resp#sip{hdrs = NewHdrs}; _ -> Resp#sip{hdrs = [{'via', Vias}|NewHdrs]} end, if Status < 300 -> esip:reply(State#state.orig_trid, NewResp); true -> ok end, State1 = if Status >= 200 -> mark_transaction_as_complete(TrID, State); true -> State end, State2 = if Status >= 300 -> collect_response(NewResp, State1); true -> State1 end, if Status >= 600 -> cancel_pending_transactions(State2); true -> ok end, case State2#state.tr_ids of [] -> choose_best_response(State2), {stop, normal, State2}; _ -> {next_state, wait_for_response, State2} end end; wait_for_response(_Event, State) -> {next_state, wait_for_response, State}. handle_event(_Event, StateName, State) -> {next_state, StateName, State}. handle_sync_event(_Event, _From, StateName, State) -> Reply = ok, {reply, Reply, StateName, State}. handle_info(_Info, StateName, State) -> {next_state, StateName, State}. terminate(_Reason, _StateName, _State) -> ok. code_change(_OldVsn, StateName, State, _Extra) -> {ok, StateName, State}. %%%=================================================================== %%% Internal functions %%%=================================================================== connect(#sip{hdrs = Hdrs} = Req, Opts) -> {_, ToURI, _} = esip:get_hdr('to', Hdrs), case mod_sip:at_my_host(ToURI) of true -> LUser = jid:nodeprep(ToURI#uri.user), LServer = jid:nameprep(ToURI#uri.host), case mod_sip_registrar:find_sockets(LUser, LServer) of [_|_] = SIPSocks -> {ok, SIPSocks}; [] -> {error, notfound} end; false -> case esip:connect(Req, Opts) of {ok, SIPSock} -> {ok, [{SIPSock, Req#sip.uri}]}; {error, _} = Err -> Err end end. cancel_pending_transactions(State) -> lists:foreach(fun esip:cancel/1, State#state.tr_ids). add_certfile(LServer, Opts) -> case ejabberd_config:get_option({domain_certfile, LServer}, fun iolist_to_binary/1) of CertFile when is_binary(CertFile), CertFile /= <<"">> -> [{certfile, CertFile}|Opts]; _ -> Opts end. add_via(#sip_socket{type = Transport}, LServer, #sip{hdrs = Hdrs} = Req) -> ConfiguredVias = get_configured_vias(LServer), {ViaHost, ViaPort} = proplists:get_value( Transport, ConfiguredVias, {LServer, undefined}), ViaTransport = case Transport of tls -> <<"TLS">>; tcp -> <<"TCP">>; udp -> <<"UDP">> end, Via = #via{transport = ViaTransport, host = ViaHost, port = ViaPort, params = [{<<"branch">>, esip:make_branch()}]}, Req#sip{hdrs = [{'via', [Via]}|Hdrs]}. add_record_route_and_set_uri(URI, LServer, #sip{hdrs = Hdrs} = Req) -> case is_request_within_dialog(Req) of false -> case need_record_route(LServer) of true -> RR_URI = get_configured_record_route(LServer), 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}, Hdrs1 = [{'record-route', [{<<>>, NewRR_URI, []}]}|Hdrs], Req#sip{uri = URI, hdrs = Hdrs1}; false -> Req end; true -> Req end. is_request_within_dialog(#sip{hdrs = Hdrs}) -> {_, _, Params} = esip:get_hdr('to', Hdrs), esip:has_param(<<"tag">>, Params). need_record_route(LServer) -> gen_mod:get_module_opt( LServer, mod_sip, always_record_route, fun(true) -> true; (false) -> false end, true). make_sign(TS, Hdrs) -> {_, #uri{user = FUser, host = FServer}, FParams} = esip:get_hdr('from', Hdrs), {_, #uri{user = TUser, host = TServer}, _} = esip:get_hdr('to', Hdrs), LFUser = safe_nodeprep(FUser), LTUser = safe_nodeprep(TUser), LFServer = safe_nameprep(FServer), LTServer = safe_nameprep(TServer), FromTag = esip:get_param(<<"tag">>, FParams), CallID = esip:get_hdr('call-id', Hdrs), SharedKey = ejabberd_config:get_option(shared_key, fun(V) -> V end), p1_sha:sha([SharedKey, LFUser, LFServer, LTUser, LTServer, FromTag, CallID, TS]). is_signed_by_me(TS_Sign, Hdrs) -> try [TSBin, Sign] = str:tokens(TS_Sign, <<"-">>), TS = list_to_integer(binary_to_list(TSBin)), NowTS = p1_time_compat:system_time(seconds), true = (NowTS - TS) =< ?SIGN_LIFETIME, Sign == make_sign(TSBin, Hdrs) catch _:_ -> false end. get_configured_vias(LServer) -> gen_mod:get_module_opt( LServer, mod_sip, 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, []). get_configured_record_route(LServer) -> gen_mod:get_module_opt( LServer, mod_sip, record_route, fun(IOList) -> S = iolist_to_binary(IOList), #uri{} = esip:decode_uri(S) end, #uri{host = LServer, params = [{<<"lr">>, <<"">>}]}). get_configured_routes(LServer) -> gen_mod:get_module_opt( LServer, mod_sip, routes, fun(L) -> lists:map( fun(IOList) -> S = iolist_to_binary(IOList), #uri{} = esip:decode_uri(S) end, L) end, [#uri{host = LServer, params = [{<<"lr">>, <<"">>}]}]). mark_transaction_as_complete(TrID, State) -> NewTrIDs = lists:delete(TrID, State#state.tr_ids), State#state{tr_ids = NewTrIDs}. collect_response(Resp, #state{responses = Resps} = State) -> State#state{responses = [Resp|Resps]}. choose_best_response(#state{responses = Responses} = State) -> SortedResponses = lists:keysort(#sip.status, Responses), case lists:filter( fun(#sip{status = Status}) -> Status >= 600 end, SortedResponses) of [Resp|_] -> esip:reply(State#state.orig_trid, Resp); [] -> case SortedResponses of [Resp|_] -> esip:reply(State#state.orig_trid, Resp); [] -> ok end end. %% Just compare host part only. cmp_uri(#uri{host = H1}, #uri{host = H2}) -> jid:nameprep(H1) == jid:nameprep(H2). is_my_route(URI, URIs) -> lists:any(fun(U) -> cmp_uri(URI, U) end, URIs). prepare_request(LServer, #sip{hdrs = Hdrs} = Req) -> ConfiguredRRoute = get_configured_record_route(LServer), ConfiguredRoutes = get_configured_routes(LServer), Hdrs1 = lists:flatmap( fun({Hdr, HdrList}) when Hdr == 'route'; Hdr == 'record-route' -> case lists:filter( fun({_, URI, _}) -> not cmp_uri(URI, ConfiguredRRoute) and not is_my_route(URI, ConfiguredRoutes) end, HdrList) of [] -> []; HdrList1 -> [{Hdr, HdrList1}] end; (Hdr) -> [Hdr] end, Hdrs), MF = esip:get_hdr('max-forwards', Hdrs1), Hdrs2 = esip:set_hdr('max-forwards', MF-1, Hdrs1), Hdrs3 = lists:filter( fun({'proxy-authorization', {_, Params}}) -> Realm = esip:unquote(esip:get_param(<<"realm">>, Params)), not mod_sip:is_my_host(jid:nameprep(Realm)); (_) -> true end, Hdrs2), Req#sip{hdrs = Hdrs3}. safe_nodeprep(S) -> case jid:nodeprep(S) of error -> S; S1 -> S1 end. safe_nameprep(S) -> case jid:nameprep(S) of 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]. ejabberd-16.01/src/ejabberd_tmp_sup.erl0000644000232200023220000000271712645157216020445 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_tmp_sup.erl %%% Author : Alexey Shchepin %%% Purpose : Supervisor for temporary processess %%% Created : 18 Jul 2003 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_tmp_sup). -author('alexey@process-one.net'). -export([start_link/2, init/1]). start_link(Name, Module) -> supervisor:start_link({local, Name}, ?MODULE, Module). init(Module) -> {ok, {{simple_one_for_one, 10, 1}, [{undefined, {Module, start_link, []}, temporary, 1000, worker, [Module]}]}}. ejabberd-16.01/src/ejabberd_sup.erl0000644000232200023220000000735012645157216017563 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_sup.erl %%% Author : Alexey Shchepin %%% Purpose : Erlang/OTP supervisor %%% Created : 31 Jan 2003 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_sup). -author('alexey@process-one.net'). -behaviour(supervisor). -export([start_link/0, init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> Hooks = {ejabberd_hooks, {ejabberd_hooks, start_link, []}, permanent, brutal_kill, worker, [ejabberd_hooks]}, NodeGroups = {ejabberd_node_groups, {ejabberd_node_groups, start_link, []}, permanent, brutal_kill, worker, [ejabberd_node_groups]}, SystemMonitor = {ejabberd_system_monitor, {ejabberd_system_monitor, start_link, []}, permanent, brutal_kill, worker, [ejabberd_system_monitor]}, Router = {ejabberd_router, {ejabberd_router, start_link, []}, permanent, brutal_kill, worker, [ejabberd_router]}, Router_multicast = {ejabberd_router_multicast, {ejabberd_router_multicast, start_link, []}, permanent, brutal_kill, worker, [ejabberd_router_multicast]}, S2S = {ejabberd_s2s, {ejabberd_s2s, start_link, []}, permanent, brutal_kill, worker, [ejabberd_s2s]}, Local = {ejabberd_local, {ejabberd_local, start_link, []}, permanent, brutal_kill, worker, [ejabberd_local]}, Captcha = {ejabberd_captcha, {ejabberd_captcha, start_link, []}, permanent, brutal_kill, worker, [ejabberd_captcha]}, Listener = {ejabberd_listener, {ejabberd_listener, start_link, []}, permanent, infinity, supervisor, [ejabberd_listener]}, S2SInSupervisor = {ejabberd_s2s_in_sup, {ejabberd_tmp_sup, start_link, [ejabberd_s2s_in_sup, ejabberd_s2s_in]}, permanent, infinity, supervisor, [ejabberd_tmp_sup]}, S2SOutSupervisor = {ejabberd_s2s_out_sup, {ejabberd_tmp_sup, start_link, [ejabberd_s2s_out_sup, ejabberd_s2s_out]}, permanent, infinity, supervisor, [ejabberd_tmp_sup]}, ServiceSupervisor = {ejabberd_service_sup, {ejabberd_tmp_sup, start_link, [ejabberd_service_sup, ejabberd_service]}, permanent, infinity, supervisor, [ejabberd_tmp_sup]}, FrontendSocketSupervisor = {ejabberd_frontend_socket_sup, {ejabberd_tmp_sup, start_link, [ejabberd_frontend_socket_sup, ejabberd_frontend_socket]}, permanent, infinity, supervisor, [ejabberd_tmp_sup]}, IQSupervisor = {ejabberd_iq_sup, {ejabberd_tmp_sup, start_link, [ejabberd_iq_sup, gen_iq_handler]}, permanent, infinity, supervisor, [ejabberd_tmp_sup]}, {ok, {{one_for_one, 10, 1}, [Hooks, NodeGroups, SystemMonitor, Router, Router_multicast, S2S, Local, Captcha, S2SInSupervisor, S2SOutSupervisor, ServiceSupervisor, IQSupervisor, FrontendSocketSupervisor, Listener]}}. ejabberd-16.01/src/mod_disco.erl0000644000232200023220000004140112645157216017071 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_disco.erl %%% Author : Alexey Shchepin %%% Purpose : Service Discovery (XEP-0030) support %%% Created : 1 Jan 2003 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(mod_disco). -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, process_local_iq_info/3, get_local_identity/5, get_local_features/5, get_local_services/5, process_sm_iq_items/3, process_sm_iq_info/3, 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, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("mod_roster.hrl"). start(Host, Opts) -> ejabberd_local:refresh_iq_handlers(), 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_DISCO_ITEMS, ?MODULE, process_local_iq_items, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO, ?MODULE, process_local_iq_info, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_DISCO_ITEMS, ?MODULE, process_sm_iq_items, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_DISCO_INFO, ?MODULE, process_sm_iq_info, IQDisc), catch ets:new(disco_features, [named_table, ordered_set, public]), register_feature(Host, <<"iq">>), register_feature(Host, <<"presence">>), catch ets:new(disco_extra_domains, [named_table, ordered_set, public]), ExtraDomains = gen_mod:get_opt(extra_domains, Opts, fun(Hs) -> [iolist_to_binary(H) || H <- Hs] end, []), lists:foreach(fun (Domain) -> register_extra_domain(Host, Domain) end, ExtraDomains), catch ets:new(disco_sm_features, [named_table, ordered_set, public]), catch ets:new(disco_sm_nodes, [named_table, ordered_set, public]), ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_local_services, 100), ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 100), ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, get_local_identity, 100), ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_items, 100), ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 100), ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100), ejabberd_hooks:add(disco_info, Host, ?MODULE, get_info, 100), ok. stop(Host) -> ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 100), ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 100), ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 100), ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, get_local_identity, 100), ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 100), ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_local_services, 100), ejabberd_hooks:delete(disco_info, Host, ?MODULE, get_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), catch ets:match_delete(disco_features, {{'_', Host}}), catch ets:match_delete(disco_extra_domains, {{'_', Host}}), ok. register_feature(Host, Feature) -> catch ets:new(disco_features, [named_table, ordered_set, public]), ets:insert(disco_features, {{Feature, Host}}). unregister_feature(Host, Feature) -> catch ets:new(disco_features, [named_table, ordered_set, public]), ets:delete(disco_features, {Feature, Host}). register_extra_domain(Host, Domain) -> catch ets:new(disco_extra_domains, [named_table, ordered_set, public]), ets:insert(disco_extra_domains, {{Domain, Host}}). unregister_extra_domain(Host, Domain) -> catch ets:new(disco_extra_domains, [named_table, ordered_set, public]), ets:delete(disco_extra_domains, {Domain, Host}). 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]}; get -> Node = xml:get_tag_attr_s(<<"node">>, SubEl), Host = To#jid.lserver, case ejabberd_hooks:run_fold(disco_local_items, Host, empty, [From, To, Node, Lang]) of {result, Items} -> ANode = case Node of <<"">> -> []; _ -> [{<<"node">>, Node}] end, IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_ITEMS} | ANode], children = Items}]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end end. process_local_iq_info(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]}; get -> Host = To#jid.lserver, Node = xml: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, [], [Host, ?MODULE, Node, Lang]), case ejabberd_hooks:run_fold(disco_local_features, Host, empty, [From, To, Node, Lang]) of {result, Features} -> ANode = case Node of <<"">> -> []; _ -> [{<<"node">>, Node}] end, IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_INFO} | ANode], children = Identity ++ Info ++ features_to_xml(Features)}]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end end. get_local_identity(Acc, _From, _To, <<>>, _Lang) -> Acc ++ [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"server">>}, {<<"type">>, <<"im">>}, {<<"name">>, <<"ejabberd">>}], children = []}]; get_local_identity(Acc, _From, _To, _Node, _Lang) -> Acc. get_local_features({error, _Error} = Acc, _From, _To, _Node, _Lang) -> Acc; get_local_features(Acc, _From, To, <<>>, _Lang) -> Feats = case Acc of {result, Features} -> Features; empty -> [] end, Host = To#jid.lserver, {result, ets:select(disco_features, [{{{'_', Host}}, [], ['$_']}]) ++ Feats}; get_local_features(Acc, _From, _To, _Node, _Lang) -> case Acc of {result, _Features} -> Acc; empty -> {error, ?ERR_ITEM_NOT_FOUND} end. features_to_xml(FeatureList) -> [#xmlel{name = <<"feature">>, attrs = [{<<"var">>, Feat}], children = []} || Feat <- lists:usort(lists:map(fun ({{Feature, _Host}}) -> Feature; (Feature) when is_binary(Feature) -> Feature end, FeatureList))]. domain_to_xml({Domain}) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Domain}], children = []}; domain_to_xml(Domain) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Domain}], children = []}. get_local_services({error, _Error} = Acc, _From, _To, _Node, _Lang) -> Acc; get_local_services(Acc, _From, To, <<>>, _Lang) -> Items = case Acc of {result, Its} -> Its; empty -> [] end, Host = To#jid.lserver, {result, lists:usort(lists:map(fun domain_to_xml/1, get_vh_services(Host) ++ ets:select(disco_extra_domains, [{{{'$1', Host}}, [], ['$1']}]))) ++ Items}; get_local_services({result, _} = Acc, _From, _To, _Node, _Lang) -> Acc; get_local_services(empty, _From, _To, _Node, _Lang) -> {error, ?ERR_ITEM_NOT_FOUND}. get_vh_services(Host) -> Hosts = lists:sort(fun (H1, H2) -> byte_size(H1) >= byte_size(H2) end, ?MYHOSTS), lists:filter(fun (H) -> case lists:dropwhile(fun (VH) -> not str:suffix( <<".", VH/binary>>, H) end, Hosts) of [] -> false; [VH | _] -> VH == Host end end, ejabberd_router:dirty_get_all_routes()). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% process_sm_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]}; get -> case is_presence_subscribed(From, To) of true -> Host = To#jid.lserver, Node = xml:get_tag_attr_s(<<"node">>, SubEl), case ejabberd_hooks:run_fold(disco_sm_items, Host, empty, [From, To, Node, Lang]) of {result, Items} -> ANode = case Node of <<"">> -> []; _ -> [{<<"node">>, Node}] end, IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_ITEMS} | ANode], children = Items}]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end; false -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]} end end. get_sm_items({error, _Error} = Acc, _From, _To, _Node, _Lang) -> Acc; get_sm_items(Acc, From, #jid{user = User, server = Server} = To, <<>>, _Lang) -> Items = case Acc of {result, Its} -> Its; empty -> [] end, Items1 = case is_presence_subscribed(From, To) of true -> get_user_resources(User, Server); _ -> [] end, {result, Items ++ Items1}; get_sm_items({result, _} = Acc, _From, _To, _Node, _Lang) -> Acc; get_sm_items(empty, From, To, _Node, _Lang) -> #jid{luser = LFrom, lserver = LSFrom} = From, #jid{luser = LTo, lserver = LSTo} = To, case {LFrom, LSFrom} of {LTo, LSTo} -> {error, ?ERR_ITEM_NOT_FOUND}; _ -> {error, ?ERR_NOT_ALLOWED} end. is_presence_subscribed(#jid{luser = User, lserver = Server}, #jid{luser = User, lserver = Server}) -> true; 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, ToServer, [], [{ToUser, ToServer}])). process_sm_iq_info(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]}; get -> case is_presence_subscribed(From, To) of true -> Host = To#jid.lserver, Node = xml:get_tag_attr_s(<<"node">>, SubEl), Identity = ejabberd_hooks:run_fold(disco_sm_identity, Host, [], [From, To, Node, Lang]), case ejabberd_hooks:run_fold(disco_sm_features, Host, empty, [From, To, Node, Lang]) of {result, Features} -> ANode = case Node of <<"">> -> []; _ -> [{<<"node">>, Node}] end, IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_INFO} | ANode], children = Identity ++ features_to_xml(Features)}]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} end; false -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]} end end. get_sm_identity(Acc, _From, #jid{luser = LUser, lserver = LServer}, _Node, _Lang) -> Acc ++ case ejabberd_auth:is_user_exists(LUser, LServer) of true -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"account">>}, {<<"type">>, <<"registered">>}], children = []}]; _ -> [] end. get_sm_features(empty, From, To, _Node, _Lang) -> #jid{luser = LFrom, lserver = LSFrom} = From, #jid{luser = LTo, lserver = LSTo} = To, case {LFrom, LSFrom} of {LTo, LSTo} -> {error, ?ERR_ITEM_NOT_FOUND}; _ -> {error, ?ERR_NOT_ALLOWED} end; get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. get_user_resources(User, Server) -> Rs = ejabberd_sm:get_user_resources(User, Server), lists:map(fun (R) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, <>}, {<<"name">>, User}], children = []} end, lists:sort(Rs)). transform_module_options(Opts) -> lists:map( fun({server_info, Infos}) -> NewInfos = lists:map( fun({Modules, Name, URLs}) -> [[{modules, Modules}, {name, Name}, {urls, URLs}]]; (Opt) -> Opt end, Infos), {server_info, NewInfos}; (Opt) -> Opt end, Opts). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Support for: XEP-0157 Contact Addresses for XMPP Services get_info(_A, Host, Mod, Node, _Lang) when Node == <<>> -> Module = case Mod of undefined -> ?MODULE; _ -> Mod end, Serverinfo_fields = get_fields_xml(Host, Module), [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}], children = [#xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"FORM_TYPE">>}, {<<"type">>, <<"hidden">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, ?NS_SERVERINFO}]}]}] ++ Serverinfo_fields}]; get_info(Acc, _, _, _Node, _) -> Acc. get_fields_xml(Host, Module) -> Fields = gen_mod:get_module_opt( Host, ?MODULE, 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, []), Fields_good = lists:filter(fun ({Modules, _, _}) -> case Modules of all -> true; Modules -> lists:member(Module, Modules) end end, Fields), fields_to_xml(Fields_good). fields_to_xml(Fields) -> [field_to_xml(Field) || Field <- Fields]. field_to_xml({_, Var, Values}) -> Values_xml = values_to_xml(Values), #xmlel{name = <<"field">>, attrs = [{<<"var">>, Var}], children = Values_xml}. values_to_xml(Values) -> lists:map(fun (Value) -> #xmlel{name = <<"value">>, attrs = [], 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]. ejabberd-16.01/src/cyrsasl_oauth.erl0000644000232200023220000000612112645157216020011 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% 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/4, mech_step/2, parse/1]). -behaviour(cyrsasl). -record(state, {host}). start(_Opts) -> cyrsasl:register_mechanism(<<"X-OAUTH2">>, ?MODULE, plain), ok. stop() -> ok. mech_new(Host, _GetPassword, _CheckPassword, _CheckPasswordDigest) -> {ok, #state{host = Host}}. mech_step(State, ClientIn) -> case prepare(ClientIn) of [AuthzId, User, Token] -> 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, <<"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]). ejabberd-16.01/src/cyrsasl_anonymous.erl0000644000232200023220000000372412645157216020727 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : cyrsasl_anonymous.erl %%% Author : Magnus Henoch %%% Purpose : ANONYMOUS SASL mechanism %%% See http://www.ietf.org/internet-drafts/draft-ietf-sasl-anon-05.txt %%% Created : 23 Aug 2005 by Magnus Henoch %%% %%% %%% 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_anonymous). -protocol({xep, 175, '1.2'}). -export([start/1, stop/0, mech_new/4, mech_step/2]). -behaviour(cyrsasl). -record(state, {server = <<"">> :: binary()}). start(_Opts) -> cyrsasl:register_mechanism(<<"ANONYMOUS">>, ?MODULE, plain), ok. stop() -> ok. mech_new(Host, _GetPassword, _CheckPassword, _CheckPasswordDigest) -> {ok, #state{server = Host}}. 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 -> mech_step(S, ClientIn); false -> {ok, [{username, User}, {auth_module, ejabberd_auth_anonymous}]} end. ejabberd-16.01/src/mod_version.erl0000644000232200023220000000612712645157216017463 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_version.erl %%% Author : Alexey Shchepin %%% Purpose : XEP-0092: Software Version %%% Created : 18 Jan 2003 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(mod_version). -author('alexey@process-one.net'). -protocol({xep, 92, '1.1'}). -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). 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_VERSION, ?MODULE, process_local_iq, IQDisc). stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VERSION). process_local_iq(_From, To, #iq{id = _ID, type = Type, xmlns = _XMLNS, sub_el = SubEl} = IQ) -> case Type of set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; get -> Host = To#jid.lserver, OS = case gen_mod:get_module_opt(Host, ?MODULE, show_os, fun(B) when is_boolean(B) -> B end, true) of true -> [get_os()]; false -> [] end, IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_VERSION}], children = [#xmlel{name = <<"name">>, attrs = [], children = [{xmlcdata, <<"ejabberd">>}]}, #xmlel{name = <<"version">>, attrs = [], children = [{xmlcdata, ?VERSION}]}] ++ OS}]} end. get_os() -> {Osfamily, Osname} = os:type(), OSType = list_to_binary([atom_to_list(Osfamily), $/, atom_to_list(Osname)]), OSVersion = case os:version() of {Major, Minor, Release} -> iolist_to_binary(io_lib:format("~w.~w.~w", [Major, Minor, Release])); VersionString -> VersionString end, 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]. ejabberd-16.01/src/node_pep.erl0000644000232200023220000002021012645157216016715 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : node_pep.erl %%% Author : Christophe Romain %%% Purpose : Standard PubSub PEP plugin %%% Created : 1 Dec 2007 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. %%% %%%---------------------------------------------------------------------- %%% @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("pubsub.hrl"). -include("jlib.hrl"). -include("logger.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]). init(Host, ServerHost, Opts) -> node_flat:init(Host, ServerHost, Opts), complain_if_modcaps_disabled(ServerHost), ok. terminate(Host, ServerHost) -> node_flat: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, 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">>]. create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> LOwner = 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; _ -> false end end, {result, Allowed}. create_node(Nidx, Owner) -> node_flat:create_node(Nidx, Owner). delete_node(Nodes) -> {result, {_, _, Result}} = node_flat:delete_node(Nodes), {result, {[], Result}}. 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) -> 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_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) -> {_, 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) -> case NodeTree:get_node(N) of #pubsub_node{nodeid = {{_, D, _}, _}} = Node -> [{Node, A} | Acc]; _ -> Acc end end, [], States), {result, Reply}. 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) -> {U, D, _} = SubKey = jid:tolower(Owner), GenKey = 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 = {{_, 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}. 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 %%% %% @doc Check mod_caps is enabled, otherwise show warning. %% The PEP plugin for mod_pubsub requires mod_caps to be enabled in the host. %% 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) -> 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. ejabberd-16.01/src/ejabberd_piefxis.erl0000644000232200023220000006163112645157216020425 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_piefxis.erl %%% Author : Pablo Polvorin, Vidal Santiago Martinez %%% Purpose : XEP-0227: Portable Import/Export Format for XMPP-IM Servers %%% Created : 17 Jul 2008 by Pablo Polvorin %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov %%% @doc %%% %%% %%% 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. %%% %%%---------------------------------------------------------------------- %%% Not implemented: %%% - write mod_piefxis with ejabberdctl commands %%% - Export from mod_offline_odbc.erl %%% - Export from mod_private_odbc.erl %%% - XEP-227: 6. Security Considerations %%% - Other schemas of XInclude are not tested, and may not be imported correctly. %%% - If a host has many users, split that host in XML files with 50 users each. %%%% Headers -module(ejabberd_piefxis). -behaviour(ejabberd_config). -protocol({xep, 227, '1.0'}). -export([import_file/1, export_server/1, export_host/2, opt_type/1]). -define(CHUNK_SIZE, 1024*20). %20k -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("mod_privacy.hrl"). -include("mod_roster.hrl"). %%-include_lib("exmpp/include/exmpp.hrl"). %%-include_lib("exmpp/include/exmpp_client.hrl"). %% Copied from exmpp header files: %% Copied from mod_private.erl %%-define(ERROR_MSG(M,Args),io:format(M,Args)). %%-define(INFO_MSG(M,Args),ok). %%%================================== %%%% Import file -define(NS_PIE, <<"urn:xmpp:pie:0">>). -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(), user = <<"">> :: binary(), server = <<"">> :: binary(), fd :: file:io_device(), dir = <<"">> :: binary()}). -type state() :: #state{}. %%File could be large.. we read it in chunks %%%=================================================================== %%% API %%%=================================================================== 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} -> Dir = filename:dirname(FileName), XMLStreamState = xml_stream:new(self(), infinity), Res = process(State#state{xml_stream_state = XMLStreamState, fd = Fd, dir = Dir}), file:close(Fd), Res; {error, Reason} -> ErrTxt = file:format_error(Reason), ?ERROR_MSG("Failed to open file '~s': ~s", [FileName, ErrTxt]), {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 %%%=================================================================== export_hosts(Hosts, Dir) -> FnT = make_filename_template(), DFn = make_main_basefilename(Dir, FnT), case file:open(DFn, [raw, write]) of {ok, Fd} -> print(Fd, make_piefxis_xml_head()), print(Fd, make_piefxis_server_head()), FilesAndHosts = [{make_host_filename(FnT, Host), Host} || Host <- Hosts], lists:foreach( fun({FnH, _}) -> print(Fd, make_xinclude(FnH)) end, FilesAndHosts), print(Fd, make_piefxis_server_tail()), print(Fd, make_piefxis_xml_tail()), file:close(Fd), lists:foldl( fun({FnH, Host}, ok) -> export_host(Dir, FnH, Host); (_, Err) -> Err end, ok, FilesAndHosts); {error, Reason} -> ErrTxt = file:format_error(Reason), ?ERROR_MSG("Failed to open file '~s': ~s", [DFn, ErrTxt]), {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 {ok, Fd} -> print(Fd, make_piefxis_xml_head()), print(Fd, make_piefxis_host_head(Host)), Users = ejabberd_auth:get_vh_registered_users(Host), case export_users(Users, Host, Fd) of ok -> print(Fd, make_piefxis_host_tail()), print(Fd, make_piefxis_xml_tail()), file:close(Fd), ok; Err -> file:close(Fd), file:delete(DFn), Err end; {error, Reason} -> ErrTxt = file:format_error(Reason), ?ERROR_MSG("Failed to open file '~s': ~s", [DFn, ErrTxt]), {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 -> export_users(Users, Server, Fd); Err -> Err end; export_users([], _Server, _Fd) -> ok. %%%================================== %%%% Utilities export_user(User, Server, Fd) -> Password = ejabberd_auth:get_password_s(User, Server), LServer = jid: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) ++ get_roster(User, Server) ++ get_private(User, Server), print(Fd, xml:element_to_binary( #xmlel{name = <<"user">>, attrs = [{<<"name">>, User}, {<<"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 = jid:make(User, Server, <<>>), case mod_vcard:process_sm_iq(JID, JID, #iq{type = get}) of #iq{type = result, sub_el = [_|_] = VCardEls} -> VCardEls; _ -> [] end. %%%================================== get_offline(User, Server) -> case mod_offline:get_offline_els(User, Server) of [] -> []; Els -> NewEls = lists:map( fun(#xmlel{attrs = Attrs} = El) -> NewAttrs = lists:keystore(<<"xmlns">>, 1, Attrs, {<<"xmlns">>, <<"jabber:client">>}), El#xmlel{attrs = NewAttrs} end, Els), [#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, lists = [_|_] = Lists}} -> XLists = lists:map( fun({Name, Items}) -> XItems = lists:map( fun mod_privacy:item_to_xml/1, Items), #xmlel{name = <<"list">>, attrs = [{<<"name">>, Name}], children = XItems} end, Lists), DefaultEl = case Default of none -> []; _ -> [#xmlel{name = <<"default">>, attrs = [{<<"name">>, Default}]}] end, [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_PRIVACY}], children = DefaultEl ++ XLists}]; _ -> [] end. %% @spec (Dir::string(), Hosts::[string()]) -> ok get_roster(User, Server) -> JID = jid:make(User, Server, <<>>), case mod_roster:get_roster(User, Server) of [_|_] = Items -> Subs = lists:flatmap( fun(#roster{ask = Ask, askmessage = Msg} = R) when Ask == in; Ask == both -> Status = if is_binary(Msg) -> (Msg); true -> <<"">> end, [#xmlel{name = <<"presence">>, attrs = [{<<"from">>, jid:to_string(R#roster.jid)}, {<<"to">>, jid:to_string(JID)}, {<<"xmlns">>, <<"jabber:client">>}, {<<"type">>, <<"subscribe">>}], children = [#xmlel{name = <<"status">>, attrs = [], children = [{xmlcdata, Status}]}]}]; (_) -> [] end, Items), Rs = lists:flatmap( fun(#roster{ask = in, subscription = none}) -> []; (R) -> [mod_roster:item_to_xml(R)] end, Items), [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_ROSTER}], children = Rs} | Subs]; _ -> [] end. get_private(User, Server) -> case mod_private:get_data(User, Server) of [_|_] = Els -> [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_PRIVATE}], children = Els}]; _ -> [] end. process(#state{xml_stream_state = XMLStreamState, fd = Fd} = State) -> case file:read(Fd, ?CHUNK_SIZE) of {ok, Data} -> NewXMLStreamState = xml_stream:parse(XMLStreamState, Data), case process_els(State#state{xml_stream_state = NewXMLStreamState}) of {ok, NewState} -> process(NewState); Err -> xml_stream:close(NewXMLStreamState), Err end; eof -> xml_stream:close(XMLStreamState), ok end. process_els(State) -> receive {'$gen_event', El} -> case process_el(El, State) of {ok, NewState} -> process_els(NewState); Err -> Err end after 0 -> {ok, State} end. process_el({xmlstreamstart, <<"server-data">>, Attrs}, State) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_PIEFXIS -> {ok, State}; ?NS_PIE -> {ok, State}; NS -> stop("Unknown 'server-data' namespace = ~s", [NS]) end; process_el({xmlstreamend, _}, State) -> {ok, State}; process_el({xmlstreamcdata, _}, State) -> {ok, State}; process_el({xmlstreamelement, #xmlel{name = <<"xi:include">>, attrs = Attrs}}, #state{dir = Dir, user = <<"">>} = State) -> FileName = xml:get_attr_s(<<"href">>, Attrs), case import_file(filename:join([Dir, FileName]), State) of ok -> {ok, State}; Err -> Err end; process_el({xmlstreamstart, <<"host">>, Attrs}, State) -> process_el({xmlstreamelement, #xmlel{name = <<"host">>, attrs = Attrs}}, State); process_el({xmlstreamelement, #xmlel{name = <<"host">>, attrs = Attrs, children = Els}}, State) -> JIDS = xml:get_attr_s(<<"jid">>, Attrs), case jid:from_string(JIDS) of #jid{lserver = S} -> case lists:member(S, ?MYHOSTS) of true -> process_users(Els, State#state{server = S}); false -> stop("Unknown host: ~s", [S]) end; error -> stop("Invalid 'jid': ~s", [JIDS]) end; process_el({xmlstreamstart, <<"user">>, Attrs}, State = #state{server = S}) when S /= <<"">> -> process_el({xmlstreamelement, #xmlel{name = <<"user">>, attrs = Attrs}}, State); process_el({xmlstreamelement, #xmlel{name = <<"user">>} = El}, State = #state{server = S}) when S /= <<"">> -> process_user(El, State); process_el({xmlstreamelement, El}, State = #state{server = S, user = U}) when S /= <<"">>, U /= <<"">> -> process_user_el(El, State); process_el({xmlstreamelement, El}, _State) -> stop("Unexpected tag: ~p", [El]); process_el({xmlstreamstart, El, Attrs}, _State) -> stop("Unexpected payload: ~p", [{El, Attrs}]); process_el({xmlstreamerror, Err}, _State) -> stop("Failed to process element = ~p", [Err]). process_users([#xmlel{} = El|Els], State) -> case process_user(El, State) of {ok, NewState} -> process_users(Els, NewState); Err -> Err end; process_users([_|Els], State) -> process_users(Els, State); process_users([], State) -> {ok, 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), 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 jid:nodeprep(Name) of error -> stop("Invalid 'user': ~s", [Name]); LUser -> case ejabberd_auth:try_register(LUser, LServer, Pass) of {atomic, _} -> process_user_els(Els, State#state{user = LUser}); Err -> stop("Failed to create user '~s': ~p", [Name, Err]) end end. process_user_els([#xmlel{} = El|Els], State) -> case process_user_el(El, State) of {ok, NewState} -> process_user_els(Els, NewState); Err -> Err end; process_user_els([_|Els], State) -> process_user_els(Els, State); process_user_els([], State) -> {ok, State}. process_user_el(#xmlel{name = Name, attrs = Attrs, children = Els} = El, State) -> case {Name, xml:get_attr_s(<<"xmlns">>, Attrs)} of {<<"query">>, ?NS_ROSTER} -> process_roster(El, State); {<<"query">>, ?NS_PRIVACY} -> %% Make sure elements go before and NewEls = lists:reverse(lists:keysort(#xmlel.name, Els)), process_privacy_el(El#xmlel{children = NewEls}, State); {<<"query">>, ?NS_PRIVATE} -> process_private(El, State); {<<"vCard">>, ?NS_VCARD} -> process_vcard(El, State); {<<"offline-messages">>, _} -> process_offline_msgs(Els, State); {<<"presence">>, <<"jabber:client">>} -> process_presence(El, State); _ -> {ok, State} end. process_privacy_el(#xmlel{children = [#xmlel{} = SubEl|SubEls]} = El, State) -> case process_privacy(#xmlel{children = [SubEl]}, State) of {ok, NewState} -> process_privacy_el(El#xmlel{children = SubEls}, NewState); Err -> Err end; process_privacy_el(#xmlel{children = [_|SubEls]} = El, State) -> process_privacy_el(El#xmlel{children = SubEls}, State); process_privacy_el(#xmlel{children = []}, State) -> {ok, State}. process_offline_msgs([#xmlel{} = El|Els], State) -> case process_offline_msg(El, State) of {ok, NewState} -> process_offline_msgs(Els, NewState); Err -> Err end; process_offline_msgs([_|Els], State) -> process_offline_msgs(Els, State); process_offline_msgs([], State) -> {ok, State}. process_roster(El, State = #state{user = U, server = S}) -> case mod_roster:set_items(U, S, El) of {atomic, _} -> {ok, State}; Err -> 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( [], JID, JID, #iq{type = set, sub_el = El}) of {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. %% @spec (Dir::string()) -> ok process_private(El, State = #state{user = U, server = S}) -> JID = jid:make(U, S, <<"">>), case mod_private:process_sm_iq( JID, JID, #iq{type = set, sub_el = El}) of #iq{type = result} -> {ok, State}; Err -> 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( JID, JID, #iq{type = set, sub_el = El}) of #iq{type = result} -> {ok, State}; Err -> 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 = xml:get_attr_s(<<"from">>, El#xmlel.attrs), case jid:from_string(FromS) of #jid{} = From -> 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 -> stop("Failed to store offline message: ~p", [Err]); _ -> {ok, State} end; _ -> stop("Invalid 'from' = ~s", [FromS]) end. %% @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 jid:from_string(FromS) of #jid{} = From -> To = jid:make(U, S, <<>>), NewEl = jlib:replace_from_to(From, To, El), ejabberd_router:route(From, To, NewEl), {ok, State}; _ -> stop("Invalid 'from' = ~s", [FromS]) end. stop(Fmt, Args) -> ?ERROR_MSG(Fmt, Args), {error, import_failed}. make_filename_template() -> {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(), list_to_binary( io_lib:format("~4..0w~2..0w~2..0w-~2..0w~2..0w~2..0w", [Year, Month, Day, Hour, Minute, Second])). make_main_basefilename(Dir, FnT) -> Filename2 = <>, filename:join([Dir, Filename2]). %% @doc Make the filename for the host. %% Example: ``(<<"20080804-231550">>, <<"jabber.example.org">>) -> %% <<"20080804-231550_jabber_example_org.xml">>'' make_host_filename(FnT, Host) -> Host2 = str:join(str:tokens(Host, <<".">>), <<"_">>), <>. %%%================================== %%%% PIEFXIS formatting make_host_basefilename(Dir, FnT) -> filename:join([Dir, FnT]). %% @spec () -> string() make_piefxis_xml_head() -> "". %% @spec () -> string() make_piefxis_xml_tail() -> "". %% @spec () -> string() make_piefxis_server_head() -> io_lib:format("", [?NS_PIE, ?NS_XI]). %% @spec () -> string() make_piefxis_server_tail() -> "". %% @spec (Host::string()) -> string() make_piefxis_host_head(Host) -> io_lib:format("", [?NS_PIE, ?NS_XI, Host]). %% @spec () -> string() make_piefxis_host_tail() -> "". %% @spec (Fn::string()) -> string() make_xinclude(Fn) -> Base = filename:basename(Fn), io_lib:format("", [Base]). print(Fd, String) -> file:write(Fd, String). opt_type(auth_password_format) -> fun (X) -> X end; opt_type(_) -> [auth_password_format]. ejabberd-16.01/src/mod_service_log.erl0000644000232200023220000000717612645157216020304 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_service_log.erl %%% Author : Alexey Shchepin %%% Purpose : Copy user messages to logger service %%% Created : 24 Aug 2003 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(mod_service_log). -author('alexey@process-one.net'). -behaviour(gen_mod). -export([start/2, stop/1, log_user_send/4, log_user_receive/5, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). start(Host, _Opts) -> ejabberd_hooks:add(user_send_packet, Host, ?MODULE, log_user_send, 50), ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, log_user_receive, 50), ok. stop(Host) -> ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, log_user_send, 50), ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, log_user_receive, 50), ok. log_user_send(Packet, _C2SState, From, To) -> log_packet(From, To, Packet, From#jid.lserver), Packet. log_user_receive(Packet, _C2SState, _JID, From, To) -> log_packet(From, To, Packet, To#jid.lserver), Packet. log_packet(From, To, #xmlel{name = Name, attrs = Attrs, children = Els}, Host) -> Loggers = gen_mod:get_module_opt(Host, ?MODULE, loggers, fun(L) -> lists:map( fun(S) -> B = iolist_to_binary(S), N = jid:nameprep(B), if N /= error -> N end end, L) end, []), ServerJID = #jid{user = <<"">>, server = Host, resource = <<"">>, luser = <<"">>, lserver = Host, lresource = <<"">>}, NewAttrs = jlib:replace_from_to_attrs(jid:to_string(From), jid:to_string(To), Attrs), FixedPacket = #xmlel{name = Name, attrs = NewAttrs, children = Els}, lists:foreach(fun (Logger) -> ejabberd_router:route(ServerJID, #jid{user = <<"">>, server = Logger, resource = <<"">>, luser = <<"">>, lserver = Logger, lresource = <<"">>}, #xmlel{name = <<"route">>, attrs = [], children = [FixedPacket]}) end, Loggers). mod_opt_type(loggers) -> fun (L) -> lists:map(fun (S) -> B = iolist_to_binary(S), N = jid:nameprep(B), if N /= error -> N end end, L) end; mod_opt_type(_) -> [loggers]. ejabberd-16.01/src/mod_carboncopy.erl0000644000232200023220000002557512645157216020145 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_carboncopy.erl %%% Author : Eric Cestari %%% Purpose : Message Carbons XEP-0280 0.8 %%% Created : 5 May 2008 by Mickael Remond %%% Usage : Add the following line in modules section of ejabberd.yml: %%% {mod_carboncopy, []} %%% %%% %%% 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_carboncopy). -author ('ecestari@process-one.net'). -protocol({xep, 280, '0.8'}). -behavior(gen_mod). %% API: -export([start/2, stop/1]). -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]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -define(PROCNAME, ?MODULE). -define(TABLE, carboncopy). -type matchspec_atom() :: '_' | '$1' | '$2' | '$3'. -record(carboncopy,{us :: {binary(), binary()} | matchspec_atom(), resource :: binary() | matchspec_atom(), version :: binary() | matchspec_atom()}). is_carbon_copy(Packet) -> is_carbon_copy(Packet, <<"sent">>) orelse is_carbon_copy(Packet, <<"received">>). is_carbon_copy(Packet, Direction) -> case xml:get_subtag(Packet, Direction) of #xmlel{name = Direction, attrs = Attrs} -> case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_CARBONS_2 -> true; ?NS_CARBONS_1 -> true; _ -> false end; _ -> false end. start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts,fun gen_iq_handler:check_type/1, one_queue), mod_disco:register_feature(Host, ?NS_CARBONS_1), mod_disco:register_feature(Host, ?NS_CARBONS_2), Fields = record_info(fields, ?TABLE), try mnesia:table_info(?TABLE, attributes) of Fields -> ok; _ -> mnesia:delete_table(?TABLE) %% recreate.. catch _:_Error -> ok %%probably table don't exist end, mnesia:create_table(?TABLE, [{ram_copies, [node()]}, {attributes, record_info(fields, ?TABLE)}, {type, bag}]), mnesia:add_table_copy(?TABLE, node(), ram_copies), ejabberd_hooks:add(unset_presence_hook,Host, ?MODULE, remove_connection, 10), %% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90) ejabberd_hooks:add(user_send_packet,Host, ?MODULE, user_send_packet, 89), ejabberd_hooks:add(user_receive_packet,Host, ?MODULE, user_receive_packet, 89), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2, ?MODULE, iq_handler2, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_1, ?MODULE, iq_handler1, IQDisc). stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_1), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2), mod_disco:unregister_feature(Host, ?NS_CARBONS_2), mod_disco:unregister_feature(Host, ?NS_CARBONS_1), %% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90) ejabberd_hooks:delete(user_send_packet,Host, ?MODULE, user_send_packet, 89), ejabberd_hooks:delete(user_receive_packet,Host, ?MODULE, user_receive_packet, 89), ejabberd_hooks:delete(unset_presence_hook,Host, ?MODULE, remove_connection, 10). iq_handler2(From, To, IQ) -> iq_handler(From, To, IQ, ?NS_CARBONS_2). iq_handler1(From, To, IQ) -> iq_handler(From, To, IQ, ?NS_CARBONS_1). iq_handler(From, _To, #iq{type=set, sub_el = #xmlel{name = Operation, children = []}} = IQ, CC)-> ?DEBUG("carbons IQ received: ~p", [IQ]), {U, S, R} = jid:tolower(From), Result = case Operation of <<"enable">>-> ?INFO_MSG("carbons enabled for user ~s@~s/~s", [U,S,R]), enable(S,U,R,CC); <<"disable">>-> ?INFO_MSG("carbons disabled for user ~s@~s/~s", [U,S,R]), disable(S, U, R) end, case Result of ok -> ?DEBUG("carbons IQ result: ok", []), IQ#iq{type=result, sub_el=[]}; {error,_Error} -> ?WARNING_MSG("Error enabling / disabling carbons: ~p", [Result]), IQ#iq{type=error,sub_el = [?ERR_BAD_REQUEST]} end; iq_handler(_From, _To, IQ, _CC)-> IQ#iq{type=error, sub_el = [?ERR_NOT_ALLOWED]}. user_send_packet(Packet, _C2SState, From, To) -> check_and_forward(From, To, Packet, sent). user_receive_packet(Packet, _C2SState, JID, _From, To) -> check_and_forward(JID, To, Packet, received). % 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 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 true -> case is_carbon_copy(Packet) of false -> send_copies(JID, To, Packet, Direction), Packet; true -> %% stop the hook chain, we don't want logging modules to duplicates %% this message {stop, Packet} end; _ -> Packet end. remove_connection(User, Server, Resource, _Status)-> disable(Server, User, Resource), ok. %%% Internal %% Direction = received | sent send_copies(JID, To, Packet, Direction)-> {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 {Prio, Res} -> {Prio, Res}; _ -> {0, undefined} end, %% unavailable resources are handled like bare JIDs IsBareTo = case {Direction, To} of {received, #jid{lresource = <<>>}} -> true; {received, #jid{lresource = LRes}} -> not lists:member(LRes, AvailRs); _ -> false end, %% list of JIDs that should receive a carbon copy of this message (excluding the %% receiver(s) of the original message TargetJIDs = case {IsBareTo, R} of {true, MaxRes} -> OrigTo = fun(Res) -> lists:member({MaxPrio, Res}, PrioRes) end, [ {jid:make({U, S, CCRes}), CC_Version} || {CCRes, CC_Version} <- list(U, S), lists:member(CCRes, AvailRs), not OrigTo(CCRes) ]; {true, _} -> %% 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 create carbon %% copies only from one of those resources (the one where R equals %% MaxRes) in order to avoid duplicates. []; {false, _} -> [ {jid:make({U, S, CCRes}), CC_Version} || {CCRes, CC_Version} <- list(U, S), lists:member(CCRes, AvailRs), CCRes /= R ] %TargetJIDs = lists:delete(JID, [ jid:make({U, S, CCRes}) || CCRes <- list(U, S) ]), end, lists:map(fun({Dest,Version}) -> {_, _, Resource} = jid:tolower(Dest), ?DEBUG("Sending: ~p =/= ~p", [R, Resource]), 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) end, TargetJIDs), ok. build_forward_packet(JID, Packet, Sender, Dest, Direction, ?NS_CARBONS_2) -> #xmlel{name = <<"message">>, attrs = [{<<"xmlns">>, <<"jabber:client">>}, {<<"type">>, message_type(Packet)}, {<<"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}], children = [ #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">>, attrs = [{<<"xmlns">>, <<"jabber:client">>}, {<<"type">>, message_type(Packet)}, {<<"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}]}, #xmlel{name = <<"forwarded">>, attrs = [{<<"xmlns">>, ?NS_FORWARD}], children = [complete_packet(JID, Packet, Direction)]} ]}. enable(Host, U, R, CC)-> ?DEBUG("enabling for ~p", [U]), try mnesia:dirty_write(#carboncopy{us = {U, Host}, resource=R, version = CC}) of ok -> ok catch _:Error -> {error, Error} end. disable(Host, U, R)-> ?DEBUG("disabling for ~p", [U]), ToDelete = mnesia:dirty_match_object(?TABLE, #carboncopy{us = {U, Host}, resource = R, version = '_'}), try lists:foreach(fun mnesia:dirty_delete_object/1, ToDelete) of ok -> ok catch _:Error -> {error, Error} end. complete_packet(From, #xmlel{name = <<"message">>, attrs = OrigAttrs} = Packet, sent) -> %% if this is a packet sent by user on this host, then Packet doesn't %% include the 'from' attribute. We must add it. Attrs = lists:keystore(<<"xmlns">>, 1, OrigAttrs, {<<"xmlns">>, <<"jabber:client">>}), case proplists:get_value(<<"from">>, Attrs) of undefined -> Packet#xmlel{attrs = [{<<"from">>, jid:to_string(From)}|Attrs]}; _ -> Packet#xmlel{attrs = Attrs} end; complete_packet(_From, #xmlel{name = <<"message">>, attrs=OrigAttrs} = Packet, received) -> Attrs = lists:keystore(<<"xmlns">>, 1, OrigAttrs, {<<"xmlns">>, <<"jabber:client">>}), Packet#xmlel{attrs = Attrs}. message_type(#xmlel{attrs = Attrs}) -> case xml:get_attr(<<"type">>, Attrs) of {value, Type} -> Type; false -> <<"normal">> end. is_chat_message(#xmlel{name = <<"message">>} = Packet) -> case message_type(Packet) of <<"chat">> -> true; <<"normal">> -> has_non_empty_body(Packet); _ -> false end; 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) -> 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]. ejabberd-16.01/src/gen_mod.erl0000644000232200023220000002417012645157216016545 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : gen_mod.erl %%% Author : Alexey Shchepin %%% Purpose : %%% Created : 24 Jan 2003 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(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/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]). -include("ejabberd.hrl"). -include("logger.hrl"). -record(ejabberd_module, {module_host = {undefined, <<"">>} :: {atom(), binary()}, 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. start() -> ets:new(ejabberd_modules, [named_table, public, {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) -> Modules = ejabberd_config:get_option( {modules, Host}, fun(L) when is_list(L) -> L end, []), case lists:keyfind(Module, 1, Modules) of {_, Opts} -> start_module(Host, Module, Opts); false -> {error, not_found_in_config} end. -spec start_module(binary(), atom(), opts()) -> any(). start_module(Host, Module, Opts0) -> Opts = validate_opts(Module, Opts0), ets:insert(ejabberd_modules, #ejabberd_module{module_host = {Module, Host}, opts = Opts}), try Module:start(Host, Opts) catch Class:Reason -> ets:delete(ejabberd_modules, {Module, Host}), ErrorText = io_lib:format("Problem starting the module ~p for host " "~p ~n options: ~p~n ~p: ~p~n~p", [Module, Host, Opts, Class, Reason, erlang:get_stacktrace()]), ?CRITICAL_MSG(ErrorText, []), case is_app_running(ejabberd) of true -> erlang:raise(Class, Reason, erlang:get_stacktrace()); false -> ?CRITICAL_MSG("ejabberd initialization was aborted " "because a module start failed.", []), timer:sleep(3000), erlang:halt(string:substr(lists:flatten(ErrorText), 1, 199)) end end. is_app_running(AppName) -> Timeout = 15000, lists:keymember(AppName, 1, application:which_applications(Timeout)). -spec stop_module(binary(), atom()) -> error | {aborted, any()} | {atomic, any()}. stop_module(Host, Module) -> case stop_module_keep_config(Host, Module) of error -> error; ok -> ok end. -spec stop_module_keep_config(binary(), atom()) -> error | ok. stop_module_keep_config(Host, Module) -> case catch Module:stop(Host) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), error; {wait, ProcList} when is_list(ProcList) -> lists:foreach(fun wait_for_process/1, ProcList), ets:delete(ejabberd_modules, {Module, Host}), ok; {wait, Process} -> wait_for_process(Process), ets:delete(ejabberd_modules, {Module, Host}), ok; _ -> ets:delete(ejabberd_modules, {Module, Host}), ok end. wait_for_process(Process) -> MonitorReference = erlang:monitor(process, Process), wait_for_stop(Process, MonitorReference). wait_for_stop(Process, MonitorReference) -> receive {'DOWN', MonitorReference, _Type, _Object, _Info} -> ok after 5000 -> catch exit(whereis(Process), kill), wait_for_stop1(MonitorReference) end. wait_for_stop1(MonitorReference) -> receive {'DOWN', MonitorReference, _Type, _Object, _Info} -> ok after 5000 -> ok end. -type check_fun() :: fun((any()) -> any()) | {module(), atom()}. -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() | {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 -> Default; {value, {_, Val}} -> 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) -> Hosts = (?MYHOSTS), [Value | Values] = lists:map(fun (Host) -> get_module_opt(Host, Module, Opt, F, Default) end, Hosts), Same_all = lists:all(fun (Other_value) -> Other_value == Value end, Values), case Same_all of true -> Value; false -> Default end; get_module_opt(Host, Module, Opt, F, Default) -> OptsList = ets:lookup(ejabberd_modules, {Module, Host}), case OptsList of [] -> Default; [#ejabberd_module{opts = Opts} | _] -> get_opt(Opt, Opts, F, Default) end. -spec get_module_opt_host(global | binary(), atom(), binary()) -> binary(). get_module_opt_host(Host, Module, Default) -> Val = get_module_opt(Host, Module, host, fun iolist_to_binary/1, Default), ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host). -spec get_opt_host(binary(), opts(), binary()) -> binary(). get_opt_host(Host, Opts, Default) -> Val = get_opt(host, Opts, fun iolist_to_binary/1, Default), ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host). 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("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]), 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()) -> db_type(). db_type(Opts) -> db_type(global, Opts). -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) -> db_type(). default_db(Host) -> ejabberd_config:get_option({default_db, Host}, fun v_db/1, mnesia). -spec loaded_modules(binary()) -> [atom()]. loaded_modules(Host) -> ets:select(ejabberd_modules, [{#ejabberd_module{_ = '_', module_host = {'$1', Host}}, [], ['$1']}]). -spec loaded_modules_with_opts(binary()) -> [{atom(), opts()}]. loaded_modules_with_opts(Host) -> ets:select(ejabberd_modules, [{#ejabberd_module{_ = '_', module_host = {'$1', Host}, opts = '$2'}, [], [{{'$1', '$2'}}]}]). -spec get_hosts(opts(), binary()) -> [binary()]. get_hosts(Opts, Prefix) -> case get_opt(hosts, Opts, fun(Hs) -> [iolist_to_binary(H) || H <- Hs] end) of undefined -> case get_opt(host, Opts, fun iolist_to_binary/1) of undefined -> [<> || Host <- ?MYHOSTS]; Host -> [Host] end; Hosts -> Hosts end. -spec get_module_proc(binary(), {frontend, atom()} | atom()) -> atom(). get_module_proc(Host, {frontend, Base}) -> get_module_proc(<<"frontend_", Host/binary>>, Base); get_module_proc(Host, Base) -> binary_to_atom( <<(erlang:atom_to_binary(Base, latin1))/binary, "_", Host/binary>>, latin1). -spec is_loaded(binary(), atom()) -> boolean(). 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]. ejabberd-16.01/src/ejabberd_web_admin.erl0000644000232200023220000040522112645157216020700 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_web_admin.erl %%% Author : Alexey Shchepin %%% Purpose : Administration web interface %%% Created : 9 Apr 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. %%% %%%---------------------------------------------------------------------- %%%% definitions -module(ejabberd_web_admin). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -export([process/2, list_users/4, list_users_in_diapason/4, pretty_print_xml/1, term_to_id/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("ejabberd_http.hrl"). -include("ejabberd_web_admin.hrl"). -define(INPUTATTRS(Type, Name, Value, Attrs), ?XA(<<"input">>, (Attrs ++ [{<<"type">>, Type}, {<<"name">>, Name}, {<<"value">>, Value}]))). %%%================================== %%%% get_acl_access %% @spec (Path::[string()], Method) -> {HostOfRule, [AccessRule]} %% where Method = 'GET' | 'POST' %% All accounts can access those URLs get_acl_rule([], _) -> {<<"localhost">>, [all]}; get_acl_rule([<<"style.css">>], _) -> {<<"localhost">>, [all]}; get_acl_rule([<<"logo.png">>], _) -> {<<"localhost">>, [all]}; get_acl_rule([<<"logo-fill.png">>], _) -> {<<"localhost">>, [all]}; get_acl_rule([<<"favicon.ico">>], _) -> {<<"localhost">>, [all]}; get_acl_rule([<<"additions.js">>], _) -> {<<"localhost">>, [all]}; %% This page only displays vhosts that the user is admin: get_acl_rule([<<"vhosts">>], _) -> {<<"localhost">>, [all]}; %% The pages of a vhost are only accesible if the user is admin of that vhost: get_acl_rule([<<"server">>, VHost | _RPath], Method) when Method =:= 'GET' orelse Method =:= 'HEAD' -> {VHost, [configure, webadmin_view]}; get_acl_rule([<<"server">>, VHost | _RPath], 'POST') -> {VHost, [configure]}; %% Default rule: only global admins can access any other random page get_acl_rule(_RPath, Method) when Method =:= 'GET' orelse Method =:= 'HEAD' -> {global, [configure, webadmin_view]}; get_acl_rule(_RPath, 'POST') -> {global, [configure]}. is_acl_match(Host, Rules, Jid) -> lists:any(fun (Rule) -> allow == acl:match_rule(Host, Rule, Jid) end, Rules). %%%================================== %%%% Menu Items Access get_jid(Auth, HostHTTP, Method) -> case get_auth_admin(Auth, HostHTTP, [], Method) of {ok, {User, Server}} -> jid:make(User, Server, <<"">>); {unauthorized, Error} -> ?ERROR_MSG("Unauthorized ~p: ~p", [Auth, Error]), throw({unauthorized, Auth}) end. get_menu_items(global, cluster, Lang, JID) -> {Base, _, Items} = make_server_menu([], [], Lang, JID), lists:map(fun ({URI, Name}) -> {<>, Name}; ({URI, Name, _SubMenu}) -> {<>, Name} end, Items); get_menu_items(Host, cluster, Lang, JID) -> {Base, _, Items} = make_host_menu(Host, [], Lang, JID), lists:map(fun ({URI, Name}) -> {<>, Name}; ({URI, Name, _SubMenu}) -> {<>, Name} end, Items). %% get_menu_items(Host, Node, Lang, JID) -> %% {Base, _, Items} = make_host_node_menu(Host, Node, Lang, JID), %% lists:map( %% fun({URI, Name}) -> %% {Base++URI++"/", Name}; %% ({URI, Name, _SubMenu}) -> %% {Base++URI++"/", Name} %% end, %% Items %% ). is_allowed_path(BasePath, {Path, _}, JID) -> is_allowed_path(BasePath ++ [Path], JID); is_allowed_path(BasePath, {Path, _, _}, JID) -> is_allowed_path(BasePath ++ [Path], JID). is_allowed_path([<<"admin">> | Path], JID) -> is_allowed_path(Path, JID); is_allowed_path(Path, JID) -> {HostOfRule, AccessRule} = get_acl_rule(Path, 'GET'), is_acl_match(HostOfRule, AccessRule, JID). %% @spec(Path) -> URL %% where Path = [string()] %% URL = string() %% Convert ["admin", "user", "tom"] -> "/admin/user/tom/" %%path_to_url(Path) -> %% "/" ++ string:join(Path, "/") ++ "/". %% @spec(URL) -> Path %% where Path = [string()] %% URL = string() %% Convert "admin/user/tom" -> ["admin", "user", "tom"] url_to_path(URL) -> str:tokens(URL, <<"/">>). %%%================================== %%%% process/2 process([<<"doc">>, LocalFile], _Request) -> DocPath = case os:getenv("EJABBERD_DOC_PATH") of P when is_list(P) -> P; false -> <<"/share/doc/ejabberd/">> end, FileName = filename:join(DocPath, LocalFile), case file:read_file(FileName) of {ok, FileContents} -> ?DEBUG("Delivering content.", []), {200, [{<<"Server">>, <<"ejabberd">>}], FileContents}; {error, 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 -> {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 end; process([<<"server">>, SHost | RPath] = Path, #request{auth = Auth, lang = Lang, host = HostHTTP, method = Method} = Request) -> Host = jid:nameprep(SHost), case lists:member(Host, ?MYHOSTS) of true -> case get_auth_admin(Auth, HostHTTP, Path, Method) of {ok, {User, Server}} -> AJID = get_jid(Auth, HostHTTP, Method), process_admin(Host, Request#request{path = RPath, auth = {auth_jid, Auth, AJID}, us = {User, Server}}); {unauthorized, <<"no-auth-provided">>} -> {401, [{<<"WWW-Authenticate">>, <<"basic realm=\"ejabberd\"">>}], ejabberd_web:make_xhtml([?XCT(<<"h1">>, <<"Unauthorized">>)])}; {unauthorized, Error} -> {BadUser, _BadPass} = Auth, {IPT, _Port} = Request#request.ip, 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, [{<<"WWW-Authenticate">>, <<"basic realm=\"auth error, retry login " "to ejabberd\"">>}], ejabberd_web:make_xhtml([?XCT(<<"h1">>, <<"Unauthorized">>)])} end; false -> ejabberd_web:error(not_found) end; process(RPath, #request{auth = Auth, lang = Lang, host = HostHTTP, method = Method} = Request) -> case get_auth_admin(Auth, HostHTTP, RPath, Method) of {ok, {User, Server}} -> AJID = get_jid(Auth, HostHTTP, Method), process_admin(global, Request#request{path = RPath, auth = {auth_jid, Auth, AJID}, us = {User, Server}}); {unauthorized, <<"no-auth-provided">>} -> {401, [{<<"WWW-Authenticate">>, <<"basic realm=\"ejabberd\"">>}], ejabberd_web:make_xhtml([?XCT(<<"h1">>, <<"Unauthorized">>)])}; {unauthorized, Error} -> {BadUser, _BadPass} = Auth, {IPT, _Port} = Request#request.ip, 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, [{<<"WWW-Authenticate">>, <<"basic realm=\"auth error, retry login " "to ejabberd\"">>}], ejabberd_web:make_xhtml([?XCT(<<"h1">>, <<"Unauthorized">>)])} end. get_auth_admin(Auth, HostHTTP, RPath, Method) -> case Auth of {SJID, Pass} -> {HostOfRule, AccessRule} = get_acl_rule(RPath, Method), case jid:from_string(SJID) of error -> {unauthorized, <<"badformed-jid">>}; #jid{user = <<"">>, server = User} -> get_auth_account(HostOfRule, AccessRule, User, HostHTTP, Pass); #jid{user = User, server = Server} -> get_auth_account(HostOfRule, AccessRule, User, Server, Pass) end; undefined -> {unauthorized, <<"no-auth-provided">>} end. get_auth_account(HostOfRule, AccessRule, User, Server, Pass) -> case ejabberd_auth:check_password(User, Server, Pass) of true -> case is_acl_match(HostOfRule, AccessRule, jid:make(User, Server, <<"">>)) of false -> {unauthorized, <<"unprivileged-account">>}; true -> {ok, {User, Server}} end; false -> case ejabberd_auth:is_user_exists(User, Server) of true -> {unauthorized, <<"bad-password">>}; false -> {unauthorized, <<"inexistent-account">>} end end. %%%================================== %%%% make_xhtml make_xhtml(Els, Host, Lang, JID) -> make_xhtml(Els, Host, cluster, Lang, JID). %% @spec (Els, Host, Node, Lang, JID) -> {200, [html], xmlelement()} %% where Host = global | string() %% Node = cluster | atom() %% JID = jid() make_xhtml(Els, Host, Node, Lang, JID) -> Base = get_base_path(Host, cluster), MenuItems = make_navigation(Host, Node, Lang, JID), {200, [html], #xmlel{name = <<"html">>, attrs = [{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>}, {<<"xml:lang">>, Lang}, {<<"lang">>, Lang}]++direction(Lang), children = [#xmlel{name = <<"head">>, attrs = [], children = [?XCT(<<"title">>, <<"ejabberd Web Admin">>), #xmlel{name = <<"meta">>, attrs = [{<<"http-equiv">>, <<"Content-Type">>}, {<<"content">>, <<"text/html; charset=utf-8">>}], children = []}, #xmlel{name = <<"script">>, attrs = [{<<"src">>, <>}, {<<"type">>, <<"text/javascript">>}], children = [?C(<<" ">>)]}, #xmlel{name = <<"link">>, attrs = [{<<"href">>, <>}, {<<"type">>, <<"image/x-icon">>}, {<<"rel">>, <<"shortcut icon">>}], children = []}, #xmlel{name = <<"link">>, attrs = [{<<"href">>, <>}, {<<"type">>, <<"text/css">>}, {<<"rel">>, <<"stylesheet">>}], children = []}]}, ?XE(<<"body">>, [?XAE(<<"div">>, [{<<"id">>, <<"container">>}], [?XAE(<<"div">>, [{<<"id">>, <<"header">>}], [?XE(<<"h1">>, [?ACT(<<"/admin/">>, <<"ejabberd Web Admin">>)])]), ?XAE(<<"div">>, [{<<"id">>, <<"navigation">>}], [?XE(<<"ul">>, MenuItems)]), ?XAE(<<"div">>, [{<<"id">>, <<"content">>}], Els), ?XAE(<<"div">>, [{<<"id">>, <<"clearcopyright">>}], [{xmlcdata, <<"">>}])]), ?XAE(<<"div">>, [{<<"id">>, <<"copyrightouter">>}], [?XAE(<<"div">>, [{<<"id">>, <<"copyright">>}], [?XE(<<"p">>, [?AC(<<"https://www.ejabberd.im/">>, <<"ejabberd">>), ?C(<<" (c) 2002-2015 ">>), ?AC(<<"https://www.process-one.net/">>, <<"ProcessOne, leader in messaging and push solutions">>)] )])])])]}}. direction(ltr) -> [{<<"dir">>, <<"ltr">>}]; direction(<<"he">>) -> [{<<"dir">>, <<"rtl">>}]; direction(_) -> []. get_base_path(global, cluster) -> <<"/admin/">>; get_base_path(Host, cluster) -> <<"/admin/server/", Host/binary, "/">>; get_base_path(global, Node) -> <<"/admin/node/", (iolist_to_binary(atom_to_list(Node)))/binary, "/">>; get_base_path(Host, Node) -> <<"/admin/server/", Host/binary, "/node/", (iolist_to_binary(atom_to_list(Node)))/binary, "/">>. %%%================================== %%%% css & images additions_js() -> <<"\nfunction selectAll() {\n for(i=0;i>. css(Host) -> Base = get_base_path(Host, cluster), <<"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(<<"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(<<"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" "AAAAXNSR0IArs4c6QAAAB5QTFRF1nYO/ooC/o4O/pIS/p" "4q/q5K/rpq/sqM/tam/ubGzn/S/AAAAEFJREFUCNdlw0s" "RwCAQBUE+gSRHLGABC1jAAhbWAhZwC+88XdXOXb4UlFAr" "SmwN5ekdJY2BkudEec1QvrVQ/r3xOlK9HsTvertmAAAAA" "ElFTkSuQmCC">>). %%%================================== %%%% process_admin process_admin(global, #request{path = [], auth = {_, _, AJID}, lang = Lang}) -> make_xhtml((?H1GL((?T(<<"Administration">>)), <<"">>, <<"Contents">>)) ++ [?XE(<<"ul">>, [?LI([?ACT(MIU, MIN)]) || {MIU, MIN} <- get_menu_items(global, cluster, Lang, AJID)])], global, Lang, AJID); process_admin(Host, #request{path = [], auth = {_, _Auth, AJID}, lang = Lang}) -> make_xhtml([?XCT(<<"h1">>, <<"Administration">>), ?XE(<<"ul">>, [?LI([?ACT(MIU, MIN)]) || {MIU, MIN} <- get_menu_items(Host, cluster, Lang, AJID)])], Host, Lang, AJID); process_admin(Host, #request{path = [<<"style.css">>]}) -> {200, [{<<"Content-Type">>, <<"text/css">>}, last_modified(), cache_control_public()], css(Host)}; process_admin(_Host, #request{path = [<<"favicon.ico">>]}) -> {200, [{<<"Content-Type">>, <<"image/x-icon">>}, last_modified(), cache_control_public()], favicon()}; process_admin(_Host, #request{path = [<<"logo.png">>]}) -> {200, [{<<"Content-Type">>, <<"image/png">>}, last_modified(), cache_control_public()], logo()}; process_admin(_Host, #request{path = [<<"logo-fill.png">>]}) -> {200, [{<<"Content-Type">>, <<"image/png">>}, last_modified(), cache_control_public()], logo_fill()}; process_admin(_Host, #request{path = [<<"additions.js">>]}) -> {200, [{<<"Content-Type">>, <<"text/javascript">>}, last_modified(), cache_control_public()], additions_js()}; process_admin(Host, #request{path = [<<"acls-raw">>], q = Query, auth = {_, _Auth, AJID}, lang = Lang}) -> Res = case lists:keysearch(<<"acls">>, 1, Query) of {value, {_, String}} -> case erl_scan:string(binary_to_list(String)) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens) of {ok, NewACLs} -> acl:add_list(Host, NewACLs, true); _ -> error end; _ -> error end; _ -> nothing end, ACLs = lists:keysort(2, ets:select(acl, [{{acl, {'$1', Host}, '$2'}, [], [{{acl, '$1', '$2'}}]}])), {NumLines, ACLsP} = term_to_paragraph(ACLs, 80), make_xhtml((?H1GL((?T(<<"Access Control Lists">>)), <<"acl-definition">>, <<"ACL Definition">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr), [?TEXTAREA(<<"acls">>, (iolist_to_binary(integer_to_list(lists:max([16, NumLines])))), <<"80">>, <<(iolist_to_binary(ACLsP))/binary, ".">>), ?BR, ?INPUTT(<<"submit">>, <<"submit">>, <<"Submit">>)])], Host, Lang, AJID); process_admin(Host, #request{method = Method, path = [<<"acls">>], auth = {_, _Auth, AJID}, q = Query, lang = Lang}) -> ?DEBUG("query: ~p", [Query]), Res = case Method of 'POST' -> case catch acl_parse_query(Host, Query) of {'EXIT', _} -> error; NewACLs -> ?INFO_MSG("NewACLs at ~s: ~p", [Host, NewACLs]), acl:add_list(Host, NewACLs, true) end; _ -> nothing end, ACLs = lists:keysort(2, ets:select(acl, [{{acl, {'$1', Host}, '$2'}, [], [{{acl, '$1', '$2'}}]}])), make_xhtml((?H1GL((?T(<<"Access Control Lists">>)), <<"acl-definition">>, <<"ACL Definition">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"p">>, direction(ltr), [?ACT(<<"../acls-raw/">>, <<"Raw">>)])] ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr), [acls_to_xhtml(ACLs), ?BR, ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>), ?C(<<" ">>), ?INPUTT(<<"submit">>, <<"submit">>, <<"Submit">>)])], Host, Lang, AJID); process_admin(Host, #request{path = [<<"access-raw">>], auth = {_, _Auth, AJID}, q = Query, lang = Lang}) -> SetAccess = fun (Rs) -> mnesia:transaction(fun () -> Os = mnesia:select(access, [{{access, {'$1', Host}, '$2'}, [], ['$_']}]), lists:foreach(fun (O) -> mnesia:delete_object(O) end, Os), lists:foreach(fun ({access, Name, Rules}) -> mnesia:write({access, {Name, Host}, Rules}) end, Rs) end) end, Res = case lists:keysearch(<<"access">>, 1, Query) of {value, {_, String}} -> case erl_scan:string(binary_to_list(String)) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens) of {ok, Rs} -> case SetAccess(Rs) of {atomic, _} -> ok; _ -> error end; _ -> error end; _ -> error end; _ -> nothing end, Access = ets:select(access, [{{access, {'$1', Host}, '$2'}, [], [{{access, '$1', '$2'}}]}]), {NumLines, AccessP} = term_to_paragraph(lists:keysort(2,Access), 80), make_xhtml((?H1GL((?T(<<"Access Rules">>)), <<"access-rights">>, <<"Access Rights">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr), [?TEXTAREA(<<"access">>, (iolist_to_binary(integer_to_list(lists:max([16, NumLines])))), <<"80">>, <<(iolist_to_binary(AccessP))/binary, ".">>), ?BR, ?INPUTT(<<"submit">>, <<"submit">>, <<"Submit">>)])], Host, Lang, AJID); process_admin(Host, #request{method = Method, path = [<<"access">>], q = Query, auth = {_, _Auth, AJID}, lang = Lang}) -> ?DEBUG("query: ~p", [Query]), Res = case Method of 'POST' -> case catch access_parse_query(Host, Query) of {'EXIT', _} -> error; ok -> ok end; _ -> nothing end, AccessRules = ets:select(access, [{{access, {'$1', Host}, '$2'}, [], [{{access, '$1', '$2'}}]}]), make_xhtml((?H1GL((?T(<<"Access Rules">>)), <<"access-rights">>, <<"Access Rights">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"p">>, direction(ltr), [?ACT(<<"../access-raw/">>, <<"Raw">>)])] ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr), [access_rules_to_xhtml(AccessRules, Lang), ?BR, ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>)])], Host, Lang, AJID); process_admin(Host, #request{path = [<<"access">>, SName], q = Query, auth = {_, _Auth, AJID}, lang = Lang}) -> ?DEBUG("query: ~p", [Query]), Name = jlib:binary_to_atom(SName), Res = case lists:keysearch(<<"rules">>, 1, Query) of {value, {_, String}} -> case parse_access_rule(String) of {ok, Rs} -> ejabberd_config:add_option({access, Name, Host}, Rs), ok; _ -> error end; _ -> nothing end, Rules = case ejabberd_config:get_option( {access, Name, Host}, fun(V) -> V end) of undefined -> []; Rs1 -> Rs1 end, make_xhtml([?XC(<<"h1">>, list_to_binary(io_lib:format( ?T(<<"~s access rule configuration">>), [SName])))] ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [access_rule_to_xhtml(Rules), ?BR, ?INPUTT(<<"submit">>, <<"submit">>, <<"Submit">>)])], Host, Lang, AJID); process_admin(global, #request{path = [<<"vhosts">>], auth = {_, _Auth, AJID}, lang = Lang}) -> Res = list_vhosts(Lang, AJID), make_xhtml((?H1GL((?T(<<"Virtual Hosts">>)), <<"virtual-hosting">>, <<"Virtual Hosting">>)) ++ Res, global, Lang, AJID); process_admin(Host, #request{path = [<<"users">>], q = Query, auth = {_, _Auth, AJID}, lang = Lang}) when is_binary(Host) -> Res = list_users(Host, Query, Lang, fun url_func/1), make_xhtml([?XCT(<<"h1">>, <<"Users">>)] ++ Res, Host, Lang, AJID); process_admin(Host, #request{path = [<<"users">>, Diap], auth = {_, _Auth, AJID}, lang = Lang}) when is_binary(Host) -> Res = list_users_in_diapason(Host, Diap, Lang, fun url_func/1), make_xhtml([?XCT(<<"h1">>, <<"Users">>)] ++ Res, Host, Lang, AJID); process_admin(Host, #request{path = [<<"online-users">>], auth = {_, _Auth, AJID}, lang = Lang}) when is_binary(Host) -> Res = list_online_users(Host, Lang), make_xhtml([?XCT(<<"h1">>, <<"Online Users">>)] ++ Res, Host, Lang, AJID); process_admin(Host, #request{path = [<<"last-activity">>], auth = {_, _Auth, AJID}, q = Query, lang = Lang}) when is_binary(Host) -> ?DEBUG("query: ~p", [Query]), Month = case lists:keysearch(<<"period">>, 1, Query) of {value, {_, Val}} -> Val; _ -> <<"month">> end, Res = case lists:keysearch(<<"ordinary">>, 1, Query) of {value, {_, _}} -> list_last_activity(Host, Lang, false, Month); _ -> list_last_activity(Host, Lang, true, Month) end, make_xhtml([?XCT(<<"h1">>, <<"Users Last Activity">>)] ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?CT(<<"Period: ">>), ?XAE(<<"select">>, [{<<"name">>, <<"period">>}], (lists:map(fun ({O, V}) -> Sel = if O == Month -> [{<<"selected">>, <<"selected">>}]; true -> [] end, ?XAC(<<"option">>, (Sel ++ [{<<"value">>, O}]), V) end, [{<<"month">>, ?T(<<"Last month">>)}, {<<"year">>, ?T(<<"Last year">>)}, {<<"all">>, ?T(<<"All activity">>)}]))), ?C(<<" ">>), ?INPUTT(<<"submit">>, <<"ordinary">>, <<"Show Ordinary Table">>), ?C(<<" ">>), ?INPUTT(<<"submit">>, <<"integral">>, <<"Show Integral Table">>)])] ++ Res, Host, Lang, AJID); process_admin(Host, #request{path = [<<"stats">>], auth = {_, _Auth, AJID}, lang = Lang}) -> Res = get_stats(Host, Lang), make_xhtml([?XCT(<<"h1">>, <<"Statistics">>)] ++ Res, Host, Lang, AJID); process_admin(Host, #request{path = [<<"user">>, U], auth = {_, _Auth, AJID}, q = Query, lang = Lang}) -> case ejabberd_auth:is_user_exists(U, Host) of true -> Res = user_info(U, Host, Query, Lang), make_xhtml(Res, Host, Lang, AJID); false -> make_xhtml([?XCT(<<"h1">>, <<"Not Found">>)], Host, Lang, AJID) end; process_admin(Host, #request{path = [<<"nodes">>], auth = {_, _Auth, AJID}, lang = Lang}) -> Res = get_nodes(Lang), make_xhtml(Res, Host, Lang, AJID); process_admin(Host, #request{path = [<<"node">>, SNode | NPath], auth = {_, _Auth, AJID}, q = Query, lang = Lang}) -> case search_running_node(SNode) of false -> make_xhtml([?XCT(<<"h1">>, <<"Node not found">>)], Host, Lang, AJID); Node -> Res = get_node(Host, Node, NPath, Query, Lang), make_xhtml(Res, Host, Node, Lang, AJID) end; %%%================================== %%%% process_admin default case process_admin(Host, #request{lang = Lang, auth = {_, _Auth, AJID}} = Request) -> {Hook, Opts} = case Host of global -> {webadmin_page_main, [Request]}; Host -> {webadmin_page_host, [Host, Request]} end, case ejabberd_hooks:run_fold(Hook, Host, [], Opts) of [] -> setelement(1, make_xhtml([?XC(<<"h1">>, <<"Not Found">>)], Host, Lang, AJID), 404); Res -> make_xhtml(Res, Host, Lang, AJID) end. %%%================================== %%%% acl acls_to_xhtml(ACLs) -> ?XAE(<<"table">>, [], [?XE(<<"tbody">>, (lists:map(fun ({acl, Name, Spec} = ACL) -> SName = iolist_to_binary(atom_to_list(Name)), ID = term_to_id(ACL), ?XE(<<"tr">>, ([?XE(<<"td">>, [?INPUT(<<"checkbox">>, <<"selected">>, ID)]), ?XC(<<"td">>, SName)] ++ acl_spec_to_xhtml(ID, Spec))) end, ACLs) ++ [?XE(<<"tr">>, ([?X(<<"td">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"namenew">>, <<"">>)])] ++ acl_spec_to_xhtml(<<"new">>, {user, <<"">>})))]))]). acl_spec_to_text({user, {U, S}}) -> {user, <>}; acl_spec_to_text({user, U}) -> {user, U}; acl_spec_to_text({server, S}) -> {server, S}; acl_spec_to_text({user_regexp, {RU, S}}) -> {user_regexp, <>}; acl_spec_to_text({user_regexp, RU}) -> {user_regexp, RU}; acl_spec_to_text({server_regexp, RS}) -> {server_regexp, RS}; acl_spec_to_text({node_regexp, {RU, RS}}) -> {node_regexp, <>}; acl_spec_to_text({user_glob, {RU, S}}) -> {user_glob, <>}; acl_spec_to_text({user_glob, RU}) -> {user_glob, RU}; acl_spec_to_text({server_glob, RS}) -> {server_glob, RS}; acl_spec_to_text({node_glob, {RU, RS}}) -> {node_glob, <>}; acl_spec_to_text(all) -> {all, <<"">>}; acl_spec_to_text(Spec) -> {raw, term_to_string(Spec)}. acl_spec_to_xhtml(ID, Spec) -> {Type, Str} = acl_spec_to_text(Spec), [acl_spec_select(ID, Type), ?ACLINPUT(Str)]. acl_spec_select(ID, Opt) -> ?XE(<<"td">>, [?XAE(<<"select">>, [{<<"name">>, <<"type", ID/binary>>}], (lists:map(fun (O) -> Sel = if O == Opt -> [{<<"selected">>, <<"selected">>}]; true -> [] end, ?XAC(<<"option">>, (Sel ++ [{<<"value">>, iolist_to_binary(atom_to_list(O))}]), (iolist_to_binary(atom_to_list(O)))) end, [user, server, user_regexp, server_regexp, node_regexp, user_glob, server_glob, node_glob, all, raw])))]). %% @spec (T::any()) -> StringLine::string() term_to_string(T) -> StringParagraph = iolist_to_binary(io_lib:format("~1000000p", [T])), ejabberd_regexp:greplace(StringParagraph, <<"\\n ">>, <<"">>). %% @spec (T::any(), Cols::integer()) -> {NumLines::integer(), Paragraph::string()} term_to_paragraph(T, 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}. term_to_id(T) -> jlib:encode_base64((term_to_binary(T))). acl_parse_query(Host, Query) -> ACLs = ets:select(acl, [{{acl, {'$1', Host}, '$2'}, [], [{{acl, '$1', '$2'}}]}]), case lists:keysearch(<<"submit">>, 1, Query) of {value, _} -> acl_parse_submit(ACLs, Query); _ -> case lists:keysearch(<<"delete">>, 1, Query) of {value, _} -> acl_parse_delete(ACLs, Query) end end. acl_parse_submit(ACLs, Query) -> NewACLs = lists:map(fun ({acl, Name, Spec} = ACL) -> ID = term_to_id(ACL), case {lists:keysearch(<<"type", ID/binary>>, 1, Query), lists:keysearch(<<"value", ID/binary>>, 1, Query)} of {{value, {_, T}}, {value, {_, V}}} -> {Type, Str} = acl_spec_to_text(Spec), case {iolist_to_binary(atom_to_list(Type)), Str} of {T, V} -> ACL; _ -> NewSpec = string_to_spec(T, V), {acl, Name, NewSpec} end; _ -> ACL end end, ACLs), NewACL = case {lists:keysearch(<<"namenew">>, 1, Query), lists:keysearch(<<"typenew">>, 1, Query), lists:keysearch(<<"valuenew">>, 1, Query)} of {{value, {_, <<"">>}}, _, _} -> []; {{value, {_, N}}, {value, {_, T}}, {value, {_, V}}} -> NewName = jlib:binary_to_atom(N), NewSpec = string_to_spec(T, V), [{acl, NewName, NewSpec}]; _ -> [] end, NewACLs ++ NewACL. string_to_spec(<<"user">>, Val) -> string_to_spec2(user, Val); string_to_spec(<<"server">>, Val) -> {server, Val}; string_to_spec(<<"user_regexp">>, Val) -> string_to_spec2(user_regexp, Val); string_to_spec(<<"server_regexp">>, Val) -> {server_regexp, Val}; string_to_spec(<<"node_regexp">>, Val) -> #jid{luser = U, lserver = S, resource = <<"">>} = jid:from_string(Val), {node_regexp, U, S}; string_to_spec(<<"user_glob">>, Val) -> string_to_spec2(user_glob, Val); string_to_spec(<<"server_glob">>, Val) -> {server_glob, Val}; string_to_spec(<<"node_glob">>, Val) -> #jid{luser = U, lserver = S, resource = <<"">>} = jid:from_string(Val), {node_glob, U, S}; string_to_spec(<<"all">>, _) -> all; string_to_spec(<<"raw">>, Val) -> {ok, Tokens, _} = erl_scan:string(binary_to_list(<>)), {ok, NewSpec} = erl_parse:parse_term(Tokens), NewSpec. string_to_spec2(ACLName, Val) -> #jid{luser = U, lserver = S, resource = <<"">>} = jid:from_string(Val), case U of <<"">> -> {ACLName, S}; _ -> {ACLName, {U, S}} end. acl_parse_delete(ACLs, Query) -> NewACLs = lists:filter(fun ({acl, _Name, _Spec} = ACL) -> ID = term_to_id(ACL), not lists:member({<<"selected">>, ID}, Query) end, ACLs), NewACLs. access_rules_to_xhtml(AccessRules, Lang) -> ?XAE(<<"table">>, [], [?XE(<<"tbody">>, (lists:map(fun ({access, Name, Rules} = Access) -> SName = iolist_to_binary(atom_to_list(Name)), ID = term_to_id(Access), ?XE(<<"tr">>, [?XE(<<"td">>, [?INPUT(<<"checkbox">>, <<"selected">>, ID)]), ?XE(<<"td">>, [?AC(<>, SName)]), ?XC(<<"td">>, (term_to_string(Rules)))]) end, lists:keysort(2,AccessRules)) ++ [?XE(<<"tr">>, [?X(<<"td">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"namenew">>, <<"">>)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"addnew">>, <<"Add New">>)])])]))]). access_parse_query(Host, Query) -> AccessRules = ets:select(access, [{{access, {'$1', Host}, '$2'}, [], [{{access, '$1', '$2'}}]}]), case lists:keysearch(<<"addnew">>, 1, Query) of {value, _} -> access_parse_addnew(AccessRules, Host, Query); _ -> case lists:keysearch(<<"delete">>, 1, Query) of {value, _} -> access_parse_delete(AccessRules, Host, Query) end end. access_parse_addnew(_AccessRules, Host, Query) -> case lists:keysearch(<<"namenew">>, 1, Query) of {value, {_, String}} when String /= <<"">> -> Name = jlib:binary_to_atom(String), ejabberd_config:add_option({access, Name, Host}, []), ok end. access_parse_delete(AccessRules, Host, Query) -> lists:foreach(fun ({access, Name, _Rules} = AccessRule) -> ID = term_to_id(AccessRule), case lists:member({<<"selected">>, ID}, Query) of true -> mnesia:transaction(fun () -> mnesia:delete({access, {Name, Host}}) end); _ -> ok end end, AccessRules), ok. access_rule_to_xhtml(Rules) -> Text = lists:flatmap(fun ({Access, ACL} = _Rule) -> SAccess = element_to_list(Access), SACL = atom_to_list(ACL), [SAccess, " \t", SACL, "\n"] end, Rules), ?XAC(<<"textarea">>, [{<<"name">>, <<"rules">>}, {<<"rows">>, <<"16">>}, {<<"cols">>, <<"80">>}], list_to_binary(Text)). parse_access_rule(Text) -> Strings = str:tokens(Text, <<"\r\n">>), case catch lists:flatmap(fun (String) -> case str:tokens(String, <<" \t">>) of [Access, ACL] -> [{list_to_element(Access), jlib:binary_to_atom(ACL)}]; [] -> [] end end, Strings) of {'EXIT', _Reason} -> error; Rs -> {ok, Rs} end. %%%================================== %%%% list_vhosts list_vhosts(Lang, JID) -> Hosts = (?MYHOSTS), HostsAllowed = lists:filter(fun (Host) -> is_acl_match(Host, [configure, webadmin_view], JID) end, Hosts), list_vhosts2(Lang, HostsAllowed). list_vhosts2(Lang, Hosts) -> SHosts = lists:sort(Hosts), [?XE(<<"table">>, [?XE(<<"thead">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Host">>), ?XCT(<<"td">>, <<"Registered Users">>), ?XCT(<<"td">>, <<"Online Users">>)])]), ?XE(<<"tbody">>, (lists:map(fun (Host) -> OnlineUsers = length(ejabberd_sm:get_vh_session_list(Host)), RegisteredUsers = ejabberd_auth:get_vh_registered_users_number(Host), ?XE(<<"tr">>, [?XE(<<"td">>, [?AC(<<"../server/", Host/binary, "/">>, Host)]), ?XC(<<"td">>, (pretty_string_int(RegisteredUsers))), ?XC(<<"td">>, (pretty_string_int(OnlineUsers)))]) end, SHosts)))])]. %%%================================== %%%% list_users list_users(Host, Query, Lang, URLFunc) -> Res = list_users_parse_query(Query, Host), Users = ejabberd_auth:get_vh_registered_users(Host), SUsers = lists:sort([{S, U} || {U, S} <- Users]), FUsers = case length(SUsers) of N when N =< 100 -> [list_given_users(Host, SUsers, <<"../">>, Lang, URLFunc)]; N -> NParts = trunc(math:sqrt(N * 6.17999999999999993783e-1)) + 1, M = trunc(N / NParts) + 1, lists:flatmap(fun (K) -> L = K + M - 1, Last = if L < N -> su_to_list(lists:nth(L, SUsers)); true -> su_to_list(lists:last(SUsers)) end, Name = <<(su_to_list(lists:nth(K, SUsers)))/binary, $\s, 226, 128, 148, $\s, Last/binary>>, [?AC((URLFunc({user_diapason, K, L})), Name), ?BR] end, lists:seq(1, N, M)) end, case Res of %% Parse user creation query and try register: ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], ([?XE(<<"table">>, [?XE(<<"tr">>, [?XC(<<"td">>, <<(?T(<<"User">>))/binary, ":">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"newusername">>, <<"">>)]), ?XE(<<"td">>, [?C(<<" @ ", Host/binary>>)])]), ?XE(<<"tr">>, [?XC(<<"td">>, <<(?T(<<"Password">>))/binary, ":">>), ?XE(<<"td">>, [?INPUT(<<"password">>, <<"newuserpassword">>, <<"">>)]), ?X(<<"td">>)]), ?XE(<<"tr">>, [?X(<<"td">>), ?XAE(<<"td">>, [{<<"class">>, <<"alignright">>}], [?INPUTT(<<"submit">>, <<"addnewuser">>, <<"Add User">>)]), ?X(<<"td">>)])]), ?P] ++ FUsers))]. list_users_parse_query(Query, Host) -> case lists:keysearch(<<"addnewuser">>, 1, Query) of {value, _} -> {value, {_, Username}} = lists:keysearch(<<"newusername">>, 1, Query), {value, {_, Password}} = lists:keysearch(<<"newuserpassword">>, 1, Query), case jid:from_string(<>) of error -> error; #jid{user = User, server = Server} -> case ejabberd_auth:try_register(User, Server, Password) of {error, _Reason} -> error; _ -> ok end end; false -> nothing end. list_users_in_diapason(Host, Diap, Lang, URLFunc) -> Users = ejabberd_auth:get_vh_registered_users(Host), SUsers = lists:sort([{S, U} || {U, S} <- Users]), [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>), N1 = jlib:binary_to_integer(S1), N2 = jlib:binary_to_integer(S2), Sub = lists:sublist(SUsers, N1, N2 - N1 + 1), [list_given_users(Host, Sub, <<"../../">>, Lang, URLFunc)]. list_given_users(Host, Users, Prefix, Lang, URLFunc) -> ModOffline = get_offlinemsg_module(Host), ?XE(<<"table">>, [?XE(<<"thead">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"User">>), ?XCT(<<"td">>, <<"Offline Messages">>), ?XCT(<<"td">>, <<"Last Activity">>)])]), ?XE(<<"tbody">>, (lists:map(fun (_SU = {Server, User}) -> US = {User, Server}, QueueLenStr = get_offlinemsg_length(ModOffline, User, Server), FQueueLen = [?AC((URLFunc({users_queue, Prefix, User, Server})), QueueLenStr)], FLast = case ejabberd_sm:get_user_resources(User, Server) of [] -> case mod_last:get_last_info(User, Server) of not_found -> ?T(<<"Never">>); {ok, Shift, _Status} -> TimeStamp = {Shift div 1000000, Shift rem 1000000, 0}, {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:now_to_local_time(TimeStamp), iolist_to_binary(io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w", [Year, Month, Day, Hour, Minute, Second])) end; _ -> ?T(<<"Online">>) end, ?XE(<<"tr">>, [?XE(<<"td">>, [?AC((URLFunc({user, Prefix, ejabberd_http:url_encode(User), Server})), (us_to_list(US)))]), ?XE(<<"td">>, FQueueLen), ?XC(<<"td">>, FLast)]) end, Users)))]). get_offlinemsg_length(ModOffline, User, Server) -> case ModOffline of none -> <<"disabled">>; _ -> pretty_string_int(ModOffline:get_queue_length(User, Server)) end. get_offlinemsg_module(Server) -> case gen_mod:is_loaded(Server, mod_offline) of true -> mod_offline; false -> none end. get_lastactivity_menuitem_list(Server) -> case gen_mod:db_type(Server, mod_last) of mnesia -> [{<<"last-activity">>, <<"Last Activity">>}]; _ -> [] end. us_to_list({User, Server}) -> jid:to_string({User, Server, <<"">>}). su_to_list({Server, User}) -> jid:to_string({User, Server, <<"">>}). %%%================================== %%%% get_stats get_stats(global, Lang) -> OnlineUsers = mnesia:table_info(session, size), RegisteredUsers = lists:foldl(fun (Host, Total) -> ejabberd_auth:get_vh_registered_users_number(Host) + Total end, 0, ?MYHOSTS), OutS2SNumber = ejabberd_s2s:outgoing_s2s_number(), InS2SNumber = ejabberd_s2s:incoming_s2s_number(), [?XAE(<<"table">>, [], [?XE(<<"tbody">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Registered Users:">>), ?XC(<<"td">>, (pretty_string_int(RegisteredUsers)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Online Users:">>), ?XC(<<"td">>, (pretty_string_int(OnlineUsers)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Outgoing s2s Connections:">>), ?XC(<<"td">>, (pretty_string_int(OutS2SNumber)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Incoming s2s Connections:">>), ?XC(<<"td">>, (pretty_string_int(InS2SNumber)))])])])]; get_stats(Host, Lang) -> OnlineUsers = length(ejabberd_sm:get_vh_session_list(Host)), RegisteredUsers = ejabberd_auth:get_vh_registered_users_number(Host), [?XAE(<<"table">>, [], [?XE(<<"tbody">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Registered Users:">>), ?XC(<<"td">>, (pretty_string_int(RegisteredUsers)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Online Users:">>), ?XC(<<"td">>, (pretty_string_int(OnlineUsers)))])])])]. list_online_users(Host, _Lang) -> Users = [{S, U} || {U, S, _R} <- ejabberd_sm:get_vh_session_list(Host)], SUsers = lists:usort(Users), lists:flatmap(fun ({_S, U} = SU) -> [?AC(<<"../user/", (ejabberd_http:url_encode(U))/binary, "/">>, (su_to_list(SU))), ?BR] end, SUsers). user_info(User, Server, Query, Lang) -> LServer = jid:nameprep(Server), US = {jid:nodeprep(User), LServer}, Res = user_parse_query(User, Server, Query), Resources = ejabberd_sm:get_user_resources(User, Server), FResources = case Resources of [] -> [?CT(<<"None">>)]; _ -> [?XE(<<"ul">>, (lists:map( fun (R) -> FIP = case ejabberd_sm:get_user_info(User, Server, R) of offline -> <<"">>; Info when is_list(Info) -> Node = proplists:get_value(node, Info), Conn = proplists:get_value(conn, Info), {IP, Port} = proplists:get_value(ip, Info), ConnS = case Conn of c2s -> <<"plain">>; c2s_tls -> <<"tls">>; c2s_compressed -> <<"zlib">>; c2s_compressed_tls -> <<"tls+zlib">>; http_bind -> <<"http-bind">>; websocket -> <<"websocket">>; _ -> <<"unknown">> end, <> end, case direction(Lang) of [{_, <<"rtl">>}] -> ?LI([?C((<>))]); _ -> ?LI([?C((<>))]) end end, lists:sort(Resources))))] end, FPassword = [?INPUT(<<"text">>, <<"password">>, <<"">>), ?C(<<" ">>), ?INPUTT(<<"submit">>, <<"chpassword">>, <<"Change Password">>)], UserItems = ejabberd_hooks:run_fold(webadmin_user, LServer, [], [User, Server, Lang]), LastActivity = case ejabberd_sm:get_user_resources(User, Server) of [] -> case mod_last:get_last_info(User, Server) of not_found -> ?T(<<"Never">>); {ok, Shift, _Status} -> TimeStamp = {Shift div 1000000, Shift rem 1000000, 0}, {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:now_to_local_time(TimeStamp), iolist_to_binary(io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w", [Year, Month, Day, Hour, Minute, Second])) end; _ -> ?T(<<"Online">>) end, [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"User ~s">>), [us_to_list(US)])))] ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], ([?XCT(<<"h3">>, <<"Connected Resources:">>)] ++ FResources ++ [?XCT(<<"h3">>, <<"Password:">>)] ++ FPassword ++ [?XCT(<<"h3">>, <<"Last Activity">>)] ++ [?C(LastActivity)] ++ UserItems ++ [?P, ?INPUTT(<<"submit">>, <<"removeuser">>, <<"Remove User">>)]))]. user_parse_query(User, Server, Query) -> lists:foldl(fun ({Action, _Value}, Acc) when Acc == nothing -> user_parse_query1(Action, User, Server, Query); ({_Action, _Value}, Acc) -> Acc end, nothing, Query). user_parse_query1(<<"password">>, _User, _Server, _Query) -> nothing; user_parse_query1(<<"chpassword">>, User, Server, Query) -> case lists:keysearch(<<"password">>, 1, Query) of {value, {_, Password}} -> ejabberd_auth:set_password(User, Server, Password), ok; _ -> error end; user_parse_query1(<<"removeuser">>, User, Server, _Query) -> ejabberd_auth:remove_user(User, Server), ok; user_parse_query1(Action, User, Server, Query) -> case ejabberd_hooks:run_fold(webadmin_user_parse_query, Server, [], [Action, User, Server, Query]) of [] -> nothing; Res -> Res end. list_last_activity(Host, Lang, Integral, Period) -> TimeStamp = p1_time_compat:system_time(seconds), case Period of <<"all">> -> TS = 0, Days = infinity; <<"year">> -> TS = TimeStamp - 366 * 86400, Days = 366; _ -> TS = TimeStamp - 31 * 86400, Days = 31 end, case catch mnesia:dirty_select(last_activity, [{{last_activity, {'_', Host}, '$1', '_'}, [{'>', '$1', TS}], [{trunc, {'/', {'-', TimeStamp, '$1'}, 86400}}]}]) of {'EXIT', _Reason} -> []; Vals -> Hist = histogram(Vals, Integral), if Hist == [] -> [?CT(<<"No Data">>)]; true -> Left = if Days == infinity -> 0; true -> Days - length(Hist) end, Tail = if Integral -> lists:duplicate(Left, lists:last(Hist)); true -> lists:duplicate(Left, 0) end, Max = lists:max(Hist), [?XAE(<<"ol">>, [{<<"id">>, <<"lastactivity">>}, {<<"start">>, <<"0">>}], [?XAE(<<"li">>, [{<<"style">>, <<"width:", (iolist_to_binary(integer_to_list(trunc(90 * V / Max))))/binary, "%;">>}], [{xmlcdata, pretty_string_int(V)}]) || V <- Hist ++ Tail])] end end. histogram(Values, Integral) -> histogram(lists:sort(Values), Integral, 0, 0, []). histogram([H | T], Integral, Current, Count, Hist) when Current == H -> histogram(T, Integral, Current, Count + 1, Hist); histogram([H | _] = Values, Integral, Current, Count, Hist) when Current < H -> if Integral -> histogram(Values, Integral, Current + 1, Count, [Count | Hist]); true -> histogram(Values, Integral, Current + 1, 0, [Count | Hist]) end; histogram([], _Integral, _Current, Count, Hist) -> if Count > 0 -> lists:reverse([Count | Hist]); true -> lists:reverse(Hist) end. %%%================================== %%%% get_nodes get_nodes(Lang) -> RunningNodes = mnesia:system_info(running_db_nodes), StoppedNodes = lists:usort(mnesia:system_info(db_nodes) ++ mnesia:system_info(extra_db_nodes)) -- RunningNodes, FRN = if RunningNodes == [] -> ?CT(<<"None">>); true -> ?XE(<<"ul">>, (lists:map(fun (N) -> S = iolist_to_binary(atom_to_list(N)), ?LI([?AC(<<"../node/", S/binary, "/">>, S)]) end, lists:sort(RunningNodes)))) end, FSN = if StoppedNodes == [] -> ?CT(<<"None">>); true -> ?XE(<<"ul">>, (lists:map(fun (N) -> S = iolist_to_binary(atom_to_list(N)), ?LI([?C(S)]) end, lists:sort(StoppedNodes)))) end, [?XCT(<<"h1">>, <<"Nodes">>), ?XCT(<<"h3">>, <<"Running Nodes">>), FRN, ?XCT(<<"h3">>, <<"Stopped Nodes">>), FSN]. search_running_node(SNode) -> search_running_node(SNode, mnesia:system_info(running_db_nodes)). search_running_node(_, []) -> false; search_running_node(SNode, [Node | Nodes]) -> case iolist_to_binary(atom_to_list(Node)) of SNode -> Node; _ -> search_running_node(SNode, Nodes) end. get_node(global, Node, [], Query, Lang) -> Res = node_parse_query(Node, Query), Base = get_base_path(global, Node), MenuItems2 = make_menu_items(global, Node, Base, Lang), [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Node ~p">>), [Node])))] ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XE(<<"ul">>, ([?LI([?ACT(<>, <<"Database">>)]), ?LI([?ACT(<>, <<"Backup">>)]), ?LI([?ACT(<>, <<"Listened Ports">>)]), ?LI([?ACT(<>, <<"Statistics">>)]), ?LI([?ACT(<>, <<"Update">>)])] ++ MenuItems2)), ?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?INPUTT(<<"submit">>, <<"restart">>, <<"Restart">>), ?C(<<" ">>), ?INPUTT(<<"submit">>, <<"stop">>, <<"Stop">>)])]; get_node(Host, Node, [], _Query, Lang) -> Base = get_base_path(Host, Node), MenuItems2 = make_menu_items(Host, Node, Base, Lang), [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Node ~p">>), [Node]))), ?XE(<<"ul">>, ([?LI([?ACT(<>, <<"Modules">>)])] ++ MenuItems2))]; get_node(global, Node, [<<"db">>], Query, Lang) -> case ejabberd_cluster:call(Node, mnesia, system_info, [tables]) of {badrpc, _Reason} -> [?XCT(<<"h1">>, <<"RPC Call Error">>)]; Tables -> ResS = case node_db_parse_query(Node, Tables, Query) of nothing -> []; ok -> [?XREST(<<"Submitted">>)] end, STables = lists:sort(Tables), Rows = lists:map(fun (Table) -> STable = iolist_to_binary(atom_to_list(Table)), TInfo = case ejabberd_cluster:call(Node, mnesia, table_info, [Table, all]) of {badrpc, _} -> []; I -> I end, {Type, Size, Memory} = case {lists:keysearch(storage_type, 1, TInfo), lists:keysearch(size, 1, TInfo), lists:keysearch(memory, 1, TInfo)} of {{value, {storage_type, T}}, {value, {size, S}}, {value, {memory, M}}} -> {T, S, M}; _ -> {unknown, 0, 0} end, ?XE(<<"tr">>, [?XC(<<"td">>, STable), ?XE(<<"td">>, [db_storage_select(STable, Type, Lang)]), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], (pretty_string_int(Size))), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], (pretty_string_int(Memory)))]) end, STables), [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Database Tables at ~p">>), [Node])) )] ++ ResS ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?XAE(<<"table">>, [], [?XE(<<"thead">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Name">>), ?XCT(<<"td">>, <<"Storage Type">>), ?XCT(<<"td">>, <<"Elements">>), ?XCT(<<"td">>, <<"Memory">>)])]), ?XE(<<"tbody">>, (Rows ++ [?XE(<<"tr">>, [?XAE(<<"td">>, [{<<"colspan">>, <<"4">>}, {<<"class">>, <<"alignright">>}], [?INPUTT(<<"submit">>, <<"submit">>, <<"Submit">>)])])]))])])] end; get_node(global, Node, [<<"backup">>], Query, Lang) -> HomeDirRaw = case {os:getenv("HOME"), os:type()} of {EnvHome, _} when is_list(EnvHome) -> list_to_binary(EnvHome); {false, {win32, _Osname}} -> <<"C:/">>; {false, _} -> <<"/tmp/">> end, HomeDir = filename:nativename(HomeDirRaw), ResS = case node_backup_parse_query(Node, Query) of nothing -> []; ok -> [?XREST(<<"Submitted">>)]; {error, Error} -> [?XRES(<<(?T(<<"Error">>))/binary, ": ", (list_to_binary(io_lib:format("~p", [Error])))/binary>>)] end, [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Backup of ~p">>), [Node])))] ++ ResS ++ [?XCT(<<"p">>, <<"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.">>), ?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?XAE(<<"table">>, [], [?XE(<<"tbody">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Store binary backup:">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"storepath">>, (filename:join(HomeDir, "ejabberd.backup")))]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"store">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Restore binary backup immediately:">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"restorepath">>, (filename:join(HomeDir, "ejabberd.backup")))]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"restore">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Restore binary backup after next ejabberd " "restart (requires less memory):">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"fallbackpath">>, (filename:join(HomeDir, "ejabberd.backup")))]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"fallback">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Store plain text backup:">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"dumppath">>, (filename:join(HomeDir, "ejabberd.dump")))]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"dump">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Restore plain text backup immediately:">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"loadpath">>, (filename:join(HomeDir, "ejabberd.dump")))]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"load">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Import users data from a PIEFXIS file " "(XEP-0227):">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"import_piefxis_filepath">>, (filename:join(HomeDir, "users.xml")))]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"import_piefxis_file">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Export data of all users in the server " "to PIEFXIS files (XEP-0227):">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"export_piefxis_dirpath">>, HomeDir)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"export_piefxis_dir">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XE(<<"td">>, [?CT(<<"Export data of users in a host to PIEFXIS " "files (XEP-0227):">>), ?C(<<" ">>), ?INPUT(<<"text">>, <<"export_piefxis_host_dirhost">>, (?MYNAME))]), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"export_piefxis_host_dirpath">>, HomeDir)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"export_piefxis_host_dir">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XE(<<"td">>, [?CT(<<"Export all tables as SQL queries " "to a file:">>), ?C(<<" ">>), ?INPUT(<<"text">>, <<"export_sql_filehost">>, (?MYNAME))]), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"export_sql_filepath">>, (filename:join(HomeDir, "db.sql")))]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"export_sql_file">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Import user data from jabberd14 spool " "file:">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"import_filepath">>, (filename:join(HomeDir, "user1.xml")))]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"import_file">>, <<"OK">>)])]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Import users data from jabberd14 spool " "directory:">>), ?XE(<<"td">>, [?INPUT(<<"text">>, <<"import_dirpath">>, <<"/var/spool/jabber/">>)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"import_dir">>, <<"OK">>)])])])])])]; get_node(global, Node, [<<"ports">>], Query, Lang) -> Ports = ejabberd_cluster:call(Node, ejabberd_config, get_local_option, [listen, {ejabberd_listener, validate_cfg}, []]), Res = case catch node_ports_parse_query(Node, Ports, Query) of submitted -> ok; {'EXIT', _Reason} -> error; {is_added, ok} -> ok; {is_added, {error, Reason}} -> {error, iolist_to_binary(io_lib:format("~p", [Reason]))}; _ -> nothing end, NewPorts = lists:sort(ejabberd_cluster:call(Node, ejabberd_config, get_local_option, [listen, {ejabberd_listener, validate_cfg}, []])), H1String = <<(?T(<<"Listened Ports at ">>))/binary, (iolist_to_binary(atom_to_list(Node)))/binary>>, (?H1GL(H1String, <<"listening-ports">>, <<"Listening Ports">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; {error, ReasonT} -> [?XRES(<<(?T(<<"Error">>))/binary, ": ", ReasonT/binary>>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [node_ports_to_xhtml(NewPorts, Lang)])]; get_node(Host, Node, [<<"modules">>], Query, Lang) when is_binary(Host) -> Modules = ejabberd_cluster:call(Node, gen_mod, loaded_modules_with_opts, [Host]), Res = case catch node_modules_parse_query(Host, Node, Modules, Query) of submitted -> ok; {'EXIT', Reason} -> ?INFO_MSG("~p~n", [Reason]), error; _ -> nothing end, 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">>, <<"Modules Overview">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; error -> [?XREST(<<"Bad format">>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [node_modules_to_xhtml(NewModules, Lang)])]; get_node(global, Node, [<<"stats">>], _Query, Lang) -> UpTime = ejabberd_cluster:call(Node, erlang, statistics, [wall_clock]), UpTimeS = list_to_binary(io_lib:format("~.3f", [element(1, UpTime) / 1000])), 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 = ejabberd_cluster:call(Node, mnesia, system_info, [transaction_commits]), TransactionsAborted = ejabberd_cluster:call(Node, mnesia, system_info, [transaction_failures]), TransactionsRestarted = ejabberd_cluster:call(Node, mnesia, system_info, [transaction_restarts]), TransactionsLogged = ejabberd_cluster:call(Node, mnesia, system_info, [transaction_log_writes]), [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Statistics of ~p">>), [Node]))), ?XAE(<<"table">>, [], [?XE(<<"tbody">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Uptime:">>), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], UpTimeS)]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"CPU Time:">>), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], CPUTimeS)]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Online Users:">>), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], (pretty_string_int(OnlineUsers)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Transactions Committed:">>), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], (pretty_string_int(TransactionsCommitted)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Transactions Aborted:">>), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], (pretty_string_int(TransactionsAborted)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Transactions Restarted:">>), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], (pretty_string_int(TransactionsRestarted)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Transactions Logged:">>), ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], (pretty_string_int(TransactionsLogged)))])])])]; get_node(global, Node, [<<"update">>], Query, Lang) -> ejabberd_cluster:call(Node, code, purge, [ejabberd_update]), Res = node_update_parse_query(Node, Query), ejabberd_cluster:call(Node, code, load_file, [ejabberd_update]), {ok, _Dir, UpdatedBeams, Script, LowLevelScript, Check} = ejabberd_cluster:call(Node, ejabberd_update, update_info, []), Mods = case UpdatedBeams of [] -> ?CT(<<"None">>); _ -> BeamsLis = lists:map(fun (Beam) -> BeamString = iolist_to_binary(atom_to_list(Beam)), ?LI([?INPUT(<<"checkbox">>, <<"selected">>, BeamString), ?C(BeamString)]) end, UpdatedBeams), SelectButtons = [?BR, ?INPUTATTRS(<<"button">>, <<"selectall">>, <<"Select All">>, [{<<"onClick">>, <<"selectAll()">>}]), ?C(<<" ">>), ?INPUTATTRS(<<"button">>, <<"unselectall">>, <<"Unselect All">>, [{<<"onClick">>, <<"unSelectAll()">>}])], ?XAE(<<"ul">>, [{<<"class">>, <<"nolistyle">>}], (BeamsLis ++ SelectButtons)) end, FmtScript = (?XC(<<"pre">>, list_to_binary(io_lib:format("~p", [Script])))), FmtLowLevelScript = (?XC(<<"pre">>, list_to_binary(io_lib:format("~p", [LowLevelScript])))), [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Update ~p">>), [Node])))] ++ case Res of ok -> [?XREST(<<"Submitted">>)]; {error, ErrorText} -> [?XREST(<<"Error: ", ErrorText/binary>>)]; nothing -> [] end ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [?XCT(<<"h2">>, <<"Update plan">>), ?XCT(<<"h3">>, <<"Modified modules">>), Mods, ?XCT(<<"h3">>, <<"Update script">>), FmtScript, ?XCT(<<"h3">>, <<"Low level update script">>), FmtLowLevelScript, ?XCT(<<"h3">>, <<"Script check">>), ?XC(<<"pre">>, (jlib:atom_to_binary(Check))), ?BR, ?INPUTT(<<"submit">>, <<"update">>, <<"Update">>)])]; get_node(Host, Node, NPath, Query, Lang) -> {Hook, Opts} = case Host of global -> {webadmin_page_node, [Node, NPath, Query, Lang]}; Host -> {webadmin_page_hostnode, [Host, Node, NPath, Query, Lang]} end, case ejabberd_hooks:run_fold(Hook, Host, [], Opts) of [] -> [?XC(<<"h1">>, <<"Not Found">>)]; Res -> Res end. %%%================================== %%%% node parse node_parse_query(Node, Query) -> case lists:keysearch(<<"restart">>, 1, Query) of {value, _} -> case ejabberd_cluster:call(Node, init, restart, []) of {badrpc, _Reason} -> error; _ -> ok end; _ -> case lists:keysearch(<<"stop">>, 1, Query) of {value, _} -> case ejabberd_cluster:call(Node, init, stop, []) of {badrpc, _Reason} -> error; _ -> ok end; _ -> nothing end end. db_storage_select(ID, Opt, Lang) -> ?XAE(<<"select">>, [{<<"name">>, <<"table", ID/binary>>}], (lists:map(fun ({O, Desc}) -> Sel = if O == Opt -> [{<<"selected">>, <<"selected">>}]; true -> [] end, ?XACT(<<"option">>, (Sel ++ [{<<"value">>, iolist_to_binary(atom_to_list(O))}]), Desc) end, [{ram_copies, <<"RAM copy">>}, {disc_copies, <<"RAM and disc copy">>}, {disc_only_copies, <<"Disc only copy">>}, {unknown, <<"Remote copy">>}, {delete_content, <<"Delete content">>}, {delete_table, <<"Delete table">>}]))). node_db_parse_query(_Node, _Tables, [{nokey, <<>>}]) -> nothing; node_db_parse_query(Node, Tables, Query) -> lists:foreach(fun (Table) -> STable = iolist_to_binary(atom_to_list(Table)), case lists:keysearch(<<"table", STable/binary>>, 1, Query) of {value, {_, SType}} -> Type = case SType of <<"unknown">> -> unknown; <<"ram_copies">> -> ram_copies; <<"disc_copies">> -> disc_copies; <<"disc_only_copies">> -> disc_only_copies; <<"delete_content">> -> delete_content; <<"delete_table">> -> delete_table; _ -> false end, if Type == false -> ok; Type == delete_content -> mnesia:clear_table(Table); Type == delete_table -> mnesia:delete_table(Table); Type == unknown -> mnesia:del_table_copy(Table, Node); true -> case mnesia:add_table_copy(Table, Node, Type) of {aborted, _} -> mnesia:change_table_copy_type(Table, Node, Type); _ -> ok end end; _ -> ok end end, Tables), ok. node_backup_parse_query(_Node, [{nokey, <<>>}]) -> nothing; node_backup_parse_query(Node, Query) -> lists:foldl(fun (Action, nothing) -> case lists:keysearch(Action, 1, Query) of {value, _} -> case lists:keysearch(<>, 1, Query) of {value, {_, Path}} -> Res = case Action of <<"store">> -> ejabberd_cluster:call(Node, mnesia, backup, [binary_to_list(Path)]); <<"restore">> -> ejabberd_cluster:call(Node, ejabberd_admin, restore, [Path]); <<"fallback">> -> ejabberd_cluster:call(Node, mnesia, install_fallback, [binary_to_list(Path)]); <<"dump">> -> ejabberd_cluster:call(Node, ejabberd_admin, dump_to_textfile, [Path]); <<"load">> -> ejabberd_cluster:call(Node, mnesia, load_textfile, [binary_to_list(Path)]); <<"import_piefxis_file">> -> ejabberd_cluster:call(Node, ejabberd_piefxis, import_file, [Path]); <<"export_piefxis_dir">> -> ejabberd_cluster:call(Node, ejabberd_piefxis, export_server, [Path]); <<"export_piefxis_host_dir">> -> {value, {_, Host}} = lists:keysearch(<>, 1, Query), ejabberd_cluster:call(Node, ejabberd_piefxis, export_host, [Path, Host]); <<"export_sql_file">> -> {value, {_, Host}} = lists:keysearch(<>, 1, Query), ejabberd_cluster:call(Node, ejd2odbc, export, [Host, Path]); <<"import_file">> -> ejabberd_cluster:call(Node, ejabberd_admin, import_file, [Path]); <<"import_dir">> -> ejabberd_cluster:call(Node, ejabberd_admin, import_dir, [Path]) end, case Res of {error, Reason} -> {error, Reason}; {badrpc, Reason} -> {badrpc, Reason}; _ -> ok end; OtherError -> {error, OtherError} end; _ -> nothing end; (_Action, Res) -> Res end, nothing, [<<"store">>, <<"restore">>, <<"fallback">>, <<"dump">>, <<"load">>, <<"import_file">>, <<"import_dir">>, <<"import_piefxis_file">>, <<"export_piefxis_dir">>, <<"export_piefxis_host_dir">>, <<"export_sql_file">>]). node_ports_to_xhtml(Ports, Lang) -> ?XAE(<<"table">>, [{<<"class">>, <<"withtextareas">>}], [?XE(<<"thead">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Port">>), ?XCT(<<"td">>, <<"IP">>), ?XCT(<<"td">>, <<"Protocol">>), ?XCT(<<"td">>, <<"Module">>), ?XCT(<<"td">>, <<"Options">>)])]), ?XE(<<"tbody">>, (lists:map(fun ({PortIP, Module, Opts} = _E) -> {_Port, SPort, _TIP, SIP, SSPort, NetProt, OptsClean} = get_port_data(PortIP, Opts), SModule = iolist_to_binary(atom_to_list(Module)), {NumLines, SOptsClean} = term_to_paragraph(OptsClean, 40), ?XE(<<"tr">>, [?XAE(<<"td">>, [{<<"size">>, <<"6">>}], [?C(SPort)]), ?XAE(<<"td">>, [{<<"size">>, <<"15">>}], [?C(SIP)]), ?XAE(<<"td">>, [{<<"size">>, <<"4">>}], [?C((iolist_to_binary(atom_to_list(NetProt))))]), ?XE(<<"td">>, [?INPUTS(<<"text">>, <<"module", SSPort/binary>>, SModule, <<"15">>)]), ?XAE(<<"td">>, direction(ltr), [?TEXTAREA(<<"opts", SSPort/binary>>, (iolist_to_binary(integer_to_list(NumLines))), <<"35">>, SOptsClean)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"add", SSPort/binary>>, <<"Restart">>)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"delete", SSPort/binary>>, <<"Stop">>)])]) end, Ports) ++ [?XE(<<"tr">>, [?XE(<<"td">>, [?INPUTS(<<"text">>, <<"portnew">>, <<"">>, <<"6">>)]), ?XE(<<"td">>, [?INPUTS(<<"text">>, <<"ipnew">>, <<"0.0.0.0">>, <<"15">>)]), ?XE(<<"td">>, [make_netprot_html(<<"tcp">>)]), ?XE(<<"td">>, [?INPUTS(<<"text">>, <<"modulenew">>, <<"">>, <<"15">>)]), ?XAE(<<"td">>, direction(ltr), [?TEXTAREA(<<"optsnew">>, <<"2">>, <<"35">>, <<"[]">>)]), ?XAE(<<"td">>, [{<<"colspan">>, <<"2">>}], [?INPUTT(<<"submit">>, <<"addnew">>, <<"Start">>)])])]))]). make_netprot_html(NetProt) -> ?XAE(<<"select">>, [{<<"name">>, <<"netprotnew">>}], (lists:map(fun (O) -> Sel = if O == NetProt -> [{<<"selected">>, <<"selected">>}]; true -> [] end, ?XAC(<<"option">>, (Sel ++ [{<<"value">>, O}]), O) end, [<<"tcp">>, <<"udp">>]))). get_port_data(PortIP, Opts) -> {Port, IPT, IPS, _IPV, NetProt, OptsClean} = ejabberd_listener:parse_listener_portip(PortIP, Opts), SPort = jlib:integer_to_binary(Port), SSPort = list_to_binary( lists:map(fun (N) -> io_lib:format("~.16b", [N]) end, binary_to_list( erlang:md5( [SPort, IPS, atom_to_list(NetProt)])))), {Port, SPort, IPT, IPS, SSPort, NetProt, OptsClean}. node_ports_parse_query(Node, Ports, Query) -> lists:foreach(fun ({PortIpNetp, Module1, Opts1}) -> {Port, _SPort, TIP, _SIP, SSPort, NetProt, _OptsClean} = get_port_data(PortIpNetp, Opts1), case lists:keysearch(<<"add", SSPort/binary>>, 1, Query) of {value, _} -> PortIpNetp2 = {Port, TIP, NetProt}, {{value, {_, SModule}}, {value, {_, SOpts}}} = {lists:keysearch(<<"module", SSPort/binary>>, 1, Query), lists:keysearch(<<"opts", SSPort/binary>>, 1, Query)}, Module = jlib:binary_to_atom(SModule), {ok, Tokens, _} = erl_scan:string(binary_to_list(SOpts) ++ "."), {ok, Opts} = erl_parse:parse_term(Tokens), ejabberd_cluster:call(Node, ejabberd_listener, delete_listener, [PortIpNetp2, Module1]), R = ejabberd_cluster:call(Node, ejabberd_listener, add_listener, [PortIpNetp2, Module, Opts]), throw({is_added, R}); _ -> case lists:keysearch(<<"delete", SSPort/binary>>, 1, Query) of {value, _} -> ejabberd_cluster:call(Node, ejabberd_listener, delete_listener, [PortIpNetp, Module1]), throw(submitted); _ -> ok end end end, Ports), case lists:keysearch(<<"addnew">>, 1, Query) of {value, _} -> {{value, {_, SPort}}, {value, {_, STIP}}, {value, {_, SNetProt}}, {value, {_, SModule}}, {value, {_, SOpts}}} = {lists:keysearch(<<"portnew">>, 1, Query), lists:keysearch(<<"ipnew">>, 1, Query), lists:keysearch(<<"netprotnew">>, 1, Query), lists:keysearch(<<"modulenew">>, 1, Query), lists:keysearch(<<"optsnew">>, 1, Query)}, {ok, Toks, _} = erl_scan:string(binary_to_list(<>)), {ok, Port2} = erl_parse:parse_term(Toks), {ok, ToksIP, _} = erl_scan:string(binary_to_list(<>)), STIP2 = case erl_parse:parse_term(ToksIP) of {ok, IPTParsed} -> IPTParsed; {error, _} -> STIP end, Module = jlib:binary_to_atom(SModule), NetProt2 = jlib:binary_to_atom(SNetProt), {ok, Tokens, _} = erl_scan:string(binary_to_list(<>)), {ok, Opts} = erl_parse:parse_term(Tokens), {Port2, _SPort, IP2, _SIP, _SSPort, NetProt2, OptsClean} = get_port_data({Port2, STIP2, NetProt2}, Opts), R = ejabberd_cluster:call(Node, ejabberd_listener, add_listener, [{Port2, IP2, NetProt2}, Module, OptsClean]), throw({is_added, R}); _ -> ok end. node_modules_to_xhtml(Modules, Lang) -> ?XAE(<<"table">>, [{<<"class">>, <<"withtextareas">>}], [?XE(<<"thead">>, [?XE(<<"tr">>, [?XCT(<<"td">>, <<"Module">>), ?XCT(<<"td">>, <<"Options">>)])]), ?XE(<<"tbody">>, (lists:map(fun ({Module, Opts} = _E) -> SModule = iolist_to_binary(atom_to_list(Module)), {NumLines, SOpts} = term_to_paragraph(Opts, 40), ?XE(<<"tr">>, [?XC(<<"td">>, SModule), ?XAE(<<"td">>, direction(ltr), [?TEXTAREA(<<"opts", SModule/binary>>, (iolist_to_binary(integer_to_list(NumLines))), <<"40">>, SOpts)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"restart", SModule/binary>>, <<"Restart">>)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"stop", SModule/binary>>, <<"Stop">>)])]) end, Modules) ++ [?XE(<<"tr">>, [?XE(<<"td">>, [?INPUT(<<"text">>, <<"modulenew">>, <<"">>)]), ?XAE(<<"td">>, direction(ltr), [?TEXTAREA(<<"optsnew">>, <<"2">>, <<"40">>, <<"[]">>)]), ?XAE(<<"td">>, [{<<"colspan">>, <<"2">>}], [?INPUTT(<<"submit">>, <<"start">>, <<"Start">>)])])]))]). node_modules_parse_query(Host, Node, Modules, Query) -> lists:foreach(fun ({Module, _Opts1}) -> SModule = iolist_to_binary(atom_to_list(Module)), case lists:keysearch(<<"restart", SModule/binary>>, 1, Query) of {value, _} -> {value, {_, SOpts}} = lists:keysearch(<<"opts", SModule/binary>>, 1, Query), {ok, Tokens, _} = erl_scan:string(binary_to_list(<>)), {ok, Opts} = erl_parse:parse_term(Tokens), ejabberd_cluster:call(Node, gen_mod, stop_module, [Host, Module]), ejabberd_cluster:call(Node, gen_mod, start_module, [Host, Module, Opts]), throw(submitted); _ -> case lists:keysearch(<<"stop", SModule/binary>>, 1, Query) of {value, _} -> ejabberd_cluster:call(Node, gen_mod, stop_module, [Host, Module]), throw(submitted); _ -> ok end end end, Modules), case lists:keysearch(<<"start">>, 1, Query) of {value, _} -> {{value, {_, SModule}}, {value, {_, SOpts}}} = {lists:keysearch(<<"modulenew">>, 1, Query), lists:keysearch(<<"optsnew">>, 1, Query)}, Module = jlib:binary_to_atom(SModule), {ok, Tokens, _} = erl_scan:string(binary_to_list(<>)), {ok, Opts} = erl_parse:parse_term(Tokens), ejabberd_cluster:call(Node, gen_mod, start_module, [Host, Module, Opts]), throw(submitted); _ -> ok end. node_update_parse_query(Node, Query) -> case lists:keysearch(<<"update">>, 1, Query) of {value, _} -> ModulesToUpdateStrings = proplists:get_all_values(<<"selected">>, Query), ModulesToUpdate = [jlib:binary_to_atom(M) || M <- ModulesToUpdateStrings], case ejabberd_cluster:call(Node, ejabberd_update, update, [ModulesToUpdate]) of {ok, _} -> ok; {error, Error} -> ?ERROR_MSG("~p~n", [Error]), {error, iolist_to_binary(io_lib:format("~p", [Error]))}; {badrpc, Error} -> ?ERROR_MSG("Bad RPC: ~p~n", [Error]), {error, <<"Bad RPC: ", (iolist_to_binary(io_lib:format("~p", [Error])))/binary>>} end; _ -> nothing end. pretty_print_xml(El) -> list_to_binary(pretty_print_xml(El, <<"">>)). pretty_print_xml({xmlcdata, CData}, Prefix) -> IsBlankCData = lists:all( fun($\f) -> true; ($\r) -> true; ($\n) -> true; ($\t) -> true; ($\v) -> true; ($ ) -> true; (_) -> false end, binary_to_list(CData)), if IsBlankCData -> []; true -> [Prefix, CData, $\n] end; pretty_print_xml(#xmlel{name = Name, attrs = Attrs, children = Els}, Prefix) -> [Prefix, $<, Name, case Attrs of [] -> []; [{Attr, Val} | RestAttrs] -> AttrPrefix = [Prefix, str:copies(<<" ">>, byte_size(Name) + 2)], [$\s, Attr, $=, $', xml:crypt(Val) | [$', lists:map(fun ({Attr1, Val1}) -> [$\n, AttrPrefix, Attr1, $=, $', xml:crypt(Val1), $'] end, RestAttrs)]] end, if Els == [] -> <<"/>\n">>; true -> OnlyCData = lists:all(fun ({xmlcdata, _}) -> true; (#xmlel{}) -> false end, Els), if OnlyCData -> [$>, xml:get_cdata(Els), $<, $/, Name, $>, $\n]; true -> [$>, $\n, lists:map(fun (E) -> pretty_print_xml(E, [Prefix, <<" ">>]) end, Els), Prefix, $<, $/, Name, $>, $\n] end end]. element_to_list(X) when is_atom(X) -> iolist_to_binary(atom_to_list(X)); element_to_list(X) when is_integer(X) -> iolist_to_binary(integer_to_list(X)). list_to_element(Bin) -> {ok, Tokens, _} = erl_scan:string(binary_to_list(Bin)), [{_, _, Element}] = Tokens, Element. url_func({user_diapason, From, To}) -> <<(iolist_to_binary(integer_to_list(From)))/binary, "-", (iolist_to_binary(integer_to_list(To)))/binary, "/">>; url_func({users_queue, Prefix, User, _Server}) -> <>; url_func({user, Prefix, User, _Server}) -> <>. last_modified() -> {<<"Last-Modified">>, <<"Mon, 25 Feb 2008 13:23:30 GMT">>}. cache_control_public() -> {<<"Cache-Control">>, <<"public">>}. %% Transform 1234567890 into "1,234,567,890" pretty_string_int(Integer) when is_integer(Integer) -> pretty_string_int(iolist_to_binary(integer_to_list(Integer))); pretty_string_int(String) when is_binary(String) -> {_, Result} = lists:foldl(fun (NewNumber, {3, Result}) -> {1, <>}; (NewNumber, {CountAcc, Result}) -> {CountAcc + 1, <>} end, {0, <<"">>}, lists:reverse(binary_to_list(String))), Result. %%%================================== %%%% navigation menu %% @spec (Host, Node, Lang, JID::jid()) -> [LI] make_navigation(Host, Node, Lang, JID) -> Menu = make_navigation_menu(Host, Node, Lang, JID), make_menu_items(Lang, Menu). %% @spec (Host, Node, Lang, JID::jid()) -> Menu %% where Host = global | string() %% Node = cluster | string() %% Lang = string() %% Menu = {URL, Title} | {URL, Title, [Menu]} %% URL = string() %% Title = string() make_navigation_menu(Host, Node, Lang, JID) -> HostNodeMenu = make_host_node_menu(Host, Node, Lang, JID), HostMenu = make_host_menu(Host, HostNodeMenu, Lang, JID), NodeMenu = make_node_menu(Host, Node, Lang), make_server_menu(HostMenu, NodeMenu, Lang, JID). %% @spec (Host, Node, Base, Lang) -> [LI] make_menu_items(global, cluster, Base, Lang) -> HookItems = get_menu_items_hook(server, Lang), make_menu_items(Lang, {Base, <<"">>, HookItems}); make_menu_items(global, Node, Base, Lang) -> HookItems = get_menu_items_hook({node, Node}, Lang), make_menu_items(Lang, {Base, <<"">>, HookItems}); make_menu_items(Host, cluster, Base, Lang) -> HookItems = get_menu_items_hook({host, Host}, Lang), make_menu_items(Lang, {Base, <<"">>, HookItems}); make_menu_items(Host, Node, Base, Lang) -> HookItems = get_menu_items_hook({hostnode, Host, Node}, Lang), make_menu_items(Lang, {Base, <<"">>, HookItems}). make_host_node_menu(global, _, _Lang, _JID) -> {<<"">>, <<"">>, []}; make_host_node_menu(_, cluster, _Lang, _JID) -> {<<"">>, <<"">>, []}; make_host_node_menu(Host, Node, Lang, JID) -> HostNodeBase = get_base_path(Host, Node), HostNodeFixed = [{<<"modules/">>, <<"Modules">>}] ++ get_menu_items_hook({hostnode, Host, Node}, Lang), HostNodeBasePath = url_to_path(HostNodeBase), HostNodeFixed2 = [Tuple || Tuple <- HostNodeFixed, is_allowed_path(HostNodeBasePath, Tuple, JID)], {HostNodeBase, iolist_to_binary(atom_to_list(Node)), HostNodeFixed2}. make_host_menu(global, _HostNodeMenu, _Lang, _JID) -> {<<"">>, <<"">>, []}; make_host_menu(Host, HostNodeMenu, Lang, JID) -> HostBase = get_base_path(Host, cluster), HostFixed = [{<<"acls">>, <<"Access Control Lists">>}, {<<"access">>, <<"Access Rules">>}, {<<"users">>, <<"Users">>}, {<<"online-users">>, <<"Online Users">>}] ++ get_lastactivity_menuitem_list(Host) ++ [{<<"nodes">>, <<"Nodes">>, HostNodeMenu}, {<<"stats">>, <<"Statistics">>}] ++ get_menu_items_hook({host, Host}, Lang), HostBasePath = url_to_path(HostBase), HostFixed2 = [Tuple || Tuple <- HostFixed, is_allowed_path(HostBasePath, Tuple, JID)], {HostBase, Host, HostFixed2}. make_node_menu(_Host, cluster, _Lang) -> {<<"">>, <<"">>, []}; make_node_menu(global, Node, Lang) -> NodeBase = get_base_path(global, Node), NodeFixed = [{<<"db/">>, <<"Database">>}, {<<"backup/">>, <<"Backup">>}, {<<"ports/">>, <<"Listened Ports">>}, {<<"stats/">>, <<"Statistics">>}, {<<"update/">>, <<"Update">>}] ++ get_menu_items_hook({node, Node}, Lang), {NodeBase, iolist_to_binary(atom_to_list(Node)), NodeFixed}; make_node_menu(_Host, _Node, _Lang) -> {<<"">>, <<"">>, []}. make_server_menu(HostMenu, NodeMenu, Lang, JID) -> Base = get_base_path(global, cluster), Fixed = [{<<"acls">>, <<"Access Control Lists">>}, {<<"access">>, <<"Access Rules">>}, {<<"vhosts">>, <<"Virtual Hosts">>, HostMenu}, {<<"nodes">>, <<"Nodes">>, NodeMenu}, {<<"stats">>, <<"Statistics">>}] ++ get_menu_items_hook(server, Lang), BasePath = url_to_path(Base), Fixed2 = [Tuple || Tuple <- Fixed, is_allowed_path(BasePath, Tuple, JID)], {Base, <<"">>, Fixed2}. get_menu_items_hook({hostnode, Host, Node}, Lang) -> ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host, [], [Host, Node, Lang]); get_menu_items_hook({host, Host}, Lang) -> ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host, Lang]); get_menu_items_hook({node, Node}, Lang) -> ejabberd_hooks:run_fold(webadmin_menu_node, [], [Node, Lang]); get_menu_items_hook(server, Lang) -> ejabberd_hooks:run_fold(webadmin_menu_main, [], [Lang]). %% @spec (Lang::string(), Menu) -> [LI] %% where Menu = {MURI::string(), MName::string(), Items::[Item]} %% Item = {IURI::string(), IName::string()} | {IURI::string(), IName::string(), Menu} make_menu_items(Lang, Menu) -> lists:reverse(make_menu_items2(Lang, 1, Menu)). make_menu_items2(Lang, Deep, {MURI, MName, _} = Menu) -> Res = case MName of <<"">> -> []; _ -> [make_menu_item(header, Deep, MURI, MName, Lang)] end, make_menu_items2(Lang, Deep, Menu, Res). make_menu_items2(_, _Deep, {_, _, []}, Res) -> Res; make_menu_items2(Lang, Deep, {MURI, MName, [Item | Items]}, Res) -> Res2 = case Item of {IURI, IName} -> [make_menu_item(item, Deep, <>, IName, Lang) | Res]; {IURI, IName, SubMenu} -> ResTemp = [make_menu_item(item, Deep, <>, IName, Lang) | Res], ResSubMenu = make_menu_items2(Lang, Deep + 1, SubMenu), ResSubMenu ++ ResTemp end, make_menu_items2(Lang, Deep, {MURI, MName, Items}, Res2). make_menu_item(header, 1, URI, Name, _Lang) -> ?LI([?XAE(<<"div">>, [{<<"id">>, <<"navhead">>}], [?AC(URI, Name)])]); make_menu_item(header, 2, URI, Name, _Lang) -> ?LI([?XAE(<<"div">>, [{<<"id">>, <<"navheadsub">>}], [?AC(URI, Name)])]); make_menu_item(header, 3, URI, Name, _Lang) -> ?LI([?XAE(<<"div">>, [{<<"id">>, <<"navheadsubsub">>}], [?AC(URI, Name)])]); make_menu_item(item, 1, URI, Name, Lang) -> ?LI([?XAE(<<"div">>, [{<<"id">>, <<"navitem">>}], [?ACT(URI, Name)])]); make_menu_item(item, 2, URI, Name, Lang) -> ?LI([?XAE(<<"div">>, [{<<"id">>, <<"navitemsub">>}], [?ACT(URI, Name)])]); make_menu_item(item, 3, URI, Name, Lang) -> ?LI([?XAE(<<"div">>, [{<<"id">>, <<"navitemsubsub">>}], [?ACT(URI, Name)])]). %%%================================== opt_type(access) -> fun (V) -> V end; opt_type(_) -> [access]. %%% vim: set foldmethod=marker foldmarker=%%%%,%%%=: ejabberd-16.01/src/mod_echo.erl0000644000232200023220000002016312645157216016710 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_echo.erl %%% Author : Alexey Shchepin %%% Purpose : Simple ejabberd module. %%% Created : 15 Jan 2003 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(mod_echo). -author('alexey@process-one.net'). -behaviour(gen_server). -behaviour(gen_mod). %% API -export([start_link/2, start/2, stop/1, do_client_version/3]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -record(state, {host = <<"">> :: binary()}). -define(PROCNAME, ejabberd_mod_echo). %%==================================================================== %% 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]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop(Host) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), gen_server:call(Proc, stop), supervisor:terminate_child(ejabberd_sup, Proc), supervisor:delete_child(ejabberd_sup, Proc). %%==================================================================== %% 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, <<"echo.@HOST@">>), ejabberd_router:register_route(MyHost), {ok, #state{host = MyHost}}. %%-------------------------------------------------------------------- %% 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}. %%-------------------------------------------------------------------- %% 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) -> Packet2 = case From#jid.user of <<"">> -> jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST); _ -> Packet end, do_client_version(disabled, To, From), ejabberd_router:route(To, From, Packet2), {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}. %%-------------------------------------------------------------------- %% Example of routing XMPP packets using Erlang's message passing %%-------------------------------------------------------------------- %% To enable this educational example, edit the function handle_info: %% replace the argument 'disabled' with 'enabled' in the call to the %% function do_client_version. %% ejabberd provides a method to receive XMPP packets using Erlang's %% message passing mechanism. %% %% The packets received by ejabberd are sent %% to the local destination process by sending an Erlang message. %% This means that you can receive XMPP stanzas in an Erlang process %% using Erlang's Receive, as long as this process is registered in %% ejabberd as the process which handles the destination JID. %% %% This example function is called when a client queries the echo service. %% This function then sends a query to the client, and waits 5 seconds to %% receive an answer. The answer will only be accepted if it was sent %% using exactly the same JID. We add a (mostly) random resource to %% try to guarantee that the received response matches the request sent. %% 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 = jid:to_string(To), Random_resource = iolist_to_binary(integer_to_list(random:uniform(100000))), From2 = From#jid{resource = Random_resource, lresource = Random_resource}, Packet = #xmlel{name = <<"iq">>, attrs = [{<<"to">>, ToS}, {<<"type">>, <<"get">>}], children = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_VERSION}], children = []}]}, ejabberd_router:route(From2, To, Packet), Els = receive {route, To, From2, IQ} -> #xmlel{name = <<"query">>, children = List} = xml:get_subtag(IQ, <<"query">>), List after 5000 -> % Timeout in miliseconds: 5 seconds [] end, Values = [{Name, Value} || #xmlel{name = Name, attrs = [], children = [{xmlcdata, Value}]} <- Els], Values_string1 = [io_lib:format("~n~s: ~p", [N, V]) || {N, V} <- Values], 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]. ejabberd-16.01/src/ejabberd_admin.erl0000644000232200023220000005560712645157216020054 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% File : ejabberd_admin.erl %%% Author : Mickael Remond %%% Purpose : Administrative functions and commands %%% Created : 7 May 2006 by Mickael Remond %%% %%% %%% 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_admin). -author('mickael.remond@process-one.net'). -export([start/0, stop/0, %% Server status/0, reopen_log/0, rotate_log/0, set_loglevel/1, 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 register/3, unregister/2, registered_users/1, %% Migration jabberd1.4 import_file/1, import_dir/1, %% Purge DB delete_expired_messages/0, delete_old_messages/1, %% Mnesia set_master/1, backup_mnesia/1, restore_mnesia/1, dump_mnesia/1, dump_table/2, load_mnesia/1, install_fallback_mnesia/1, dump_to_textfile/1, dump_to_textfile/2, mnesia_change_nodename/4, restore/1 % Still used by some modules ]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("ejabberd_commands.hrl"). start() -> ejabberd_commands:register_commands(commands()). stop() -> ejabberd_commands:unregister_commands(commands()). %%% %%% ejabberd commands %%% commands() -> [ %% The commands status, stop and restart are implemented also in ejabberd_ctl %% They are defined here so that other interfaces can use them too #ejabberd_commands{name = status, tags = [server], desc = "Get status of the ejabberd server", module = ?MODULE, function = status, args = [], result = {res, restuple}}, #ejabberd_commands{name = stop, tags = [server], desc = "Stop ejabberd gracefully", module = init, function = stop, args = [], result = {res, rescode}}, #ejabberd_commands{name = restart, tags = [server], desc = "Restart ejabberd gracefully", module = init, function = restart, args = [], result = {res, rescode}}, #ejabberd_commands{name = reopen_log, tags = [logs, server], 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 " "announcement quoted, for example: \n" "ejabberdctl stop_kindly 60 " "\\\"The server will stop in one minute.\\\"", module = ?MODULE, function = stop_kindly, args = [{delay, integer}, {announcement, string}], result = {res, rescode}}, #ejabberd_commands{name = get_loglevel, tags = [logs, server], desc = "Get the current loglevel", module = ejabberd_logger, function = get, args = [], result = {leveltuple, {tuple, [{levelnumber, integer}, {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", module = ?MODULE, function = update_list, args = [], result = {modules, {list, {module, string}}}}, #ejabberd_commands{name = update, tags = [server], desc = "Update the given module, or use the keyword: all", module = ?MODULE, function = update, args = [{module, string}], result = {res, restuple}}, #ejabberd_commands{name = register, tags = [accounts], desc = "Register a user", module = ?MODULE, function = register, args = [{user, binary}, {host, binary}, {password, binary}], result = {res, restuple}}, #ejabberd_commands{name = unregister, tags = [accounts], desc = "Unregister a user", module = ?MODULE, function = unregister, args = [{user, binary}, {host, binary}], result = {res, restuple}}, #ejabberd_commands{name = registered_users, tags = [accounts], desc = "List all registered users in HOST", module = ?MODULE, function = registered_users, args = [{host, binary}], result = {users, {list, {username, string}}}}, #ejabberd_commands{name = registered_vhosts, tags = [server], desc = "List all registered vhosts in SERVER", module = ?MODULE, function = registered_vhosts, args = [], result = {vhosts, {list, {vhost, string}}}}, #ejabberd_commands{name = reload_config, tags = [server], desc = "Reload config file in memory (only affects ACL and Access)", module = ?MODULE, function = reload_config, 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, args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = import_dir, tags = [mnesia], desc = "Import users data from jabberd14 spool dir", module = ?MODULE, function = import_dir, args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = import_piefxis, tags = [mnesia], desc = "Import users data from a PIEFXIS file (XEP-0227)", module = ejabberd_piefxis, function = import_file, args = [{file, string}], result = {res, rescode}}, #ejabberd_commands{name = export_piefxis, tags = [mnesia], desc = "Export data of all users in the server to PIEFXIS files (XEP-0227)", module = ejabberd_piefxis, function = export_server, args = [{dir, string}], result = {res, rescode}}, #ejabberd_commands{name = export_piefxis_host, tags = [mnesia], desc = "Export data of users in a host to PIEFXIS files (XEP-0227)", module = ejabberd_piefxis, function = export_host, args = [{dir, string}, {host, string}], result = {res, rescode}}, #ejabberd_commands{name = export_odbc, tags = [mnesia, odbc], 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", module = ejabberd_config, function = convert_to_yaml, args = [{in, string}, {out, string}], result = {res, rescode}}, #ejabberd_commands{name = delete_expired_messages, tags = [purge], desc = "Delete expired offline messages from database", module = ?MODULE, function = delete_expired_messages, args = [], result = {res, rescode}}, #ejabberd_commands{name = delete_old_messages, tags = [purge], desc = "Delete offline messages older than DAYS", module = ?MODULE, function = delete_old_messages, args = [{days, integer}], result = {res, rescode}}, #ejabberd_commands{name = export2odbc, tags = [mnesia], desc = "Export virtual host information from Mnesia tables to SQL files", module = ejd2odbc, function = export, args = [{host, string}, {directory, string}], result = {res, rescode}}, #ejabberd_commands{name = set_master, tags = [mnesia], desc = "Set master node of the clustered Mnesia tables", longdesc = "If you provide as nodename \"self\", this " "node will be set as its own master.", module = ?MODULE, function = set_master, args = [{nodename, string}], result = {res, restuple}}, #ejabberd_commands{name = mnesia_change_nodename, tags = [mnesia], desc = "Change the erlang node name in a backup file", module = ?MODULE, function = mnesia_change_nodename, args = [{oldnodename, string}, {newnodename, string}, {oldbackup, string}, {newbackup, string}], result = {res, restuple}}, #ejabberd_commands{name = backup, tags = [mnesia], desc = "Store the database to backup file", module = ?MODULE, function = backup_mnesia, args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = restore, tags = [mnesia], desc = "Restore the database from backup file", module = ?MODULE, function = restore_mnesia, args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = dump, tags = [mnesia], desc = "Dump the database to text file", module = ?MODULE, function = dump_mnesia, args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = dump_table, tags = [mnesia], desc = "Dump a table to text file", module = ?MODULE, function = dump_table, args = [{file, string}, {table, string}], result = {res, restuple}}, #ejabberd_commands{name = load, tags = [mnesia], desc = "Restore the database from text file", module = ?MODULE, function = load_mnesia, args = [{file, string}], result = {res, restuple}}, #ejabberd_commands{name = install_fallback, tags = [mnesia], desc = "Install the database from a fallback file", module = ?MODULE, function = install_fallback_mnesia, args = [{file, string}], result = {res, restuple}} ]. %%% %%% Server management %%% status() -> {InternalStatus, ProvidedStatus} = init:get_status(), String1 = io_lib:format("The node ~p is ~p. Status: ~p", [node(), InternalStatus, ProvidedStatus]), {Is_running, String2} = case lists:keysearch(ejabberd, 1, application:which_applications()) of false -> {ejabberd_not_running, "ejabberd is not running in that node."}; {value, {_, _, Version}} -> {ok, io_lib:format("ejabberd ~s is running in that node", [Version])} end, {Is_running, String1 ++ String2}. 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), Module. %%% %%% Stop Kindly %%% stop_kindly(DelaySeconds, AnnouncementTextString) -> Subject = list_to_binary(io_lib:format("Server stop in ~p seconds!", [DelaySeconds])), WaitingDesc = list_to_binary(io_lib:format("Waiting ~p seconds", [DelaySeconds])), AnnouncementText = list_to_binary(AnnouncementTextString), Steps = [ {"Stopping ejabberd port listeners", ejabberd_listener, stop_listeners, []}, {"Sending announcement to connected users", mod_announce, send_announcement_to_all, [?MYNAME, Subject, AnnouncementText]}, {"Sending service message to MUC rooms", ejabberd_admin, send_service_message_all_mucs, [Subject, AnnouncementText]}, {WaitingDesc, timer, sleep, [DelaySeconds * 1000]}, {"Stopping ejabberd", application, stop, [ejabberd]}, {"Stopping Mnesia", mnesia, stop, []}, {"Stopping Erlang node", init, stop, []} ], NumberLast = length(Steps), TimestampStart = calendar:datetime_to_gregorian_seconds({date(), time()}), lists:foldl( fun({Desc, Mod, Func, Args}, NumberThis) -> SecondsDiff = calendar:datetime_to_gregorian_seconds({date(), time()}) - TimestampStart, io:format("[~p/~p ~ps] ~s... ", [NumberThis, NumberLast, SecondsDiff, Desc]), Result = (catch apply(Mod, Func, Args)), io:format("~p~n", [Result]), NumberThis+1 end, 1, Steps), ok. send_service_message_all_mucs(Subject, AnnouncementText) -> Message = list_to_binary( io_lib:format("~s~n~s", [Subject, AnnouncementText])), lists:foreach( fun(ServerHost) -> MUCHost = gen_mod:get_module_opt_host( ServerHost, mod_muc, <<"conference.@HOST@">>), mod_muc:broadcast_service_message(MUCHost, Message) end, ?MYHOSTS). %%% %%% ejabberd_update %%% update_list() -> {ok, _Dir, UpdatedBeams, _Script, _LowLevelScript, _Check} = ejabberd_update:update_info(), [atom_to_list(Beam) || Beam <- UpdatedBeams]. update("all") -> [update_module(ModStr) || ModStr <- update_list()], {ok, []}; update(ModStr) -> update_module(ModStr). update_module(ModuleNameBin) when is_binary(ModuleNameBin) -> update_module(binary_to_list(ModuleNameBin)); update_module(ModuleNameString) -> ModuleName = list_to_atom(ModuleNameString), case ejabberd_update:update([ModuleName]) of {ok, _Res} -> {ok, []}; {error, Reason} -> {error, Reason} end. %%% %%% Account management %%% register(User, Host, Password) -> case ejabberd_auth:try_register(User, Host, Password) of {atomic, ok} -> {ok, io_lib:format("User ~s@~s successfully registered", [User, Host])}; {atomic, exists} -> String = io_lib:format("User ~s@~s already registered at node ~p", [User, Host, node()]), {exists, String}; {error, Reason} -> String = io_lib:format("Can't register user ~s@~s at node ~p: ~p", [User, Host, node(), Reason]), {cannot_register, String} end. unregister(User, Host) -> ejabberd_auth:remove_user(User, Host), {ok, ""}. registered_users(Host) -> Users = ejabberd_auth:get_vh_registered_users(Host), SUsers = lists:sort(Users), lists:map(fun({U, _S}) -> U end, SUsers). registered_vhosts() -> ?MYHOSTS. reload_config() -> ejabberd_config:reload_file(), 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 %%% import_file(Path) -> case jd2ejd:import_file(Path) of ok -> {ok, ""}; {error, Reason} -> String = io_lib:format("Can't import jabberd14 spool file ~p at node ~p: ~p", [filename:absname(Path), node(), Reason]), {cannot_import_file, String} end. import_dir(Path) -> case jd2ejd:import_dir(Path) of ok -> {ok, ""}; {error, Reason} -> String = io_lib:format("Can't import jabberd14 spool dir ~p at node ~p: ~p", [filename:absname(Path), node(), Reason]), {cannot_import_dir, String} end. %%% %%% Purge DB %%% delete_expired_messages() -> lists:foreach( fun(Host) -> {atomic, ok} = mod_offline:remove_expired_messages(Host) end, ?MYHOSTS). delete_old_messages(Days) -> lists:foreach( fun(Host) -> {atomic, _} = mod_offline:remove_old_messages(Days, Host) end, ?MYHOSTS). %%% %%% Mnesia management %%% set_master("self") -> set_master(node()); set_master(NodeString) when is_list(NodeString) -> set_master(list_to_atom(NodeString)); set_master(Node) when is_atom(Node) -> case mnesia:set_master_nodes([Node]) of ok -> {ok, ""}; {error, Reason} -> String = io_lib:format("Can't set master node ~p at node ~p:~n~p", [Node, node(), Reason]), {error, String} end. backup_mnesia(Path) -> case mnesia:backup(Path) of ok -> {ok, ""}; {error, Reason} -> String = io_lib:format("Can't store backup in ~p at node ~p: ~p", [filename:absname(Path), node(), Reason]), {cannot_backup, String} end. restore_mnesia(Path) -> case ejabberd_admin:restore(Path) of {atomic, _} -> {ok, ""}; {error, Reason} -> String = io_lib:format("Can't restore backup from ~p at node ~p: ~p", [filename:absname(Path), node(), Reason]), {cannot_restore, String}; {aborted,{no_exists,Table}} -> String = io_lib:format("Can't restore backup from ~p at node ~p: Table ~p does not exist.", [filename:absname(Path), node(), Table]), {table_not_exists, String}; {aborted,enoent} -> String = io_lib:format("Can't restore backup from ~p at node ~p: File not found.", [filename:absname(Path), node()]), {file_not_found, String} end. %% Mnesia database restore %% This function is called from ejabberd_ctl, ejabberd_web_admin and %% mod_configure/adhoc restore(Path) -> mnesia:restore(Path, [{keep_tables,keep_tables()}, {default_op, skip_tables}]). %% This function return a list of tables that should be kept from a previous %% version backup. %% Obsolete tables or tables created by module who are no longer used are not %% restored and are ignored. keep_tables() -> lists:flatten([acl, passwd, config, local_config, keep_modules_tables()]). %% Returns the list of modules tables in use, according to the list of actually %% loaded modules keep_modules_tables() -> lists:map(fun(Module) -> module_tables(Module) end, gen_mod:loaded_modules(?MYNAME)). %% TODO: This mapping should probably be moved to a callback function in each %% module. %% Mapping between modules and their tables module_tables(mod_announce) -> [motd, motd_users]; module_tables(mod_irc) -> [irc_custom]; module_tables(mod_last) -> [last_activity]; module_tables(mod_muc) -> [muc_room, muc_registered]; module_tables(mod_offline) -> [offline_msg]; module_tables(mod_privacy) -> [privacy]; module_tables(mod_private) -> [private_storage]; module_tables(mod_pubsub) -> [pubsub_node]; module_tables(mod_roster) -> [roster]; module_tables(mod_shared_roster) -> [sr_group, sr_user]; module_tables(mod_vcard) -> [vcard, vcard_search]; module_tables(_Other) -> []. get_local_tables() -> Tabs1 = lists:delete(schema, mnesia:system_info(local_tables)), Tabs = lists:filter( fun(T) -> case mnesia:table_info(T, storage_type) of disc_copies -> true; disc_only_copies -> true; _ -> false end end, Tabs1), Tabs. dump_mnesia(Path) -> Tabs = get_local_tables(), dump_tables(Path, Tabs). dump_table(Path, STable) -> Table = list_to_atom(STable), dump_tables(Path, [Table]). dump_tables(Path, Tables) -> case dump_to_textfile(Path, Tables) of ok -> {ok, ""}; {error, Reason} -> String = io_lib:format("Can't store dump in ~p at node ~p: ~p", [filename:absname(Path), node(), Reason]), {cannot_dump, String} end. dump_to_textfile(File) -> Tabs = get_local_tables(), dump_to_textfile(File, Tabs). dump_to_textfile(File, Tabs) -> dump_to_textfile(mnesia:system_info(is_running), Tabs, file:open(File, [write])). dump_to_textfile(yes, Tabs, {ok, F}) -> Defs = lists:map( fun(T) -> {T, [{record_name, mnesia:table_info(T, record_name)}, {attributes, mnesia:table_info(T, attributes)}]} end, Tabs), io:format(F, "~p.~n", [{tables, Defs}]), lists:foreach(fun(T) -> dump_tab(F, T) end, Tabs), file:close(F); dump_to_textfile(_, _, {ok, F}) -> file:close(F), {error, mnesia_not_running}; dump_to_textfile(_, _, {error, Reason}) -> {error, Reason}. dump_tab(F, T) -> W = mnesia:table_info(T, wild_pattern), {atomic,All} = mnesia:transaction( fun() -> mnesia:match_object(T, W, read) end), lists:foreach( fun(Term) -> io:format(F,"~p.~n", [setelement(1, Term, T)]) end, All). load_mnesia(Path) -> case mnesia:load_textfile(Path) of {atomic, ok} -> {ok, ""}; {error, Reason} -> String = io_lib:format("Can't load dump in ~p at node ~p: ~p", [filename:absname(Path), node(), Reason]), {cannot_load, String} end. install_fallback_mnesia(Path) -> case mnesia:install_fallback(Path) of ok -> {ok, ""}; {error, Reason} -> String = io_lib:format("Can't install fallback from ~p at node ~p: ~p", [filename:absname(Path), node(), Reason]), {cannot_fallback, String} end. mnesia_change_nodename(FromString, ToString, Source, Target) -> From = list_to_atom(FromString), To = list_to_atom(ToString), Switch = fun (Node) when Node == From -> io:format(" - Replacing nodename: '~p' with: '~p'~n", [From, To]), To; (Node) when Node == To -> %% throw({error, already_exists}); io:format(" - Node: '~p' will not be modified (it is already '~p')~n", [Node, To]), Node; (Node) -> io:format(" - Node: '~p' will not be modified (it is not '~p')~n", [Node, From]), Node end, Convert = fun ({schema, db_nodes, Nodes}, Acc) -> io:format(" +++ db_nodes ~p~n", [Nodes]), {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc}; ({schema, version, Version}, Acc) -> io:format(" +++ version: ~p~n", [Version]), {[{schema, version, Version}], Acc}; ({schema, cookie, Cookie}, Acc) -> io:format(" +++ cookie: ~p~n", [Cookie]), {[{schema, cookie, Cookie}], Acc}; ({schema, Tab, CreateList}, Acc) -> io:format("~n * Checking table: '~p'~n", [Tab]), Keys = [ram_copies, disc_copies, disc_only_copies], OptSwitch = fun({Key, Val}) -> case lists:member(Key, Keys) of true -> io:format(" + Checking key: '~p'~n", [Key]), {Key, lists:map(Switch, Val)}; false-> {Key, Val} end end, Res = {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc}, Res; (Other, Acc) -> {[Other], Acc} end, mnesia:traverse_backup(Source, Target, Convert, switched). ejabberd-16.01/src/eldap_utils.erl0000644000232200023220000003154112645157216017442 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : eldap_utils.erl %%% Author : Mickael Remond %%% Purpose : ejabberd LDAP helper functions %%% Created : 12 Oct 2006 by Mickael Remond %%% %%% %%% 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(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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("eldap.hrl"). %% Generate an 'or' LDAP query on one or several attributes %% If there is only one attribute generate_subfilter([UID]) -> subfilter(UID); %% If there is several attributes generate_subfilter(UIDs) -> iolist_to_binary(["(|", [subfilter(UID) || UID <- UIDs], ")"]). %% Subfilter for a single attribute subfilter({UIDAttr, UIDAttrFormat}) -> %% The default UiDAttrFormat is %u <<$(, UIDAttr/binary, $=, UIDAttrFormat/binary, $)>>; %% The default UiDAttrFormat is <<"%u">> subfilter({UIDAttr}) -> <<$(, UIDAttr/binary, $=, "%u)">>. %% Not tail-recursive, but it is not very terribly. %% It stops finding on the first not empty value. -spec find_ldap_attrs([{binary()} | {binary(), binary()}], [{binary(), [binary()]}]) -> <<>> | {binary(), binary()}. find_ldap_attrs([{Attr} | Rest], Attributes) -> find_ldap_attrs([{Attr, <<"%u">>} | Rest], Attributes); find_ldap_attrs([{Attr, Format} | Rest], Attributes) -> case get_ldap_attr(Attr, Attributes) of Value when is_binary(Value), Value /= <<>> -> {Value, Format}; _ -> find_ldap_attrs(Rest, Attributes) end; find_ldap_attrs([], _) -> <<>>. -spec get_ldap_attr(binary(), [{binary(), [binary()]}]) -> binary(). get_ldap_attr(LDAPAttr, Attributes) -> Res = lists:filter( fun({Name, _}) -> case_insensitive_match(Name, LDAPAttr) end, Attributes), case Res of [{_, [Value|_]}] -> Value; _ -> <<>> end. -spec get_user_part(binary(), binary()) -> {ok, binary()} | {error, badmatch}. get_user_part(String, Pattern) -> F = fun(S, P) -> First = str:str(P, <<"%u">>), TailLength = byte_size(P) - (First+1), str:sub_string(S, First, byte_size(S) - TailLength) end, case catch F(String, Pattern) of {'EXIT', _} -> {error, badmatch}; Result -> case catch ejabberd_regexp:replace(Pattern, <<"%u">>, Result) of {'EXIT', _} -> {error, badmatch}; StringRes -> case case_insensitive_match(StringRes, String) of true -> {ok, Result}; false -> {error, badmatch} end end end. -spec make_filter([{binary(), [binary()]}], [{binary(), binary()}]) -> any(). make_filter(Data, UIDs) -> NewUIDs = [{U, eldap_filter:do_sub( UF, [{<<"%u">>, <<"*%u*">>, 1}])} || {U, UF} <- UIDs], Filter = lists:flatmap( fun({Name, [Value | _]}) -> case Name of <<"%u">> when Value /= <<"">> -> case eldap_filter:parse( generate_subfilter(NewUIDs), [{<<"%u">>, Value}]) of {ok, F} -> [F]; _ -> [] end; _ when Value /= <<"">> -> [eldap:substrings( Name, [{any, Value}])]; _ -> [] end end, Data), case Filter of [F] -> F; _ -> eldap:'and'(Filter) end. -spec case_insensitive_match(binary(), binary()) -> boolean(). case_insensitive_match(X, Y) -> X1 = str:to_lower(X), Y1 = str:to_lower(Y), if X1 == Y1 -> true; true -> false end. get_state(Server, Module) -> Proc = gen_mod:get_module_proc(Server, Module), gen_server:call(Proc, get_state). %% From the list of uids attribute: %% we look from alias domain (%d) and make the substitution %% with the actual host domain %% This help when you need to configure many virtual domains. -spec uids_domain_subst(binary(), [{binary(), binary()}]) -> [{binary(), binary()}]. uids_domain_subst(Host, UIDs) -> lists:map(fun({U,V}) -> {U, eldap_filter:do_sub(V,[{<<"%d">>, Host}])}; (A) -> A end, UIDs). -spec get_config(binary(), list()) -> eldap_config(). get_config(Host, Opts) -> Servers = gen_mod:get_opt({ldap_servers, Host}, Opts, fun(L) -> [iolist_to_binary(H) || H <- L] end, [<<"localhost">>]), Backups = gen_mod:get_opt({ldap_backups, Host}, Opts, fun(L) -> [iolist_to_binary(H) || H <- L] end, []), Encrypt = gen_mod:get_opt({ldap_encrypt, Host}, Opts, fun(tls) -> tls; (starttls) -> starttls; (none) -> none end, none), TLSVerify = gen_mod:get_opt({ldap_tls_verify, Host}, Opts, fun(hard) -> hard; (soft) -> soft; (false) -> false end, false), TLSCAFile = gen_mod:get_opt({ldap_tls_cacertfile, Host}, Opts, fun iolist_to_binary/1), TLSDepth = gen_mod:get_opt({ldap_tls_depth, Host}, Opts, fun(I) when is_integer(I), I>=0 -> I end), 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 = gen_mod:get_opt({ldap_rootdn, Host}, Opts, fun iolist_to_binary/1, <<"">>), Password = gen_mod:get_opt({ldap_password, Host}, Opts, fun iolist_to_binary/1, <<"">>), Base = gen_mod:get_opt({ldap_base, Host}, Opts, fun iolist_to_binary/1, <<"">>), OldDerefAliases = gen_mod:get_opt({deref_aliases, Host}, Opts, fun(never) -> never; (searching) -> searching; (finding) -> finding; (always) -> always end, unspecified), DerefAliases = if OldDerefAliases == unspecified -> gen_mod:get_opt({ldap_deref_aliases, Host}, Opts, fun(never) -> never; (searching) -> searching; (finding) -> finding; (always) -> always end, never); true -> ?WARNING_MSG("Option 'deref_aliases' is deprecated. " "The option is still supported " "but it is better to fix your config: " "use 'ldap_deref_aliases' instead.", []), OldDerefAliases end, #eldap_config{servers = Servers, backups = Backups, tls_options = [{encrypt, Encrypt}, {tls_verify, TLSVerify}, {tls_cacertfile, TLSCAFile}, {tls_depth, TLSDepth}], port = Port, dn = RootDN, password = Password, base = Base, deref_aliases = DerefAliases}. %%---------------------------------------- %% Borrowed from asn1rt_ber_bin_v2.erl %%---------------------------------------- %%% The tag-number for universal types -define(N_BOOLEAN, 1). -define(N_INTEGER, 2). -define(N_BIT_STRING, 3). -define(N_OCTET_STRING, 4). -define(N_NULL, 5). -define(N_OBJECT_IDENTIFIER, 6). -define(N_OBJECT_DESCRIPTOR, 7). -define(N_EXTERNAL, 8). -define(N_REAL, 9). -define(N_ENUMERATED, 10). -define(N_EMBEDDED_PDV, 11). -define(N_SEQUENCE, 16). -define(N_SET, 17). -define(N_NumericString, 18). -define(N_PrintableString, 19). -define(N_TeletexString, 20). -define(N_VideotexString, 21). -define(N_IA5String, 22). -define(N_UTCTime, 23). -define(N_GeneralizedTime, 24). -define(N_GraphicString, 25). -define(N_VisibleString, 26). -define(N_GeneralString, 27). -define(N_UniversalString, 28). -define(N_BMPString, 30). decode_octet_string(Buffer, Range, Tags) -> % NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}), decode_restricted_string(Buffer, Range, Tags). decode_restricted_string(Tlv, Range, TagsIn) -> Val = match_tags(Tlv, TagsIn), Val2 = case Val of PartList = [_H|_T] -> % constructed val collect_parts(PartList); Bin -> Bin end, check_and_convert_restricted_string(Val2, Range). check_and_convert_restricted_string(Val, Range) -> {StrLen,NewVal} = if is_binary(Val) -> {size(Val), Val}; true -> {length(Val), list_to_binary(Val)} end, case Range of [] -> % No length constraint NewVal; {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint NewVal; {{Lb,_Ub},[]} when StrLen >= Lb -> NewVal; {{Lb,_Ub},_Ext=[Min|_]} when StrLen >= Lb; StrLen >= Min -> NewVal; {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1; StrLen =< Ub2, StrLen >= Lb2 -> NewVal; StrLen -> % fixed length constraint NewVal; {_,_} -> exit({error,{asn1,{length,Range,Val}}}); _Len when is_integer(_Len) -> exit({error,{asn1,{length,Range,Val}}}); _ -> % some strange constraint that we don't support yet NewVal end. %%---------------------------------------- %% Decode the in buffer to bits %%---------------------------------------- match_tags({T,V},[T]) -> V; match_tags({T,V}, [T|Tt]) -> match_tags(V,Tt); match_tags([{T,V}],[T|Tt]) -> match_tags(V, Tt); match_tags(Vlist = [{T,_V}|_], [T]) -> Vlist; match_tags(Tlv, []) -> Tlv; match_tags({Tag,_V},[T|_Tt]) -> {error,{asn1,{wrong_tag,{Tag,T}}}}. collect_parts(TlvList) -> collect_parts(TlvList,[]). collect_parts([{_,L}|Rest],Acc) when is_list(L) -> collect_parts(Rest,[collect_parts(L)|Acc]); collect_parts([{?N_BIT_STRING,<>}|Rest],_Acc) -> collect_parts_bit(Rest,[Bits],Unused); collect_parts([{_T,V}|Rest],Acc) -> collect_parts(Rest,[V|Acc]); collect_parts([],Acc) -> list_to_binary(lists:reverse(Acc)). 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]. ejabberd-16.01/src/mod_http_upload.erl0000644000232200023220000010333712645157216020322 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% 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'). -protocol({xep, 363, '0.1'}). -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">>}, {<<".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 :: binary(), height :: integer(), width :: 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), supervisor:terminate_child(ejabberd_sup, Proc), 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, 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, 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 = 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 -> ?DEBUG("Storing file from ~s for ~s: ~s", [?ADDR_TO_STR(IP), Host, Path]), case store_file(Path, Data, FileMode, DirMode, GetPrefix, Slot, 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, ?FORMAT(Error)]), http_response(Host, 500) end; {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); {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} = Request) when Method == 'GET'; Method == 'HEAD' -> {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], <<$/>>), case file:read_file(Path) of {ok, Data} -> ?INFO_MSG("Serving ~s to ~s", [Path, ?ADDR_TO_STR(IP)]), 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", [?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@">>), {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(). 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", [jid:to_string(From)]), IQ#iq{type = error, sub_el = [SubEl, Error]} end; deny -> ?DEBUG("Denying HTTP upload slot request from ~s", [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, 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)", [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(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)", [jid:to_string(JID), File]), {ok, PutURL, GetURL}; Lines -> ?ERROR_MSG("Can't parse data received for ~s from <~s>: ~p", [jid:to_string(JID), ServiceURL, Lines]), {error, ?ERR_SERVICE_UNAVAILABLE} end; {ok, {402, _Body}} -> ?INFO_MSG("Got status code 402 for ~s from <~s>", [jid:to_string(JID), ServiceURL]), {error, ?ERR_RESOURCE_CONSTRAINT}; {ok, {403, _Body}} -> ?INFO_MSG("Got status code 403 for ~s from <~s>", [jid:to_string(JID), ServiceURL]), {error, ?ERR_NOT_ALLOWED}; {ok, {413, _Body}} -> ?INFO_MSG("Got status code 413 for ~s from <~s>", [jid:to_string(JID), ServiceURL]), {error, ?ERR_NOT_ACCEPTABLE}; {ok, {Code, _Body}} -> ?ERROR_MSG("Got unexpected status code for ~s from <~s>: ~B", [jid:to_string(JID), ServiceURL, Code]), {error, ?ERR_SERVICE_UNAVAILABLE}; {error, Reason} -> ?ERROR_MSG("Error requesting upload slot for ~s from <~s>: ~p", [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. -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, binary(), slot(), boolean()) -> ok | {ok, [{binary(), binary()}], binary()} | {error, term()}. 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 | _] = Slot, 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)}; pass -> ok end; pass -> ok end; ok -> ok; Err -> Err end. -spec do_store_file(file:filename_all(), binary(), integer() | undefined, integer() | undefined) -> 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, 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(binary()) -> {ok, media_info()} | pass. identify(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)}}; _ -> ?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 Mpix", [Path]), pass; 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: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", [Path, OutPath, string:strip(Err, right, $\n)]), pass end; true -> ?DEBUG("Won't call 'convert' for unknown type ~s", [T]), pass end. -spec thumb_el(binary(), binary()) -> xmlel(). thumb_el(Path, URI) -> ContentType = guess_content_type(Path), case identify(Path) of {ok, #media_info{height = H, width = 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)}]}; pass -> #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 = jid: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(jid:make(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, ?FORMAT(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, Error}; _:Error -> {error, Error} end. ejabberd-16.01/src/randoms.erl0000644000232200023220000000253012645157216016574 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : randoms.erl %%% Author : Alexey Shchepin %%% Purpose : Random generation number wrapper %%% Created : 13 Dec 2002 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(randoms). -author('alexey@process-one.net'). -export([get_string/0]). -export([start/0]). start() -> ok. get_string() -> R = crypto:rand_uniform(0, 16#10000000000000000), jlib:integer_to_binary(R). ejabberd-16.01/src/mod_configure.erl0000644000232200023220000020720512645157216017757 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : mod_configure.erl %%% Author : Alexey Shchepin %%% Purpose : Support for online configuration of ejabberd %%% Created : 19 Jan 2003 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(mod_configure). -author('alexey@process-one.net'). -protocol({xep, 133, '1.1'}). -behaviour(gen_mod). -export([start/2, stop/1, get_local_identity/5, 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, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.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), ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 50), ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, get_local_identity, 50), ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_items, 50), ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 50), ejabberd_hooks:add(adhoc_local_items, Host, ?MODULE, adhoc_local_items, 50), ejabberd_hooks:add(adhoc_local_commands, Host, ?MODULE, adhoc_local_commands, 50), ejabberd_hooks:add(adhoc_sm_items, Host, ?MODULE, adhoc_sm_items, 50), ejabberd_hooks:add(adhoc_sm_commands, Host, ?MODULE, adhoc_sm_commands, 50), ok. stop(Host) -> ejabberd_hooks:delete(adhoc_sm_commands, Host, ?MODULE, adhoc_sm_commands, 50), ejabberd_hooks:delete(adhoc_sm_items, Host, ?MODULE, adhoc_sm_items, 50), ejabberd_hooks:delete(adhoc_local_commands, Host, ?MODULE, adhoc_local_commands, 50), ejabberd_hooks:delete(adhoc_local_items, Host, ?MODULE, adhoc_local_items, 50), ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 50), ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 50), ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, get_local_identity, 50), ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 50), ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_local_items, 50), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_COMMANDS), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_COMMANDS). %%%----------------------------------------------------------------------- -define(INFO_IDENTITY(Category, Type, Name, Lang), [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, Category}, {<<"type">>, Type}, {<<"name">>, ?T(Lang, Name)}], children = []}]). -define(INFO_COMMAND(Name, Lang), ?INFO_IDENTITY(<<"automation">>, <<"command-node">>, Name, Lang)). -define(NODEJID(To, Name, Node), #xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string(To)}, {<<"name">>, ?T(Lang, Name)}, {<<"node">>, Node}], children = []}). -define(NODE(Name, Node), #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Server}, {<<"name">>, ?T(Lang, Name)}, {<<"node">>, Node}], children = []}). -define(NS_ADMINX(Sub), <<(?NS_ADMIN)/binary, "#", Sub/binary>>). -define(NS_ADMINL(Sub), [<<"http:">>, <<"jabber.org">>, <<"protocol">>, <<"admin">>, Sub]). tokenize(Node) -> str:tokens(Node, <<"/#">>). get_sm_identity(Acc, _From, _To, Node, Lang) -> case Node of <<"config">> -> ?INFO_COMMAND(<<"Configuration">>, Lang); _ -> Acc end. get_local_identity(Acc, _From, _To, Node, Lang) -> LNode = tokenize(Node), case LNode of [<<"running nodes">>, ENode] -> ?INFO_IDENTITY(<<"ejabberd">>, <<"node">>, ENode, Lang); [<<"running nodes">>, _ENode, <<"DB">>] -> ?INFO_COMMAND(<<"Database">>, Lang); [<<"running nodes">>, _ENode, <<"modules">>, <<"start">>] -> ?INFO_COMMAND(<<"Start Modules">>, Lang); [<<"running nodes">>, _ENode, <<"modules">>, <<"stop">>] -> ?INFO_COMMAND(<<"Stop Modules">>, Lang); [<<"running nodes">>, _ENode, <<"backup">>, <<"backup">>] -> ?INFO_COMMAND(<<"Backup">>, Lang); [<<"running nodes">>, _ENode, <<"backup">>, <<"restore">>] -> ?INFO_COMMAND(<<"Restore">>, Lang); [<<"running nodes">>, _ENode, <<"backup">>, <<"textfile">>] -> ?INFO_COMMAND(<<"Dump to Text File">>, Lang); [<<"running nodes">>, _ENode, <<"import">>, <<"file">>] -> ?INFO_COMMAND(<<"Import File">>, Lang); [<<"running nodes">>, _ENode, <<"import">>, <<"dir">>] -> ?INFO_COMMAND(<<"Import Directory">>, Lang); [<<"running nodes">>, _ENode, <<"restart">>] -> ?INFO_COMMAND(<<"Restart Service">>, Lang); [<<"running nodes">>, _ENode, <<"shutdown">>] -> ?INFO_COMMAND(<<"Shut Down Service">>, Lang); ?NS_ADMINL(<<"add-user">>) -> ?INFO_COMMAND(<<"Add User">>, Lang); ?NS_ADMINL(<<"delete-user">>) -> ?INFO_COMMAND(<<"Delete User">>, Lang); ?NS_ADMINL(<<"end-user-session">>) -> ?INFO_COMMAND(<<"End User Session">>, Lang); ?NS_ADMINL(<<"get-user-password">>) -> ?INFO_COMMAND(<<"Get User Password">>, Lang); ?NS_ADMINL(<<"change-user-password">>) -> ?INFO_COMMAND(<<"Change User Password">>, Lang); ?NS_ADMINL(<<"get-user-lastlogin">>) -> ?INFO_COMMAND(<<"Get User Last Login Time">>, Lang); ?NS_ADMINL(<<"user-stats">>) -> ?INFO_COMMAND(<<"Get User Statistics">>, Lang); ?NS_ADMINL(<<"get-registered-users-num">>) -> ?INFO_COMMAND(<<"Get Number of Registered Users">>, Lang); ?NS_ADMINL(<<"get-online-users-num">>) -> ?INFO_COMMAND(<<"Get Number of Online Users">>, Lang); [<<"config">>, <<"acls">>] -> ?INFO_COMMAND(<<"Access Control Lists">>, Lang); [<<"config">>, <<"access">>] -> ?INFO_COMMAND(<<"Access Rules">>, Lang); _ -> Acc end. %%%----------------------------------------------------------------------- -define(INFO_RESULT(Allow, Feats), case Allow of deny -> {error, ?ERR_FORBIDDEN}; allow -> {result, Feats} end). get_sm_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> Allow = acl:match_rule(LServer, configure, From), case Node of <<"config">> -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); _ -> Acc end end. get_local_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> LNode = tokenize(Node), Allow = acl:match_rule(LServer, configure, From), case LNode of [<<"config">>] -> ?INFO_RESULT(Allow, []); [<<"user">>] -> ?INFO_RESULT(Allow, []); [<<"online users">>] -> ?INFO_RESULT(Allow, []); [<<"all users">>] -> ?INFO_RESULT(Allow, []); [<<"all users">>, <<$@, _/binary>>] -> ?INFO_RESULT(Allow, []); [<<"outgoing s2s">> | _] -> ?INFO_RESULT(Allow, []); [<<"running nodes">>] -> ?INFO_RESULT(Allow, []); [<<"stopped nodes">>] -> ?INFO_RESULT(Allow, []); [<<"running nodes">>, _ENode] -> ?INFO_RESULT(Allow, [?NS_STATS]); [<<"running nodes">>, _ENode, <<"DB">>] -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); [<<"running nodes">>, _ENode, <<"modules">>] -> ?INFO_RESULT(Allow, []); [<<"running nodes">>, _ENode, <<"modules">>, _] -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); [<<"running nodes">>, _ENode, <<"backup">>] -> ?INFO_RESULT(Allow, []); [<<"running nodes">>, _ENode, <<"backup">>, _] -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); [<<"running nodes">>, _ENode, <<"import">>] -> ?INFO_RESULT(Allow, []); [<<"running nodes">>, _ENode, <<"import">>, _] -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); [<<"running nodes">>, _ENode, <<"restart">>] -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); [<<"running nodes">>, _ENode, <<"shutdown">>] -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); [<<"config">>, _] -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"add-user">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"delete-user">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"end-user-session">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"get-user-password">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"change-user-password">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"get-user-lastlogin">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"user-stats">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"get-registered-users-num">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); ?NS_ADMINL(<<"get-online-users-num">>) -> ?INFO_RESULT(Allow, [?NS_COMMANDS]); _ -> Acc end end. %%%----------------------------------------------------------------------- adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To, Lang) -> case acl:match_rule(LServer, configure, From) of allow -> Items = case Acc of {result, Its} -> Its; empty -> [] end, Nodes = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string(To)}, {<<"name">>, ?T(Lang, <<"Configuration">>)}, {<<"node">>, <<"config">>}], children = []}], {result, Items ++ Nodes}; _ -> Acc end. %%%----------------------------------------------------------------------- get_sm_items(Acc, From, #jid{user = User, server = Server, lserver = LServer} = To, Node, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> Items = case Acc of {result, Its} -> Its; empty -> [] end, case {acl:match_rule(LServer, configure, From), Node} of {allow, <<"">>} -> Nodes = [?NODEJID(To, <<"Configuration">>, <<"config">>), ?NODEJID(To, <<"User Management">>, <<"user">>)], {result, Items ++ Nodes ++ get_user_resources(User, Server)}; {allow, <<"config">>} -> {result, []}; {_, <<"config">>} -> {error, ?ERR_FORBIDDEN}; _ -> Acc end end. get_user_resources(User, Server) -> Rs = ejabberd_sm:get_user_resources(User, Server), lists:map(fun (R) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, <>}, {<<"name">>, User}], children = []} end, lists:sort(Rs)). %%%----------------------------------------------------------------------- adhoc_local_items(Acc, From, #jid{lserver = LServer, server = Server} = To, Lang) -> case acl:match_rule(LServer, configure, From) of allow -> Items = case Acc of {result, Its} -> Its; empty -> [] end, PermLev = get_permission_level(From), Nodes = recursively_get_local_items(PermLev, LServer, <<"">>, Server, Lang), Nodes1 = lists:filter(fun (N) -> Nd = xml:get_tag_attr_s(<<"node">>, N), F = get_local_features([], From, To, Nd, Lang), case F of {result, [?NS_COMMANDS]} -> true; _ -> false end end, Nodes), {result, Items ++ Nodes1}; _ -> Acc end. recursively_get_local_items(_PermLev, _LServer, <<"online users">>, _Server, _Lang) -> []; recursively_get_local_items(_PermLev, _LServer, <<"all users">>, _Server, _Lang) -> []; recursively_get_local_items(PermLev, LServer, Node, Server, Lang) -> LNode = tokenize(Node), Items = case get_local_items({PermLev, LServer}, LNode, Server, Lang) of {result, Res} -> Res; {error, _Error} -> [] end, Nodes = lists:flatten(lists:map(fun (N) -> S = xml:get_tag_attr_s(<<"jid">>, N), Nd = xml:get_tag_attr_s(<<"node">>, N), if (S /= Server) or (Nd == <<"">>) -> []; true -> [N, recursively_get_local_items(PermLev, LServer, Nd, Server, Lang)] end end, Items)), Nodes. get_permission_level(JID) -> case acl:match_rule(global, configure, JID) of allow -> global; deny -> vhost end. %%%----------------------------------------------------------------------- -define(ITEMS_RESULT(Allow, LNode, Fallback), case Allow of deny -> Fallback; allow -> PermLev = get_permission_level(From), case get_local_items({PermLev, LServer}, LNode, jid:to_string(To), Lang) of {result, Res} -> {result, Res}; {error, Error} -> {error, Error} end end). get_local_items(Acc, From, #jid{lserver = LServer} = To, <<"">>, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> Items = case Acc of {result, Its} -> Its; empty -> [] end, Allow = acl:match_rule(LServer, configure, From), case Allow of deny -> {result, Items}; allow -> PermLev = get_permission_level(From), case get_local_items({PermLev, LServer}, [], jid:to_string(To), Lang) of {result, Res} -> {result, Items ++ Res}; {error, _Error} -> {result, Items} end end end; get_local_items(Acc, From, #jid{lserver = LServer} = To, Node, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of false -> Acc; _ -> LNode = tokenize(Node), Allow = acl:match_rule(LServer, configure, From), case LNode of [<<"config">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"user">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"online users">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"all users">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"all users">>, <<$@, _/binary>>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"outgoing s2s">> | _] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"stopped nodes">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"DB">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"modules">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"modules">>, _] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"backup">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"backup">>, _] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"import">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"import">>, _] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"restart">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"running nodes">>, _ENode, <<"shutdown">>] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); [<<"config">>, _] -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"add-user">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"delete-user">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"end-user-session">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"get-user-password">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"change-user-password">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"get-user-lastlogin">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"user-stats">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"get-registered-users-num">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); ?NS_ADMINL(<<"get-online-users-num">>) -> ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN}); _ -> Acc end end. %%%----------------------------------------------------------------------- %% @spec ({PermissionLevel, Host}, [string()], Server::string(), Lang) %% -> {result, [xmlelement()]} %% PermissionLevel = global | vhost get_local_items(_Host, [], Server, Lang) -> {result, [?NODE(<<"Configuration">>, <<"config">>), ?NODE(<<"User Management">>, <<"user">>), ?NODE(<<"Online Users">>, <<"online users">>), ?NODE(<<"All Users">>, <<"all users">>), ?NODE(<<"Outgoing s2s Connections">>, <<"outgoing s2s">>), ?NODE(<<"Running Nodes">>, <<"running nodes">>), ?NODE(<<"Stopped Nodes">>, <<"stopped nodes">>)]}; get_local_items(_Host, [<<"config">>], Server, Lang) -> {result, [?NODE(<<"Access Control Lists">>, <<"config/acls">>), ?NODE(<<"Access Rules">>, <<"config/access">>)]}; get_local_items(_Host, [<<"config">>, _], _Server, _Lang) -> {result, []}; get_local_items(_Host, [<<"user">>], Server, Lang) -> {result, [?NODE(<<"Add User">>, (?NS_ADMINX(<<"add-user">>))), ?NODE(<<"Delete User">>, (?NS_ADMINX(<<"delete-user">>))), ?NODE(<<"End User Session">>, (?NS_ADMINX(<<"end-user-session">>))), ?NODE(<<"Get User Password">>, (?NS_ADMINX(<<"get-user-password">>))), ?NODE(<<"Change User Password">>, (?NS_ADMINX(<<"change-user-password">>))), ?NODE(<<"Get User Last Login Time">>, (?NS_ADMINX(<<"get-user-lastlogin">>))), ?NODE(<<"Get User Statistics">>, (?NS_ADMINX(<<"user-stats">>))), ?NODE(<<"Get Number of Registered Users">>, (?NS_ADMINX(<<"get-registered-users-num">>))), ?NODE(<<"Get Number of Online Users">>, (?NS_ADMINX(<<"get-online-users-num">>)))]}; get_local_items(_Host, [<<"http:">> | _], _Server, _Lang) -> {result, []}; get_local_items({_, Host}, [<<"online users">>], _Server, _Lang) -> {result, get_online_vh_users(Host)}; get_local_items({_, Host}, [<<"all users">>], _Server, _Lang) -> {result, get_all_vh_users(Host)}; get_local_items({_, Host}, [<<"all users">>, <<$@, Diap/binary>>], _Server, _Lang) -> case catch ejabberd_auth:get_vh_registered_users(Host) of {'EXIT', _Reason} -> ?ERR_INTERNAL_SERVER_ERROR; Users -> SUsers = lists:sort([{S, U} || {U, S} <- Users]), case catch begin [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>), N1 = jlib:binary_to_integer(S1), N2 = jlib:binary_to_integer(S2), Sub = lists:sublist(SUsers, N1, N2 - N1 + 1), lists:map(fun ({S, U}) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, <>}, {<<"name">>, <>}], children = []} end, Sub) end of {'EXIT', _Reason} -> ?ERR_NOT_ACCEPTABLE; Res -> {result, Res} end end; get_local_items({_, Host}, [<<"outgoing s2s">>], _Server, Lang) -> {result, get_outgoing_s2s(Host, Lang)}; get_local_items({_, Host}, [<<"outgoing s2s">>, To], _Server, Lang) -> {result, get_outgoing_s2s(Host, Lang, To)}; get_local_items(_Host, [<<"running nodes">>], Server, Lang) -> {result, get_running_nodes(Server, Lang)}; get_local_items(_Host, [<<"stopped nodes">>], _Server, Lang) -> {result, get_stopped_nodes(Lang)}; get_local_items({global, _Host}, [<<"running nodes">>, ENode], Server, Lang) -> {result, [?NODE(<<"Database">>, <<"running nodes/", ENode/binary, "/DB">>), ?NODE(<<"Modules">>, <<"running nodes/", ENode/binary, "/modules">>), ?NODE(<<"Backup Management">>, <<"running nodes/", ENode/binary, "/backup">>), ?NODE(<<"Import Users From jabberd14 Spool Files">>, <<"running nodes/", ENode/binary, "/import">>), ?NODE(<<"Restart Service">>, <<"running nodes/", ENode/binary, "/restart">>), ?NODE(<<"Shut Down Service">>, <<"running nodes/", ENode/binary, "/shutdown">>)]}; get_local_items({vhost, _Host}, [<<"running nodes">>, ENode], Server, Lang) -> {result, [?NODE(<<"Modules">>, <<"running nodes/", ENode/binary, "/modules">>)]}; get_local_items(_Host, [<<"running nodes">>, _ENode, <<"DB">>], _Server, _Lang) -> {result, []}; get_local_items(_Host, [<<"running nodes">>, ENode, <<"modules">>], Server, Lang) -> {result, [?NODE(<<"Start Modules">>, <<"running nodes/", ENode/binary, "/modules/start">>), ?NODE(<<"Stop Modules">>, <<"running nodes/", ENode/binary, "/modules/stop">>)]}; get_local_items(_Host, [<<"running nodes">>, _ENode, <<"modules">>, _], _Server, _Lang) -> {result, []}; get_local_items(_Host, [<<"running nodes">>, ENode, <<"backup">>], Server, Lang) -> {result, [?NODE(<<"Backup">>, <<"running nodes/", ENode/binary, "/backup/backup">>), ?NODE(<<"Restore">>, <<"running nodes/", ENode/binary, "/backup/restore">>), ?NODE(<<"Dump to Text File">>, <<"running nodes/", ENode/binary, "/backup/textfile">>)]}; get_local_items(_Host, [<<"running nodes">>, _ENode, <<"backup">>, _], _Server, _Lang) -> {result, []}; get_local_items(_Host, [<<"running nodes">>, ENode, <<"import">>], Server, Lang) -> {result, [?NODE(<<"Import File">>, <<"running nodes/", ENode/binary, "/import/file">>), ?NODE(<<"Import Directory">>, <<"running nodes/", ENode/binary, "/import/dir">>)]}; get_local_items(_Host, [<<"running nodes">>, _ENode, <<"import">>, _], _Server, _Lang) -> {result, []}; get_local_items(_Host, [<<"running nodes">>, _ENode, <<"restart">>], _Server, _Lang) -> {result, []}; get_local_items(_Host, [<<"running nodes">>, _ENode, <<"shutdown">>], _Server, _Lang) -> {result, []}; get_local_items(_Host, _, _Server, _Lang) -> {error, ?ERR_ITEM_NOT_FOUND}. get_online_vh_users(Host) -> case catch ejabberd_sm:get_vh_session_list(Host) of {'EXIT', _Reason} -> []; USRs -> SURs = lists:sort([{S, U, R} || {U, S, R} <- USRs]), lists:map(fun ({S, U, R}) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, <>}, {<<"name">>, <>}], children = []} end, SURs) end. get_all_vh_users(Host) -> case catch ejabberd_auth:get_vh_registered_users(Host) of {'EXIT', _Reason} -> []; Users -> SUsers = lists:sort([{S, U} || {U, S} <- Users]), case length(SUsers) of N when N =< 100 -> lists:map(fun ({S, U}) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, <>}, {<<"name">>, <>}], children = []} end, SUsers); N -> NParts = trunc(math:sqrt(N * 6.17999999999999993783e-1)) + 1, M = trunc(N / NParts) + 1, lists:map(fun (K) -> L = K + M - 1, Node = <<"@", (iolist_to_binary(integer_to_list(K)))/binary, "-", (iolist_to_binary(integer_to_list(L)))/binary>>, {FS, FU} = lists:nth(K, SUsers), {LS, LU} = if L < N -> lists:nth(L, SUsers); true -> lists:last(SUsers) end, Name = <>, #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Host}, {<<"node">>, <<"all users/", Node/binary>>}, {<<"name">>, Name}], children = []} end, lists:seq(1, N, M)) end end. get_outgoing_s2s(Host, Lang) -> case catch ejabberd_s2s:dirty_get_connections() of {'EXIT', _Reason} -> []; Connections -> DotHost = <<".", Host/binary>>, TConns = [TH || {FH, TH} <- Connections, Host == FH orelse str:suffix(DotHost, FH)], lists:map(fun (T) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Host}, {<<"node">>, <<"outgoing s2s/", T/binary>>}, {<<"name">>, iolist_to_binary(io_lib:format(?T(Lang, <<"To ~s">>), [T]))}], children = []} end, lists:usort(TConns)) end. get_outgoing_s2s(Host, Lang, To) -> case catch ejabberd_s2s:dirty_get_connections() of {'EXIT', _Reason} -> []; Connections -> lists:map(fun ({F, _T}) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Host}, {<<"node">>, <<"outgoing s2s/", To/binary, "/", F/binary>>}, {<<"name">>, iolist_to_binary(io_lib:format(?T(Lang, <<"From ~s">>), [F]))}], children = []} end, lists:keysort(1, lists:filter(fun (E) -> element(2, E) == To end, Connections))) end. get_running_nodes(Server, _Lang) -> case catch mnesia:system_info(running_db_nodes) of {'EXIT', _Reason} -> []; DBNodes -> lists:map(fun (N) -> S = iolist_to_binary(atom_to_list(N)), #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Server}, {<<"node">>, <<"running nodes/", S/binary>>}, {<<"name">>, S}], children = []} end, lists:sort(DBNodes)) end. get_stopped_nodes(_Lang) -> case catch lists:usort(mnesia:system_info(db_nodes) ++ mnesia:system_info(extra_db_nodes)) -- mnesia:system_info(running_db_nodes) of {'EXIT', _Reason} -> []; DBNodes -> lists:map(fun (N) -> S = iolist_to_binary(atom_to_list(N)), #xmlel{name = <<"item">>, attrs = [{<<"jid">>, ?MYNAME}, {<<"node">>, <<"stopped nodes/", S/binary>>}, {<<"name">>, S}], children = []} end, lists:sort(DBNodes)) end. %%------------------------------------------------------------------------- -define(COMMANDS_RESULT(LServerOrGlobal, From, To, Request), case acl:match_rule(LServerOrGlobal, configure, From) of deny -> {error, ?ERR_FORBIDDEN}; allow -> adhoc_local_commands(From, To, Request) end). adhoc_local_commands(Acc, From, #jid{lserver = LServer} = To, #adhoc_request{node = Node} = Request) -> LNode = tokenize(Node), case LNode of [<<"running nodes">>, _ENode, <<"DB">>] -> ?COMMANDS_RESULT(global, From, To, Request); [<<"running nodes">>, _ENode, <<"modules">>, _] -> ?COMMANDS_RESULT(LServer, From, To, Request); [<<"running nodes">>, _ENode, <<"backup">>, _] -> ?COMMANDS_RESULT(global, From, To, Request); [<<"running nodes">>, _ENode, <<"import">>, _] -> ?COMMANDS_RESULT(global, From, To, Request); [<<"running nodes">>, _ENode, <<"restart">>] -> ?COMMANDS_RESULT(global, From, To, Request); [<<"running nodes">>, _ENode, <<"shutdown">>] -> ?COMMANDS_RESULT(global, From, To, Request); [<<"config">>, _] -> ?COMMANDS_RESULT(LServer, From, To, Request); ?NS_ADMINL(_) -> ?COMMANDS_RESULT(LServer, From, To, Request); _ -> Acc end. adhoc_local_commands(From, #jid{lserver = LServer} = _To, #adhoc_request{lang = Lang, node = Node, sessionid = SessionID, action = Action, xdata = XData} = Request) -> LNode = tokenize(Node), ActionIsExecute = lists:member(Action, [<<"">>, <<"execute">>, <<"complete">>]), if Action == <<"cancel">> -> adhoc:produce_response(Request, #adhoc_response{status = canceled}); XData == false, ActionIsExecute -> case get_form(LServer, LNode, Lang) of {result, Form} -> adhoc:produce_response(Request, #adhoc_response{status = executing, elements = Form}); {result, Status, Form} -> adhoc:produce_response(Request, #adhoc_response{status = Status, elements = Form}); {error, Error} -> {error, Error} end; XData /= false, ActionIsExecute -> case jlib:parse_xdata_submit(XData) of invalid -> {error, ?ERR_BAD_REQUEST}; Fields -> case catch set_form(From, LServer, LNode, Lang, Fields) of {result, Res} -> adhoc:produce_response(#adhoc_response{lang = Lang, node = Node, sessionid = SessionID, elements = Res, status = completed}); {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; {error, Error} -> {error, Error} end end; true -> {error, ?ERR_BAD_REQUEST} end. -define(TVFIELD(Type, Var, Val), #xmlel{name = <<"field">>, attrs = [{<<"type">>, Type}, {<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Val}]}]}). -define(HFIELD(), ?TVFIELD(<<"hidden">>, <<"FORM_TYPE">>, (?NS_ADMIN))). -define(TLFIELD(Type, Label, Var), #xmlel{name = <<"field">>, attrs = [{<<"type">>, Type}, {<<"label">>, ?T(Lang, Label)}, {<<"var">>, Var}], children = []}). -define(XFIELD(Type, Label, Var, Val), #xmlel{name = <<"field">>, attrs = [{<<"type">>, Type}, {<<"label">>, ?T(Lang, Label)}, {<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Val}]}]}). -define(XMFIELD(Type, Label, Var, Vals), #xmlel{name = <<"field">>, attrs = [{<<"type">>, Type}, {<<"label">>, ?T(Lang, Label)}, {<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Val}]} || Val <- Vals]}). -define(TABLEFIELD(Table, Val), #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"list-single">>}, {<<"label">>, iolist_to_binary(atom_to_list(Table))}, {<<"var">>, iolist_to_binary(atom_to_list(Table))}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, iolist_to_binary(atom_to_list(Val))}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, ?T(Lang, <<"RAM copy">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"ram_copies">>}]}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, ?T(Lang, <<"RAM and disc copy">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"disc_copies">>}]}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, ?T(Lang, <<"Disc only copy">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"disc_only_copies">>}]}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, ?T(Lang, <<"Remote copy">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"unknown">>}]}]}]}). get_form(_Host, [<<"running nodes">>, ENode, <<"DB">>], Lang) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> case ejabberd_cluster:call(Node, mnesia, system_info, [tables]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; Tables -> STables = lists:sort(Tables), {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Database Tables Configuration at ">>))/binary, ENode/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Choose storage type of tables">>)}]} | lists:map(fun (Table) -> case ejabberd_cluster:call(Node, mnesia, table_info, [Table, storage_type]) of {badrpc, _} -> ?TABLEFIELD(Table, unknown); Type -> ?TABLEFIELD(Table, Type) end end, STables)]}]} end end; get_form(Host, [<<"running nodes">>, ENode, <<"modules">>, <<"stop">>], Lang) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> case ejabberd_cluster:call(Node, gen_mod, loaded_modules, [Host]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; Modules -> SModules = lists:sort(Modules), {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Stop Modules at ">>))/binary, ENode/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Choose modules to stop">>)}]} | lists:map(fun (M) -> S = jlib:atom_to_binary(M), ?XFIELD(<<"boolean">>, S, S, <<"0">>) end, SModules)]}]} end end; get_form(_Host, [<<"running nodes">>, ENode, <<"modules">>, <<"start">>], Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Start Modules at ">>))/binary, ENode/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Enter list of {Module, [Options]}">>)}]}, ?XFIELD(<<"text-multi">>, <<"List of modules to start">>, <<"modules">>, <<"[].">>)]}]}; get_form(_Host, [<<"running nodes">>, ENode, <<"backup">>, <<"backup">>], Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Backup to File at ">>))/binary, ENode/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Enter path to backup file">>)}]}, ?XFIELD(<<"text-single">>, <<"Path to File">>, <<"path">>, <<"">>)]}]}; get_form(_Host, [<<"running nodes">>, ENode, <<"backup">>, <<"restore">>], Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Restore Backup from File at ">>))/binary, ENode/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Enter path to backup file">>)}]}, ?XFIELD(<<"text-single">>, <<"Path to File">>, <<"path">>, <<"">>)]}]}; get_form(_Host, [<<"running nodes">>, ENode, <<"backup">>, <<"textfile">>], Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Dump Backup to Text File at ">>))/binary, ENode/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Enter path to text file">>)}]}, ?XFIELD(<<"text-single">>, <<"Path to File">>, <<"path">>, <<"">>)]}]}; get_form(_Host, [<<"running nodes">>, ENode, <<"import">>, <<"file">>], Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Import User from File at ">>))/binary, ENode/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Enter path to jabberd14 spool file">>)}]}, ?XFIELD(<<"text-single">>, <<"Path to File">>, <<"path">>, <<"">>)]}]}; get_form(_Host, [<<"running nodes">>, ENode, <<"import">>, <<"dir">>], Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Import Users from Dir at ">>))/binary, ENode/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Enter path to jabberd14 spool dir">>)}]}, ?XFIELD(<<"text-single">>, <<"Path to Dir">>, <<"path">>, <<"">>)]}]}; get_form(_Host, [<<"running nodes">>, _ENode, <<"restart">>], Lang) -> Make_option = fun (LabelNum, LabelUnit, Value) -> #xmlel{name = <<"option">>, attrs = [{<<"label">>, <>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Value}]}]} end, {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Restart Service">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"list-single">>}, {<<"label">>, ?T(Lang, <<"Time delay">>)}, {<<"var">>, <<"delay">>}], children = [Make_option(<<"">>, <<"immediately">>, <<"1">>), Make_option(<<"15 ">>, <<"seconds">>, <<"15">>), Make_option(<<"30 ">>, <<"seconds">>, <<"30">>), Make_option(<<"60 ">>, <<"seconds">>, <<"60">>), Make_option(<<"90 ">>, <<"seconds">>, <<"90">>), Make_option(<<"2 ">>, <<"minutes">>, <<"120">>), Make_option(<<"3 ">>, <<"minutes">>, <<"180">>), Make_option(<<"4 ">>, <<"minutes">>, <<"240">>), Make_option(<<"5 ">>, <<"minutes">>, <<"300">>), Make_option(<<"10 ">>, <<"minutes">>, <<"600">>), Make_option(<<"15 ">>, <<"minutes">>, <<"900">>), Make_option(<<"30 ">>, <<"minutes">>, <<"1800">>), #xmlel{name = <<"required">>, attrs = [], children = []}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"fixed">>}, {<<"label">>, ?T(Lang, <<"Send announcement to all online users " "on all hosts">>)}], children = []}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"subject">>}, {<<"type">>, <<"text-single">>}, {<<"label">>, ?T(Lang, <<"Subject">>)}], children = []}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"announcement">>}, {<<"type">>, <<"text-multi">>}, {<<"label">>, ?T(Lang, <<"Message body">>)}], children = []}]}]}; get_form(_Host, [<<"running nodes">>, _ENode, <<"shutdown">>], Lang) -> Make_option = fun (LabelNum, LabelUnit, Value) -> #xmlel{name = <<"option">>, attrs = [{<<"label">>, <>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Value}]}]} end, {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Shut Down Service">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"list-single">>}, {<<"label">>, ?T(Lang, <<"Time delay">>)}, {<<"var">>, <<"delay">>}], children = [Make_option(<<"">>, <<"immediately">>, <<"1">>), Make_option(<<"15 ">>, <<"seconds">>, <<"15">>), Make_option(<<"30 ">>, <<"seconds">>, <<"30">>), Make_option(<<"60 ">>, <<"seconds">>, <<"60">>), Make_option(<<"90 ">>, <<"seconds">>, <<"90">>), Make_option(<<"2 ">>, <<"minutes">>, <<"120">>), Make_option(<<"3 ">>, <<"minutes">>, <<"180">>), Make_option(<<"4 ">>, <<"minutes">>, <<"240">>), Make_option(<<"5 ">>, <<"minutes">>, <<"300">>), Make_option(<<"10 ">>, <<"minutes">>, <<"600">>), Make_option(<<"15 ">>, <<"minutes">>, <<"900">>), Make_option(<<"30 ">>, <<"minutes">>, <<"1800">>), #xmlel{name = <<"required">>, attrs = [], children = []}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"fixed">>}, {<<"label">>, ?T(Lang, <<"Send announcement to all online users " "on all hosts">>)}], children = []}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"subject">>}, {<<"type">>, <<"text-single">>}, {<<"label">>, ?T(Lang, <<"Subject">>)}], children = []}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"announcement">>}, {<<"type">>, <<"text-multi">>}, {<<"label">>, ?T(Lang, <<"Message body">>)}], children = []}]}]}; get_form(Host, [<<"config">>, <<"acls">>], Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Access Control List Configuration">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-multi">>}, {<<"label">>, ?T(Lang, <<"Access control lists">>)}, {<<"var">>, <<"acls">>}], children = lists:map(fun (S) -> #xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, S}]} end, str:tokens(iolist_to_binary(io_lib:format("~p.", [ets:select(acl, [{{acl, {'$1', '$2'}, '$3'}, [{'==', '$2', Host}], [{{acl, '$1', '$3'}}]}])])), <<"\n">>))}]}]}; get_form(Host, [<<"config">>, <<"access">>], Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Access Configuration">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-multi">>}, {<<"label">>, ?T(Lang, <<"Access rules">>)}, {<<"var">>, <<"access">>}], children = lists:map(fun (S) -> #xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, S}]} end, str:tokens(iolist_to_binary(io_lib:format("~p.", [ets:select(local_config, [{{local_config, {access, '$1', '$2'}, '$3'}, [{'==', '$2', Host}], [{{access, '$1', '$3'}}]}])])), <<"\n">>))}]}]}; get_form(_Host, ?NS_ADMINL(<<"add-user">>), Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Add User">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"jid-single">>}, {<<"label">>, ?T(Lang, <<"Jabber ID">>)}, {<<"var">>, <<"accountjid">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-private">>}, {<<"label">>, ?T(Lang, <<"Password">>)}, {<<"var">>, <<"password">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-private">>}, {<<"label">>, ?T(Lang, <<"Password Verification">>)}, {<<"var">>, <<"password-verify">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}]}]}; get_form(_Host, ?NS_ADMINL(<<"delete-user">>), Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Delete User">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"jid-multi">>}, {<<"label">>, ?T(Lang, <<"Jabber ID">>)}, {<<"var">>, <<"accountjids">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}]}]}; get_form(_Host, ?NS_ADMINL(<<"end-user-session">>), Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"End User Session">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"jid-single">>}, {<<"label">>, ?T(Lang, <<"Jabber ID">>)}, {<<"var">>, <<"accountjid">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}]}]}; get_form(_Host, ?NS_ADMINL(<<"get-user-password">>), Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Get User Password">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"jid-single">>}, {<<"label">>, ?T(Lang, <<"Jabber ID">>)}, {<<"var">>, <<"accountjid">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}]}]}; get_form(_Host, ?NS_ADMINL(<<"change-user-password">>), Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Get User Password">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"jid-single">>}, {<<"label">>, ?T(Lang, <<"Jabber ID">>)}, {<<"var">>, <<"accountjid">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-private">>}, {<<"label">>, ?T(Lang, <<"Password">>)}, {<<"var">>, <<"password">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}]}]}; get_form(_Host, ?NS_ADMINL(<<"get-user-lastlogin">>), Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Get User Last Login Time">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"jid-single">>}, {<<"label">>, ?T(Lang, <<"Jabber ID">>)}, {<<"var">>, <<"accountjid">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}]}]}; get_form(_Host, ?NS_ADMINL(<<"user-stats">>), Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, ?T(Lang, <<"Get User Statistics">>)}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"jid-single">>}, {<<"label">>, ?T(Lang, <<"Jabber ID">>)}, {<<"var">>, <<"accountjid">>}], children = [#xmlel{name = <<"required">>, attrs = [], children = []}]}]}]}; get_form(Host, ?NS_ADMINL(<<"get-registered-users-num">>), Lang) -> Num = list_to_binary( io_lib:format("~p", [ejabberd_auth:get_vh_registered_users_number(Host)])), {result, completed, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-single">>}, {<<"label">>, ?T(Lang, <<"Number of registered users">>)}, {<<"var">>, <<"registeredusersnum">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Num}]}]}]}]}; get_form(Host, ?NS_ADMINL(<<"get-online-users-num">>), Lang) -> Num = list_to_binary( io_lib:format("~p", [length(ejabberd_sm:get_vh_session_list(Host))])), {result, completed, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"text-single">>}, {<<"label">>, ?T(Lang, <<"Number of online users">>)}, {<<"var">>, <<"onlineusersnum">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Num}]}]}]}]}; get_form(_Host, _, _Lang) -> {error, ?ERR_SERVICE_UNAVAILABLE}. set_form(_From, _Host, [<<"running nodes">>, ENode, <<"DB">>], _Lang, XData) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> lists:foreach(fun ({SVar, SVals}) -> Table = jlib:binary_to_atom(SVar), Type = case SVals of [<<"unknown">>] -> unknown; [<<"ram_copies">>] -> ram_copies; [<<"disc_copies">>] -> disc_copies; [<<"disc_only_copies">>] -> disc_only_copies; _ -> false end, if Type == false -> ok; Type == unknown -> mnesia:del_table_copy(Table, Node); true -> case mnesia:add_table_copy(Table, Node, Type) of {aborted, _} -> mnesia:change_table_copy_type(Table, Node, Type); _ -> ok end end end, XData), {result, []} end; set_form(_From, Host, [<<"running nodes">>, ENode, <<"modules">>, <<"stop">>], _Lang, XData) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> lists:foreach(fun ({Var, Vals}) -> case Vals of [<<"1">>] -> Module = jlib:binary_to_atom(Var), ejabberd_cluster:call(Node, gen_mod, stop_module, [Host, Module]); _ -> ok end end, XData), {result, []} end; set_form(_From, Host, [<<"running nodes">>, ENode, <<"modules">>, <<"start">>], _Lang, XData) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> case lists:keysearch(<<"modules">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, Strings}} -> String = lists:foldl(fun (S, Res) -> <> end, <<"">>, Strings), case erl_scan:string(binary_to_list(String)) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens) of {ok, Modules} -> lists:foreach(fun ({Module, Args}) -> ejabberd_cluster:call(Node, gen_mod, start_module, [Host, Module, Args]) end, Modules), {result, []}; _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"backup">>, <<"backup">>], _Lang, XData) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> case ejabberd_cluster:call(Node, mnesia, backup, [String]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; {error, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; _ -> {result, []} end; _ -> {error, ?ERR_BAD_REQUEST} end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"backup">>, <<"restore">>], _Lang, XData) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> case ejabberd_cluster:call(Node, ejabberd_admin, restore, [String]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; {error, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; _ -> {result, []} end; _ -> {error, ?ERR_BAD_REQUEST} end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"backup">>, <<"textfile">>], _Lang, XData) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> case ejabberd_cluster:call(Node, ejabberd_admin, dump_to_textfile, [String]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; {error, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; _ -> {result, []} end; _ -> {error, ?ERR_BAD_REQUEST} end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"import">>, <<"file">>], _Lang, XData) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> ejabberd_cluster:call(Node, jd2ejd, import_file, [String]), {result, []}; _ -> {error, ?ERR_BAD_REQUEST} end end; set_form(_From, _Host, [<<"running nodes">>, ENode, <<"import">>, <<"dir">>], _Lang, XData) -> case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> ejabberd_cluster:call(Node, jd2ejd, import_dir, [String]), {result, []}; _ -> {error, ?ERR_BAD_REQUEST} end end; set_form(From, Host, [<<"running nodes">>, ENode, <<"restart">>], _Lang, XData) -> stop_node(From, Host, ENode, restart, XData); set_form(From, Host, [<<"running nodes">>, ENode, <<"shutdown">>], _Lang, XData) -> stop_node(From, Host, ENode, stop, XData); set_form(_From, Host, [<<"config">>, <<"acls">>], _Lang, XData) -> case lists:keysearch(<<"acls">>, 1, XData) of {value, {_, Strings}} -> String = lists:foldl(fun (S, Res) -> <> end, <<"">>, Strings), case erl_scan:string(binary_to_list(String)) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens) of {ok, ACLs} -> acl:add_list(Host, ACLs, true), {result, []}; _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end; set_form(_From, Host, [<<"config">>, <<"access">>], _Lang, XData) -> SetAccess = fun (Rs) -> mnesia:transaction(fun () -> Os = mnesia:select(local_config, [{{local_config, {access, '$1', '$2'}, '$3'}, [{'==', '$2', Host}], ['$_']}]), lists:foreach(fun (O) -> mnesia:delete_object(O) end, Os), lists:foreach(fun ({access, Name, Rules}) -> mnesia:write({local_config, {access, Name, Host}, Rules}) end, Rs) end) end, case lists:keysearch(<<"access">>, 1, XData) of {value, {_, Strings}} -> String = lists:foldl(fun (S, Res) -> <> end, <<"">>, Strings), case erl_scan:string(binary_to_list(String)) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens) of {ok, Rs} -> case SetAccess(Rs) of {atomic, _} -> {result, []}; _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end; _ -> {error, ?ERR_BAD_REQUEST} end; set_form(From, Host, ?NS_ADMINL(<<"add-user">>), _Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), Password = get_value(<<"password">>, XData), Password = get_value(<<"password-verify">>, XData), AccountJID = jid:from_string(AccountString), User = AccountJID#jid.luser, Server = AccountJID#jid.lserver, true = lists:member(Server, ?MYHOSTS), true = Server == Host orelse get_permission_level(From) == global, ejabberd_auth:try_register(User, Server, Password), {result, []}; set_form(From, Host, ?NS_ADMINL(<<"delete-user">>), _Lang, XData) -> AccountStringList = get_values(<<"accountjids">>, XData), [_ | _] = AccountStringList, ASL2 = lists:map(fun (AccountString) -> JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse get_permission_level(From) == global, true = ejabberd_auth:is_user_exists(User, Server), {User, Server} end, AccountStringList), [ejabberd_auth:remove_user(User, Server) || {User, Server} <- ASL2], {result, []}; set_form(From, Host, ?NS_ADMINL(<<"end-user-session">>), Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), JID = jid:from_string(AccountString), LUser = JID#jid.luser, LServer = JID#jid.lserver, true = LServer == Host orelse get_permission_level(From) == global, Xmlelement = ?SERRT_POLICY_VIOLATION(Lang, <<"has been kicked">>), case JID#jid.lresource of <<>> -> SIDs = mnesia:dirty_select(session, [{#session{sid = '$1', usr = {LUser, LServer, '_'}, _ = '_'}, [], ['$1']}]), [Pid ! {kick, kicked_by_admin, Xmlelement} || {_, Pid} <- SIDs]; R -> [{_, Pid}] = mnesia:dirty_select(session, [{#session{sid = '$1', usr = {LUser, LServer, R}, _ = '_'}, [], ['$1']}]), Pid ! {kick, kicked_by_admin, Xmlelement} end, {result, []}; set_form(From, Host, ?NS_ADMINL(<<"get-user-password">>), Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse get_permission_level(From) == global, Password = ejabberd_auth:get_password(User, Server), true = is_binary(Password), {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), ?XFIELD(<<"jid-single">>, <<"Jabber ID">>, <<"accountjid">>, AccountString), ?XFIELD(<<"text-single">>, <<"Password">>, <<"password">>, Password)]}]}; set_form(From, Host, ?NS_ADMINL(<<"change-user-password">>), _Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), Password = get_value(<<"password">>, XData), JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse get_permission_level(From) == global, true = ejabberd_auth:is_user_exists(User, Server), ejabberd_auth:set_password(User, Server, Password), {result, []}; set_form(From, Host, ?NS_ADMINL(<<"get-user-lastlogin">>), Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse get_permission_level(From) == global, FLast = case ejabberd_sm:get_user_resources(User, Server) of [] -> case get_last_info(User, Server) of not_found -> ?T(Lang, <<"Never">>); {ok, Timestamp, _Status} -> Shift = Timestamp, TimeStamp = {Shift div 1000000, Shift rem 1000000, 0}, {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:now_to_local_time(TimeStamp), iolist_to_binary(io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w", [Year, Month, Day, Hour, Minute, Second])) end; _ -> ?T(Lang, <<"Online">>) end, {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}], children = [?HFIELD(), ?XFIELD(<<"jid-single">>, <<"Jabber ID">>, <<"accountjid">>, AccountString), ?XFIELD(<<"text-single">>, <<"Last login">>, <<"lastlogin">>, FLast)]}]}; set_form(From, Host, ?NS_ADMINL(<<"user-stats">>), Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse get_permission_level(From) == global, Resources = ejabberd_sm:get_user_resources(User, Server), IPs1 = [ejabberd_sm:get_user_ip(User, Server, Resource) || Resource <- Resources], IPs = [<<(jlib:ip_to_list(IP))/binary, ":", (jlib:integer_to_binary(Port))/binary>> || {IP, Port} <- IPs1], Items = ejabberd_hooks:run_fold(roster_get, Server, [], [{User, Server}]), Rostersize = jlib:integer_to_binary(erlang:length(Items)), {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), ?XFIELD(<<"jid-single">>, <<"Jabber ID">>, <<"accountjid">>, AccountString), ?XFIELD(<<"text-single">>, <<"Roster size">>, <<"rostersize">>, Rostersize), ?XMFIELD(<<"text-multi">>, <<"IP addresses">>, <<"ipaddresses">>, IPs), ?XMFIELD(<<"text-multi">>, <<"Resources">>, <<"onlineresources">>, Resources)]}]}; set_form(_From, _Host, _, _Lang, _XData) -> {error, ?ERR_SERVICE_UNAVAILABLE}. get_value(Field, XData) -> hd(get_values(Field, XData)). get_values(Field, XData) -> {value, {_, ValueList}} = lists:keysearch(Field, 1, XData), ValueList. search_running_node(SNode) -> search_running_node(SNode, mnesia:system_info(running_db_nodes)). search_running_node(_, []) -> false; search_running_node(SNode, [Node | Nodes]) -> case iolist_to_binary(atom_to_list(Node)) of SNode -> Node; _ -> search_running_node(SNode, Nodes) end. stop_node(From, Host, ENode, Action, XData) -> Delay = jlib:binary_to_integer(get_value(<<"delay">>, XData)), Subject = case get_value(<<"subject">>, XData) of <<"">> -> []; S -> [#xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"subject">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, S}]}]}] end, Announcement = case get_values(<<"announcement">>, XData) of [] -> []; As -> [#xmlel{name = <<"field">>, attrs = [{<<"var">>, <<"body">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, Line}]} || Line <- As]}] end, case Subject ++ Announcement of [] -> ok; SubEls -> Request = #adhoc_request{node = ?NS_ADMINX(<<"announce-allhosts">>), action = <<"complete">>, xdata = #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"submit">>}], children = SubEls}, others = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"submit">>}], children = SubEls}]}, To = jid:make(<<"">>, Host, <<"">>), mod_announce:announce_commands(empty, From, To, Request) end, Time = timer:seconds(Delay), Node = jlib:binary_to_atom(ENode), {ok, _} = timer:apply_after(Time, rpc, call, [Node, init, Action, []]), {result, []}. get_last_info(User, Server) -> case gen_mod:is_loaded(Server, mod_last) of true -> mod_last:get_last_info(User, Server); false -> not_found end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% adhoc_sm_commands(_Acc, From, #jid{user = User, server = Server, lserver = LServer} = _To, #adhoc_request{lang = Lang, node = <<"config">>, action = Action, xdata = XData} = Request) -> case acl:match_rule(LServer, configure, From) of deny -> {error, ?ERR_FORBIDDEN}; allow -> ActionIsExecute = lists:member(Action, [<<"">>, <<"execute">>, <<"complete">>]), if Action == <<"cancel">> -> adhoc:produce_response(Request, #adhoc_response{status = canceled}); XData == false, ActionIsExecute -> case get_sm_form(User, Server, <<"config">>, Lang) of {result, Form} -> adhoc:produce_response(Request, #adhoc_response{status = executing, elements = Form}); {error, Error} -> {error, Error} end; XData /= false, ActionIsExecute -> case jlib:parse_xdata_submit(XData) of invalid -> {error, ?ERR_BAD_REQUEST}; Fields -> set_sm_form(User, Server, <<"config">>, Request, Fields) end; true -> {error, ?ERR_BAD_REQUEST} end end; adhoc_sm_commands(Acc, _From, _To, _Request) -> Acc. get_sm_form(User, Server, <<"config">>, Lang) -> {result, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = [?HFIELD(), #xmlel{name = <<"title">>, attrs = [], children = [{xmlcdata, <<(?T(Lang, <<"Administration of ">>))/binary, User/binary>>}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"list-single">>}, {<<"label">>, ?T(Lang, <<"Action on user">>)}, {<<"var">>, <<"action">>}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"edit">>}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, ?T(Lang, <<"Edit Properties">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"edit">>}]}]}, #xmlel{name = <<"option">>, attrs = [{<<"label">>, ?T(Lang, <<"Remove User">>)}], children = [#xmlel{name = <<"value">>, attrs = [], children = [{xmlcdata, <<"remove">>}]}]}]}, ?XFIELD(<<"text-private">>, <<"Password">>, <<"password">>, (ejabberd_auth:get_password_s(User, Server)))]}]}; get_sm_form(_User, _Server, _Node, _Lang) -> {error, ?ERR_SERVICE_UNAVAILABLE}. set_sm_form(User, Server, <<"config">>, #adhoc_request{lang = Lang, node = Node, sessionid = SessionID}, XData) -> Response = #adhoc_response{lang = Lang, node = Node, sessionid = SessionID, status = completed}, case lists:keysearch(<<"action">>, 1, XData) of {value, {_, [<<"edit">>]}} -> case lists:keysearch(<<"password">>, 1, XData) of {value, {_, [Password]}} -> ejabberd_auth:set_password(User, Server, Password), adhoc:produce_response(Response); _ -> {error, ?ERR_NOT_ACCEPTABLE} end; {value, {_, [<<"remove">>]}} -> catch ejabberd_auth:remove_user(User, Server), adhoc:produce_response(Response); _ -> {error, ?ERR_NOT_ACCEPTABLE} end; set_sm_form(_User, _Server, _Node, _Request, _Fields) -> {error, ?ERR_SERVICE_UNAVAILABLE}. mod_opt_type(_) -> []. ejabberd-16.01/src/shaper.erl0000644000232200023220000001052112645157216016412 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : shaper.erl %%% Author : Alexey Shchepin %%% Purpose : Functions to control connections traffic %%% Created : 9 Feb 2003 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(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, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -record(maxrate, {maxrate = 0 :: integer(), lastrate = 0.0 :: float(), lasttime = 0 :: integer()}). -record(shaper, {name :: {atom(), global}, maxrate :: integer()}). -type shaper() :: none | #maxrate{}. -export_type([shaper/0]). -spec start() -> ok. start() -> mnesia:create_table(shaper, [{ram_copies, [node()]}, {local_content, true}, {attributes, record_info(fields, shaper)}]), mnesia:add_table_copy(shaper, node(), ram_copies), load_from_config(), ok. -spec load_from_config() -> ok | {error, any()}. load_from_config() -> Shapers = ejabberd_config:get_option( shaper, fun(V) -> V end, []), case mnesia:transaction( fun() -> lists:foreach( fun({Name, MaxRate}) -> mnesia:write(#shaper{name = {Name, global}, maxrate = MaxRate}) end, Shapers) end) of {atomic, ok} -> ok; Err -> {error, Err} end. -spec get_max_rate(atom()) -> none | non_neg_integer(). get_max_rate(none) -> none; get_max_rate(Name) -> case ets:lookup(shaper, {Name, global}) of [#shaper{maxrate = R}] -> R; [] -> none end. -spec new(atom()) -> shaper(). new(none) -> none; new(Name) -> MaxRate = case ets:lookup(shaper, {Name, global}) of [#shaper{maxrate = R}] -> R; [] -> none end, new1(MaxRate). -spec new1(none | integer()) -> shaper(). new1(none) -> none; new1(MaxRate) -> #maxrate{maxrate = MaxRate, lastrate = 0.0, lasttime = p1_time_compat:system_time(micro_seconds)}. -spec update(shaper(), integer()) -> {shaper(), integer()}. update(none, _Size) -> {none, 0}; update(#maxrate{} = State, Size) -> MinInterv = 1000 * Size / (2 * State#maxrate.maxrate - State#maxrate.lastrate), 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]), Pause = if MinInterv > Interv -> 1 + trunc(MinInterv - Interv); true -> 0 end, NextNow = p1_time_compat:system_time(micro_seconds) + Pause * 1000, {State#maxrate{lastrate = (State#maxrate.lastrate + 1000000 * Size / (NextNow - State#maxrate.lasttime)) / 2, lasttime = NextNow}, Pause}. transform_options(Opts) -> lists:foldl(fun transform_options/2, [], Opts). transform_options({OptName, Name, {maxrate, N}}, Opts) when OptName == shaper -> [{shaper, [{Name, N}]}|Opts]; transform_options({OptName, Name, none}, Opts) when OptName == shaper -> [{shaper, [{Name, none}]}|Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. opt_type(shaper) -> fun (V) -> V end; opt_type(_) -> [shaper]. ejabberd-16.01/src/mod_http_upload_quota.erl0000644000232200023220000003045312645157216021531 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% 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'). -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), supervisor:terminate_child(ejabberd_sup, Proc), 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", [jid:to_string(JID)]), undefined; {0, _} -> ?WARNING_MSG("No hard quota specified for ~s", [jid:to_string(JID)]), enforce_quota(Path, Size, OldSize, SoftQuota, SoftQuota); {_, 0} -> ?WARNING_MSG("No soft quota specified for ~s", [jid:to_string(JID)]), enforce_quota(Path, Size, OldSize, HardQuota, HardQuota); _ when SoftQuota > HardQuota -> ?WARNING_MSG("Bad quota for ~s (soft: ~p, hard: ~p)", [jid:to_string(JID), SoftQuota, HardQuota]), enforce_quota(Path, Size, OldSize, SoftQuota, SoftQuota); _ -> ?DEBUG("Enforcing quota for ~s", [jid:to_string(JID)]), enforce_quota(Path, Size, OldSize, SoftQuota, HardQuota) end, 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}. -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, CutOff) -> FileInfo = gather_file_info(UserDir), 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()) -> [{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} -> ?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(). secs_since_epoch() -> {MegaSecs, Secs, _MicroSecs} = os:timestamp(), MegaSecs * 1000000 + Secs. ejabberd-16.01/src/ejabberd_router.erl0000644000232200023220000003122112645157216020266 0ustar debalancedebalance%%%---------------------------------------------------------------------- %%% File : ejabberd_router.erl %%% Author : Alexey Shchepin %%% Purpose : Main router %%% Created : 27 Nov 2002 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_router). -behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_server). %% API -export([route/3, route_error/4, register_route/1, register_route/2, register_routes/1, unregister_route/1, unregister_routes/1, dirty_get_all_routes/0, dirty_get_all_domains/0 ]). -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -type local_hint() :: undefined | integer() | {apply, atom(), atom()}. -record(route, {domain, pid, local_hint}). -record(state, {}). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). -spec route(jid(), jid(), xmlel()) -> ok. route(From, To, Packet) -> case catch do_route(From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p~nwhen processing: ~p", [Reason, {From, To, Packet}]); _ -> ok end. %% Route the error packet only if the originating packet is not an error itself. %% RFC3920 9.3.1 -spec route_error(jid(), jid(), xmlel(), xmlel()) -> ok. route_error(From, To, ErrPacket, OrigPacket) -> #xmlel{attrs = Attrs} = OrigPacket, case <<"error">> == xml:get_attr_s(<<"type">>, Attrs) of false -> route(From, To, ErrPacket); true -> ok end. -spec register_route(binary()) -> term(). register_route(Domain) -> register_route(Domain, undefined). -spec register_route(binary(), local_hint()) -> term(). register_route(Domain, LocalHint) -> case jid:nameprep(Domain) of error -> erlang:error({invalid_domain, Domain}); LDomain -> Pid = self(), case get_component_number(LDomain) of undefined -> F = fun () -> mnesia:write(#route{domain = LDomain, pid = Pid, local_hint = LocalHint}) end, mnesia:transaction(F); N -> F = fun () -> case mnesia:wread({route, LDomain}) of [] -> mnesia:write(#route{domain = LDomain, pid = Pid, local_hint = 1}), lists:foreach(fun (I) -> mnesia:write(#route{domain = LDomain, pid = undefined, 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) end end, mnesia:transaction(F) end end. -spec register_routes([binary()]) -> ok. register_routes(Domains) -> lists:foreach(fun (Domain) -> register_route(Domain) end, Domains). -spec unregister_route(binary()) -> term(). unregister_route(Domain) -> case jid:nameprep(Domain) of error -> erlang:error({invalid_domain, Domain}); LDomain -> Pid = self(), case get_component_number(LDomain) of undefined -> F = fun () -> case mnesia:match_object(#route{domain = LDomain, pid = Pid, _ = '_'}) of [R] -> mnesia:delete_object(R); _ -> ok end end, mnesia:transaction(F); _ -> F = fun () -> case mnesia:match_object(#route{domain = LDomain, pid = Pid, _ = '_'}) of [R] -> I = R#route.local_hint, mnesia:write(#route{domain = LDomain, pid = undefined, local_hint = I}), mnesia:delete_object(R); _ -> ok end end, mnesia:transaction(F) end end. -spec unregister_routes([binary()]) -> ok. unregister_routes(Domains) -> lists:foreach(fun (Domain) -> unregister_route(Domain) end, Domains). -spec dirty_get_all_routes() -> [binary()]. dirty_get_all_routes() -> lists:usort(mnesia:dirty_all_keys(route)) -- (?MYHOSTS). -spec dirty_get_all_domains() -> [binary()]. dirty_get_all_domains() -> lists:usort(mnesia:dirty_all_keys(route)). %%==================================================================== %% gen_server callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- init([]) -> update_tables(), mnesia:create_table(route, [{ram_copies, [node()]}, {type, bag}, {attributes, record_info(fields, route)}]), mnesia:add_table_copy(route, node(), ram_copies), mnesia:subscribe({table, route, simple}), lists:foreach(fun (Pid) -> erlang:monitor(process, Pid) end, mnesia:dirty_select(route, [{{route, '_', '$1', '_'}, [], ['$1']}])), {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} -> ?ERROR_MSG("~p~nwhen processing: ~p", [Reason, {From, To, Packet}]); _ -> ok end, {noreply, State}; handle_info({mnesia_table_event, {write, #route{pid = Pid}, _ActivityId}}, State) -> erlang:monitor(process, Pid), {noreply, State}; handle_info({'DOWN', _Ref, _Type, Pid, _Info}, State) -> F = fun () -> Es = mnesia:select(route, [{#route{pid = Pid, _ = '_'}, [], ['$_']}]), lists:foreach(fun (E) -> if is_integer(E#route.local_hint) -> LDomain = E#route.domain, I = E#route.local_hint, mnesia:write(#route{domain = LDomain, pid = undefined, local_hint = I}), mnesia:delete_object(E); true -> mnesia:delete_object(E) end end, Es) end, mnesia:transaction(F), {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}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- do_route(OrigFrom, OrigTo, OrigPacket) -> ?DEBUG("route~n\tfrom ~p~n\tto ~p~n\tpacket " "~p~n", [OrigFrom, OrigTo, OrigPacket]), case ejabberd_hooks:run_fold(filter_packet, {OrigFrom, OrigTo, OrigPacket}, []) of {From, To, Packet} -> LDstDomain = To#jid.lserver, case mnesia:dirty_read(route, LDstDomain) of [] -> ejabberd_s2s:route(From, To, Packet); [R] -> Pid = R#route.pid, if node(Pid) == node() -> case R#route.local_hint of {apply, Module, Function} -> Module:Function(From, To, Packet); _ -> Pid ! {route, From, To, Packet} end; is_pid(Pid) -> Pid ! {route, From, To, Packet}; true -> drop end; Rs -> Value = case ejabberd_config:get_local_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(); source -> jid:tolower(From); destination -> jid:tolower(To); bare_source -> jid:remove_resource(jid:tolower(From)); bare_destination -> jid:remove_resource(jid:tolower(To)) end, case get_component_number(LDstDomain) of undefined -> case [R || R <- Rs, node(R#route.pid) == node()] of [] -> R = lists:nth(erlang:phash(Value, length(Rs)), Rs), Pid = R#route.pid, if is_pid(Pid) -> Pid ! {route, From, To, Packet}; true -> drop end; LRs -> R = lists:nth(erlang:phash(Value, length(LRs)), LRs), Pid = R#route.pid, case R#route.local_hint of {apply, Module, Function} -> Module:Function(From, To, Packet); _ -> Pid ! {route, From, To, Packet} end end; _ -> SRs = lists:ukeysort(#route.local_hint, Rs), R = lists:nth(erlang:phash(Value, length(SRs)), SRs), Pid = R#route.pid, if is_pid(Pid) -> Pid ! {route, From, To, Packet}; true -> drop end end end; drop -> ok end. get_component_number(LDomain) -> ejabberd_config:get_option( {domain_balancing_component_number, LDomain}, fun(N) when is_integer(N), N > 1 -> N end, 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 end, case lists:member(local_route, mnesia:system_info(tables)) of true -> mnesia:delete_table(local_route); 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]. ejabberd-16.01/src/ejabberd_sm_odbc.erl0000644000232200023220000001212312645157216020354 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov %%% @copyright (C) 2015, Evgeny Khramtsov %%% @doc %%% %%% @end %%% Created : 9 Mar 2015 by Evgeny Khramtsov %%%------------------------------------------------------------------- -module(ejabberd_sm_odbc). -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]). -include("ejabberd.hrl"). -include("ejabberd_sm.hrl"). -include("logger.hrl"). -include("jlib.hrl"). %%%=================================================================== %%% API %%%=================================================================== -spec init() -> ok | {error, any()}. init() -> Node = ejabberd_odbc:escape(jlib:atom_to_binary(node())), ?INFO_MSG("Cleaning SQL SM table...", []), lists:foldl( fun(Host, ok) -> case ejabberd_odbc:sql_query( Host, [<<"delete from sm where node='">>, Node, <<"'">>]) of {updated, _} -> ok; Err -> ?ERROR_MSG("failed to clean 'sm' table: ~p", [Err]), Err end; (_, Err) -> Err end, ok, ?MYHOSTS). set_session(#session{sid = {Now, Pid}, usr = {U, LServer, R}, priority = Priority, info = Info}) -> Username = ejabberd_odbc:escape(U), Resource = ejabberd_odbc:escape(R), InfoS = ejabberd_odbc:encode_term(Info), PrioS = enc_priority(Priority), TS = now_to_timestamp(Now), PidS = list_to_binary(erlang:pid_to_list(Pid)), Node = ejabberd_odbc:escape(jlib:atom_to_binary(node(Pid))), case odbc_queries:update( LServer, <<"sm">>, [<<"usec">>, <<"pid">>, <<"node">>, <<"username">>, <<"resource">>, <<"priority">>, <<"info">>], [TS, PidS, Node, Username, Resource, PrioS, InfoS], [<<"usec='">>, TS, <<"' and pid='">>, PidS, <<"'">>]) of ok -> ok; Err -> ?ERROR_MSG("failed to update 'sm' table: ~p", [Err]) end. delete_session(_LUser, LServer, _LResource, {Now, Pid}) -> TS = now_to_timestamp(Now), PidS = list_to_binary(erlang:pid_to_list(Pid)), case ejabberd_odbc:sql_query( LServer, [<<"select usec, pid, username, resource, priority, info ">>, <<"from sm where usec='">>, TS, <<"' and pid='">>,PidS, <<"'">>]) of {selected, _, [Row]} -> ejabberd_odbc:sql_query( LServer, [<<"delete from sm where usec='">>, TS, <<"' and pid='">>, PidS, <<"'">>]), {ok, row_to_session(LServer, Row)}; {selected, _, []} -> {error, notfound}; Err -> ?ERROR_MSG("failed to delete from 'sm' table: ~p", [Err]), {error, notfound} end. get_sessions() -> lists:flatmap( fun(LServer) -> get_sessions(LServer) end, ?MYHOSTS). get_sessions(LServer) -> case ejabberd_odbc:sql_query( LServer, [<<"select usec, pid, username, ">>, <<"resource, priority, info from sm">>]) of {selected, _, Rows} -> [row_to_session(LServer, Row) || Row <- Rows]; Err -> ?ERROR_MSG("failed to select from 'sm' table: ~p", [Err]), [] end. get_sessions(LUser, LServer) -> Username = ejabberd_odbc:escape(LUser), case ejabberd_odbc:sql_query( LServer, [<<"select usec, pid, username, ">>, <<"resource, priority, info from sm where ">>, <<"username='">>, Username, <<"'">>]) of {selected, _, Rows} -> [row_to_session(LServer, Row) || Row <- Rows]; Err -> ?ERROR_MSG("failed to select from 'sm' table: ~p", [Err]), [] end. get_sessions(LUser, LServer, LResource) -> Username = ejabberd_odbc:escape(LUser), Resource = ejabberd_odbc:escape(LResource), case ejabberd_odbc:sql_query( LServer, [<<"select usec, pid, username, ">>, <<"resource, priority, info from sm where ">>, <<"username='">>, Username, <<"' and resource='">>, Resource, <<"'">>]) of {selected, _, Rows} -> [row_to_session(LServer, Row) || Row <- Rows]; Err -> ?ERROR_MSG("failed to select from 'sm' table: ~p", [Err]), [] end. %%%=================================================================== %%% Internal functions %%%=================================================================== now_to_timestamp({MSec, Sec, USec}) -> jlib:integer_to_binary((MSec * 1000000 + Sec) * 1000000 + USec). timestamp_to_now(TS) -> I = jlib:binary_to_integer(TS), Head = I div 1000000, USec = I rem 1000000, MSec = Head div 1000000, Sec = Head div 1000000, {MSec, Sec, USec}. dec_priority(Prio) -> case catch jlib:binary_to_integer(Prio) of {'EXIT', _} -> undefined; Int -> Int end. enc_priority(undefined) -> <<"">>; enc_priority(Int) when is_integer(Int) -> jlib:integer_to_binary(Int). row_to_session(LServer, [USec, PidS, User, Resource, PrioS, InfoS]) -> Now = timestamp_to_now(USec), Pid = erlang:list_to_pid(binary_to_list(PidS)), Priority = dec_priority(PrioS), Info = ejabberd_odbc:decode_term(InfoS), #session{sid = {Now, Pid}, us = {User, LServer}, usr = {User, LServer, Resource}, priority = Priority, info = Info}. ejabberd-16.01/COPYING0000644000232200023220000004332412645157216014677 0ustar debalancedebalanceAs a special exception, the authors give permission to link this program with the OpenSSL library and distribute the resulting binary. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ejabberd-16.01/rel/0000755000232200023220000000000012645157216014420 5ustar debalancedebalanceejabberd-16.01/rel/files/0000755000232200023220000000000012645157216015522 5ustar debalancedebalanceejabberd-16.01/rel/files/install_upgrade.escript0000644000232200023220000000325612645157216022300 0ustar debalancedebalance#!/usr/bin/env escript %%! -noshell -noinput %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ft=erlang ts=4 sw=4 et -define(TIMEOUT, 60000). -define(INFO(Fmt,Args), io:format(Fmt,Args)). main([NodeName, Cookie, ReleasePackage]) -> TargetNode = start_distribution(NodeName, Cookie), {ok, Vsn} = rpc:call(TargetNode, release_handler, unpack_release, [ReleasePackage], ?TIMEOUT), ?INFO("Unpacked Release ~p~n", [Vsn]), {ok, OtherVsn, Desc} = rpc:call(TargetNode, release_handler, check_install_release, [Vsn], ?TIMEOUT), {ok, OtherVsn, Desc} = rpc:call(TargetNode, release_handler, install_release, [Vsn], ?TIMEOUT), ?INFO("Installed Release ~p~n", [Vsn]), ok = rpc:call(TargetNode, release_handler, make_permanent, [Vsn], ?TIMEOUT), ?INFO("Made Release ~p Permanent~n", [Vsn]); main(_) -> init:stop(1). start_distribution(NodeName, Cookie) -> MyNode = make_script_node(NodeName), {ok, _Pid} = net_kernel:start([MyNode, shortnames]), erlang:set_cookie(node(), list_to_atom(Cookie)), TargetNode = make_target_node(NodeName), case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of {true, pong} -> ok; {_, pang} -> io:format("Node ~p not responding to pings.\n", [TargetNode]), init:stop(1) end, TargetNode. make_target_node(Node) -> [_, Host] = string:tokens(atom_to_list(node()), "@"), list_to_atom(lists:concat([Node, "@", Host])). make_script_node(Node) -> list_to_atom(lists:concat([Node, "_upgrader_", os:getpid()])). ejabberd-16.01/rel/files/erl0000755000232200023220000000213612645157216016234 0ustar debalancedebalance#!/bin/sh ## This script replaces the default "erl" in erts-VSN/bin. This is necessary ## as escript depends on erl and in turn, erl depends on having access to a ## bootscript (start.boot). Note that this script is ONLY invoked as a side-effect ## of running escript -- the embedded node bypasses erl and uses erlexec directly ## (as it should). ## ## Note that this script makes the assumption that there is a start_clean.boot ## file available in $ROOTDIR/release/VSN. # Determine the abspath of where this script is executing from. ERTS_BIN_DIR=$(cd ${0%/*} && pwd) # Now determine the root directory -- this script runs from erts-VSN/bin, # so we simply need to strip off two dirs from the end of the ERTS_BIN_DIR # path. ROOTDIR=${ERTS_BIN_DIR%/*/*} # Parse out release and erts info START_ERL=`cat $ROOTDIR/releases/start_erl.data` ERTS_VSN=${START_ERL% *} APP_VSN=${START_ERL#* } BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin EMU=beam PROGNAME=`echo $0 | sed 's/.*\\///'` CMD="$BINDIR/erlexec" export EMU export ROOTDIR export BINDIR export PROGNAME exec $CMD -boot $ROOTDIR/releases/$APP_VSN/start_clean ${1+"$@"} ejabberd-16.01/rel/reltool.config.script0000644000232200023220000001016512645157216020575 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov %%% @copyright (C) 2013, Evgeniy Khramtsov %%% @doc %%% %%% @end %%% Created : 8 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- 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 -> [] end, RequiredOTPApps = [sasl, crypto, public_key, ssl, mnesia, inets, compiler, asn1, syntax_tools, os_mon, xmerl], ConfiguredOTPApps = lists:flatmap( fun({tools, true}) -> [tools, runtime_tools]; ({odbc, true}) -> [odbc]; (_) -> [] end, Vars), OTPApps = RequiredOTPApps ++ ConfiguredOTPApps, DepApps = lists:usort(lists:flatten(GetDeps(filename:join(TopDir, "rebar.config"), GetDeps))), Sys = [{lib_dirs, []}, {erts, [{mod_cond, derived}, {app_file, strip}]}, {app_file, strip}, {rel, "ejabberd", proplists:get_value(vsn, Vars), [ kernel, stdlib, ejabberd ] ++ OTPApps ++ DepApps}, {rel, "start_clean", "", [ kernel, stdlib ]}, {boot_rel, "ejabberd"}, {profile, embedded}, {incl_cond, exclude}, {excl_archive_filters, [".*"]}, %% Do not archive built libs {excl_sys_filters, ["^bin/.*", "^erts.*/bin/(dialyzer|typer)", "^erts.*/(doc|info|include|lib|man|src)"]}, {excl_app_filters, ["\.gitignore"]}, {app, stdlib, [{incl_cond, include}]}, {app, kernel, [{incl_cond, include}]}, {app, ejabberd, [{incl_cond, include}, {lib_dir, ".."}]}] ++ lists:map( fun(App) -> {app, App, [{incl_cond, include}, {lib_dir, "../deps/" ++ atom_to_list(App)}]} end, DepApps) ++ lists:map( fun(App) -> {app, App, [{incl_cond, include}]} end, OTPApps). Overlay = [ {mkdir, "var/log/ejabberd"}, {mkdir, "var/lock"}, {mkdir, "var/lib/ejabberd"}, {mkdir, "etc/ejabberd"}, {mkdir, "doc"}, {template, "files/erl", "\{\{erts_vsn\}\}/bin/erl"}, {template, "../ejabberdctl.template", "bin/ejabberdctl"}, {copy, "../ejabberdctl.cfg.example", "etc/ejabberd/ejabberdctl.cfg"}, {copy, "../ejabberd.yml.example", "etc/ejabberd/ejabberd.yml"}, {copy, "../inetrc", "etc/ejabberd/inetrc"}, {copy, "files/install_upgrade.escript", "bin/install_upgrade.escript"} ], Config = [{sys, Sys}, {overlay_vars, "../vars.config"}, {target_dir, "ejabberd"}, {overlay, Overlay}], %%io:format("ejabberd release:~n ~p~n", [Config]), Config. %% Local Variables: %% mode: erlang %% End: %% vim: set filetype=erlang tabstop=8: ejabberd-16.01/vars.config.in0000644000232200023220000000256412645157216016414 0ustar debalancedebalance%%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov %%% @copyright (C) 2013, Evgeniy Khramtsov %%% @doc %%% %%% @end %%% Created : 8 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- %% Macros {roster_gateway_workaround, @roster_gateway_workaround@}. {full_xml, @full_xml@}. {db_type, @db_type@}. {debug, @debug@}. {hipe, @hipe@}. {erlang_deprecated_types, @erlang_deprecated_types@}. %% Ad-hoc directories with source files {tools, @tools@}. %% Dependencies {odbc, @odbc@}. {mysql, @mysql@}. {pgsql, @pgsql@}. {sqlite, @sqlite@}. {pam, @pam@}. {zlib, @zlib@}. {riak, @riak@}. {redis, @redis@}. {elixir, @elixir@}. {lager, @lager@}. {iconv, @iconv@}. %% Version {vsn, "@PACKAGE_VERSION@"}. %% Variables for overlay template files %% Platform-specific installation paths {release, true}. {release_dir, "${SCRIPT_DIR%/*}"}. {sysconfdir, "{{release_dir}}/etc"}. {installuser, "@INSTALLUSER@"}. {erl, "{{release_dir}}/{{erts_vsn}}/bin/erl"}. {localstatedir, "{{release_dir}}/var"}. {libdir, "{{release_dir}}/lib"}. {docdir, "{{release_dir}}/doc"}. {latest_deps, @latest_deps@}. {ldflags, "@LDFLAGS@"}. {cflags, "@CFLAGS@"}. {cppflags, "@CPPFLAGS@"}. %% Local Variables: %% mode: erlang %% End: %% vim: set filetype=erlang tabstop=8: