Compare commits

...

203 Commits

Author SHA1 Message Date
Paweł Chmielowski 23beaa9fad Update mix dependencies 2020-07-30 17:57:52 +02:00
Jerome Sautret 839229b5f0 Check if TERM is set before running a remote debug shell 2020-07-30 10:33:38 +02:00
Jérôme Sautret b89b0f140a Merge pull request #3346 from processone/ejabberd-3343
Allow passing Erlang VM args through vm.args config file
2020-07-30 10:31:12 +02:00
Mickael Remond 09454e1658 Allow passing Erlang VM args through vm.args config file
This can be used to define the Erlang cookie in a place that feels less foreign to
non Erlang users.

Fixes #3343
2020-07-29 17:35:59 +02:00
Paweł Chmielowski 828c0ad1e0 Update deps 2020-07-28 14:38:34 +02:00
Paweł Chmielowski 87bbd9cb02 Update stun 2020-07-28 14:04:00 +02:00
Paweł Chmielowski 70507a694c Update changelog 2020-07-28 13:25:27 +02:00
Paweł Chmielowski 1b168e7d5c Add support for unix socket in listeners
To use it you just need to set port value to "unix:/path/to/socket"
2020-07-28 12:19:30 +02:00
Paweł Chmielowski d5935fd1ad Don't log http errors when socket get closed after processing one request 2020-07-28 12:19:30 +02:00
Badlop 2bcd2c38a9 No need to check for Erlang 17, as 19 is the lowest supported anyway
This rollsback the conditional introduced years ago in c2753cd51c
2020-07-28 11:28:04 +02:00
Badlop 042cddb768 Elixir was required for quicktest, that was removed in 2018 51cbbf313 2020-07-28 11:26:41 +02:00
Badlop e0b7fd72af Update Stun to 1.0.36, and Esip too 2020-07-28 11:25:43 +02:00
Badlop 9c5e4454e4 Sort dependencies and improve some indentation 2020-07-22 18:03:28 +02:00
Badlop 7fe0b8d274 Revert "Modify ERL_LDFLAGS of deps when compiling on R23 on rebar2"
This reverts commit 21312c79aa.
2020-07-22 10:08:14 +02:00
Badlop 90ca689123 Update dependencies, they now compile with Erlang/OTP 23.0 natively 2020-07-22 10:06:06 +02:00
Badlop db2825342c Revert "Dirty workarounds to compile jiffy with Erlang/OTP 23 (#3282)"
This reverts commit 2ca5712507.
2020-07-15 12:12:42 +02:00
Badlop bc1de531cc Update jiffy to 1.0.5 which supports Erlang/OTP 23 2020-07-15 12:12:39 +02:00
Badlop 2ea5f7856c In fact misc:try_url/1 is not used anymore 2020-07-15 11:41:51 +02:00
Badlop e5b66aadaf Fix try_url/1 parsing of uri_parse result format, reported by Dialyzer 2020-07-14 12:21:37 +02:00
Holger Weiss cff7c4c100 Update 'stun' dependency to tagged version 2020-07-11 17:53:33 +02:00
Holger Weiss e30592c050 mod_stun_disco: Fix function specification 2020-07-11 17:51:20 +02:00
Badlop ff92dab49e Parse also ServerHost in create_room* commands (#3326) 2020-07-10 13:06:05 +02:00
Badlop f652f8c8d6 Fix crash when creating new MUC log file in non-ASCII lang (#3324) 2020-07-10 12:03:12 +02:00
Badlop 80a502782b Use the same leading sentence than other sections 2020-07-06 16:39:15 +02:00
Holger Weiss 3bf7fbc117 ejabberd_stun: Filter info/debug messages
Update 'stun' dependency, and drop the info/debug messages now logged by
the 'stun' application if OTP's new logging API is used.
2020-07-01 21:53:22 +02:00
Badlop 0ff5b44d15 Fix YAML syntax in example configuration (#3301) 2020-06-25 12:39:44 +02:00
Badlop 61926a44be Subscriber should not send message to moderated room (#3222) 2020-06-24 13:17:04 +02:00
Holger Weiss ec5f369d9d ejabberd_logger: Avoid excessive stat calls
By default, the logger_std_h module shipped with OTP 21.0 and newer
reads the log file information prior to each and every write operation.
This is done to play well with external log rotation tools.

In order to minimize the performance penalty in situations where the log
file is flooded, configure logger_std_h to skip reading the file
information as long as no more than one second has passed since it was
last read.
2020-06-23 21:27:12 +02:00
Holger Weiss dbebcd08c7 README.md: Add line breaks after feature titles 2020-06-23 00:31:22 +02:00
Paweł Chmielowski 768460b518 Correctly handle user_regexp acl rules with not matching host
This should fix issue reported in issue 3304
2020-06-22 10:24:10 +02:00
Holger Weiss 515dfc002b mod_stun_disco: Fix wording of log message 2020-06-19 18:04:26 +02:00
Badlop 16645a3c0a Document that only ejabberdctl can join and leave a local node (#3049) 2020-06-09 13:23:17 +02:00
Badlop 38949bdeea Update example config to include mod_http_upload custom headers (#3288) 2020-06-09 13:08:05 +02:00
Badlop 5f3457dbd6 Add default values so Travis config validation stops warning 2020-06-08 15:27:37 +02:00
Badlop b9108c4650 Travis renamed redis-server to redis apparently 2020-06-08 15:27:28 +02:00
Badlop a54c667c80 Remove old Regexp, the new Re is available since Erlang/OTP R12B-4 2020-06-08 15:27:27 +02:00
Badlop bcd2cd7e93 Remove comment about Erlang/OTP older than R14, as we require 19.3 nowadays 2020-06-08 15:27:25 +02:00
Badlop 337ba42953 Get back some commented specs that required Erlang R12 2020-06-08 15:27:23 +02:00
Badlop 4f5c00a83d Option route_subdomains was deprecated and useless a year ago in ffe1c722 2020-06-08 15:27:18 +02:00
Holger Weiss c6bbdafe92 Update 'yconf' dependency to fix Erlang/OTP 19.x 2020-06-05 20:24:17 +02:00
Badlop f2e81ed2a0 When updating group in cache, first delete so insert succeeds (#3296) 2020-06-05 19:34:00 +02:00
Badlop 7efc208b9e Handle ets_cache return value in shared roster get_group_opts (#3296) 2020-06-05 19:33:52 +02:00
Holger Weiss 266691f929 Update 'yconf' dependency
Fixes #3295.
2020-06-05 17:02:06 +02:00
Paweł Chmielowski 482917348b Update deps 2020-06-03 13:43:10 +02:00
Holger Weiss 945a5cd09c misc: Don't crash on URLs without port number
Let misc:uri_parse/1 return default HTTP(S) port number if the URL
doesn't specify a port number, analogous to the behavior when
USE_OLD_HTTP_URI is defined.
2020-06-03 12:22:14 +02:00
Holger Weiss 9ea51d3295 misc: Make sure uri_parse/1 returns strings
The uri_string:parse/1 function returns the URI elements as strings or
as binaries depending on the input.  Make sure misc:uri_parse/1 returns
strings in both cases, analogous to the behavior when USE_OLD_HTTP_URI
is defined.
2020-06-03 12:02:29 +02:00
Holger Weiss 77308e6aff Merge remote-tracking branch 'processone/pr/3294'
* processone/pr/3294:
  Update example config
2020-06-03 09:41:24 +02:00
Licaon_Kter b0c6caa60e Update example config 2020-06-03 07:19:02 +00:00
Holger Weiss 3cfc5c9633 Update 'turn_ip' option name in test configuration
Thanks to Badlop for spotting this.
2020-06-03 06:13:43 +02:00
Holger Weiss cd336369a5 mod_stream_mgmt: Don't kill new PID on resumption
During XEP-0198 resumption, the ejabberd_c2s process that handles the
new connection reopens the ejabberd_sm session of the old one.  Since
commit b4770815c0, the new process adds
the new session table entry before the old process removes the old one.
While adding the new one, ejabberd_sm checks for old sessions to
replace.  This check assumes old SIDs compare lower than new ones.  This
assumption didn't necessarily hold for the session resumption case,
where the old SID's timestamp was copied over to the new SID and only
the PID was updated.  Therefore, the new process was killed if the new
PID happened to be smaller than the old one.

Fix this by having mod_stream_mgmt use its own SM-ID rather than copying
over the old SID's timestamp to the new SID.

Thanks to Thilo Molitor and Friedrich Altheide for reporting the issue,
and to Thomas Leister for his help with debugging it.
2020-06-01 21:33:55 +02:00
Badlop c62956ab7b Test 23.0 version 2020-06-01 10:35:41 +02:00
Badlop 1d7e29765e Update eimp, sqlite3 and epam to support Erlang/OTP 23 (#3282) 2020-06-01 10:35:37 +02:00
Badlop c0f7008e96 Use old http_uri, crypto and pg2 only with old Erlang/OTP (#3284) 2020-06-01 10:35:28 +02:00
Badlop 2ca5712507 Dirty workarounds to compile jiffy with Erlang/OTP 23 (#3282)
Works for me with:
./configure --disable-pam
./rebar get-deps
./rebar configure-deps
./rebar compile
make install

changes in erlang-native-compiler used by jiffy:

src/rebar_port_compiler.erl
-     {"ERL_LDFLAGS"  , " -L$ERL_EI_LIBDIR -lerl_interface -lei"},
+     {"ERL_LDFLAGS"  , " -L$ERL_EI_LIBDIR -lei"},

src/rebar_utils.erl
--dialyzer({no_missing_calls, escript_foldl/3}).
2020-06-01 10:33:06 +02:00
Holger Weiss 7a37483307 Rename 'turn_v4_ip' and 'turn_v6_ip' options
The 'turn_ipv4_address' and 'turn_ipv6_address' option names are
probably more intuitive.
2020-05-29 18:40:19 +02:00
Paweł Chmielowski 21312c79aa Modify ERL_LDFLAGS of deps when compiling on R23 on rebar2
Newer version removed erl_interface, and default rebar2 ERL_LDFLAGS will
try to link it, this change should pass correct flags to compiler.
2020-05-26 11:01:22 +02:00
Holger Weiss 56d00e427d ejabberd_stun: Add 'turn_blacklist' option
The new 'turn_blacklist' listener option allows for specifying one or
more IP addresses and/or subnet addresses/masks.  The TURN server will
refuse to relay traffic from/to blacklisted IP addresses.  By default,
Teredo and 6to4 addresses are blacklisted, as mandated by RFC 6156
(section 9.1).
2020-05-21 21:46:02 +02:00
Holger Weiss 7bb4da2fee mod_stun_disco: Make 'services' example shorter
Omit the 'tcp' and 'stuns' services from the list of example 'services'
in the documentation.  For typical use cases, those are less interesting
than 'udp' and 'turns' services.
2020-05-19 23:23:24 +02:00
Holger Weiss f19b975e8d mod_stun_disco: Offer local IPv6 services
Also announce local STUN/TURN services listening on IPv6 sockets (unless
the 'offer_local_services' option is set to 'false').
2020-05-19 22:55:12 +02:00
Holger Weiss 83fa637569 ejabberd_stun: Support IPv6 for TURN
The stun application now supports RFC 6156: TURN Extension for IPv6, and
therefore needs separate IPv4 and IPv6 relay addresses.
2020-05-19 21:42:41 +02:00
Holger Weiss 858bfb4b80 Let ejabberd_stun listen on IPv6 sockets
The stun application now allows IPv6 clients to perform STUN requests
and to allocate TURN relays.
2020-05-19 20:22:58 +02:00
Badlop 42c82c9e72 Fix hardcoded URL to register.css and URLS to sections (#3281) 2020-05-19 19:32:06 +02:00
Badlop 8efdd439f1 Update man page to ejabberd 20.04 2020-05-19 16:38:11 +02:00
Badlop 70977cbb13 Sort databases alphabetically in options doc (thanks to Neustradamus)(#3246) 2020-05-19 16:38:08 +02:00
Badlop ad31fbee1e Sort alphabetically configure options (thanks to Neustradamus)(#3246) 2020-05-19 16:38:05 +02:00
Paweł Chmielowski 6f54b6ae3b Don't crash in mod_muc_log:get_url when mod_muc_log is not enabled
Disco on room can call this function even when logger is not enabled,
but this room option was enabled previously when logger was active.
2020-05-15 13:44:09 +02:00
Badlop e94b89a57d Display installed ejabberd version in webadmin footer (#3272) 2020-05-15 11:20:53 +02:00
yuriyz-w 44528d3fef Make SQL query more generic for MSSQL compatibility (#3271) 2020-05-15 09:19:55 +02:00
Paweł Chmielowski 4580feaa3c Increase default shaper limits, to help with jingle initiation delay
More discussion about this can be found in pull request 3255
2020-05-15 09:10:57 +02:00
Badlop f3b8dc9c0b Update *_vcard commands help, so they are better displayed in Docs 2020-05-14 20:02:47 +02:00
Badlop 9d923e8e6d Update syntax of some options so they are better displayed in Docs 2020-05-12 21:33:00 +02:00
Badlop c861fa6a6a Revert service_subscription_subscribers test that is iconsistent (#2696) 2020-05-11 22:25:56 +02:00
Badlop d7d8085d3b Fix most EDoc errors, even if that's not used nowadays apparently 2020-05-11 19:53:13 +02:00
Badlop 5e70a47f20 If new session Pid exists when sm_remove is called, then keep Ping (#3260) 2020-05-11 18:22:35 +02:00
Holger Weiss e286bb23db mod_stun_disco: Bump credentials_lifetime default
Increase the default lifetime of temporary credentials to 12 hours.
ejabberd's built-in TURN server re-queries the temporary password from
mod_stun_disco whenever a TURN client attempts to refresh an allocation,
and mod_stun_disco will only return the password as long as the
credentials didn't expire.  Therefore, the credentials lifetime
effectively limits the maximum lifetime of a TURN allocation when
ejabberd's TURN service is used, so the default value shouldn't be too
short.
2020-05-11 17:32:28 +02:00
Badlop 2c42bd07c8 Fix link in mod_sip to SIP Docs section 2020-05-09 16:10:26 +02:00
Badlop 2001540143 Provide minimal mod_bosh configuration example 2020-05-09 15:04:10 +02:00
Badlop d88a32992a Add link in acme option to ACME section in ejabberd Docs 2020-05-09 11:45:39 +02:00
Badlop 64c09c20eb Hide false-positive warnings about mod_delegation Type atom and NS binary 2020-05-07 22:29:54 +02:00
Badlop c990704418 Remove ancient and rather useless incode ejabberd_commands documentation 2020-05-07 19:38:12 +02:00
Badlop edf5b3c7f0 Don't use string:take, as it isn't available in Erlang/OTP 19.3 (#3256) 2020-05-07 16:09:51 +02:00
Badlop e5a2d42484 Fix webadmin muc room sorting broken due to trailing slash patch (#3256) 2020-05-07 11:22:43 +02:00
Paweł Chmielowski 51e45516a4 Unconditionally send presence unavailable to all pres_a recipient
Previously we only send that presence to direct presence recipients if
client also sent general self presence (without to attribute).

This should help with issue #3245
2020-05-07 10:40:18 +02:00
Badlop 41b06cb79e Show deprecation warning if ejabberd_xmlrpc is configured as listen module (#2915) 2020-05-06 14:08:43 +02:00
Badlop d8509aec12 Remove access_commands useless lines, api_permission replaced it years ago 2020-05-06 14:08:40 +02:00
Holger Weiss 5649e35a64 ejabberd_listener: Let supervisor terminate child
If a TCP connection was closed before the socket was handed over to a
supervised child process, let the supervisor terminate the process
rather than killing it directly.  This avoids crash log entries
generated by the supervisor.
2020-05-05 17:22:52 +02:00
Holger Weiss 865074603c Set 'max_fsm_queue' default value (back) to 10000
The default value for the 'max_fsm_queue' option was set to 10000 in
commit 79685da90b, and that value is still
documented to be the default.  It was (probably unintentionally) changed
to 5000 in commit 03de853e4f.

It makes sense to keep it larger than the value of mod_stream_mgmt's
'max_ack_queue' option.
2020-05-05 01:34:12 +02:00
Holger Weiss 6d13120e69 mod_stun_disco: Log discovered services on startup
If the 'offer_local_services' option isn't set to 'false', log an [info]
message for each auto-discovered ejabberd_stun listener on startup (and
on configuration reload).
2020-05-05 01:02:50 +02:00
Badlop e6a3b1fa68 Extract translatable strings also from the xmpp library 2020-05-04 16:25:42 +02:00
Badlop df66fa6a48 Fix the new service_subscription_subscribers test (#2696) 2020-05-04 11:31:52 +02:00
Marc Tonnes 5d499c7173 Fix @from attribute on MucSub 'subscribers' node messages 2020-05-04 11:31:24 +02:00
Holger Weiss b1e967eaf3 mod_stun_disco: Remove unnecessary inclusion 2020-05-03 17:27:41 +02:00
Holger Weiss 151fa2ec50 mod_stun_disco: Apply minor documentation cleanups 2020-05-03 17:20:15 +02:00
Holger Weiss e4de03f3df mod_stun_disco: Try to resolve listener address
In some IPv6-only networks, hostnames that have no AAAA record are
resolved to an IPv6 address that's mapped to the host's IPv4 address.
This allows the IPv6-only clients to communicate with IPv4-only services
such as ejabberd's built-in STUN/TURN server.  If STUN/TURN clients try
to contact the IPv4 address directly rather than using the mapped IPv6
address, the connection will fail.

Therefore, try to resolve the IP address of local ejabberd_stun services
to the hostname and announce that hostname rather than the IP address if
(and only if) the hostname resolves back to the original IP address, and
not to any additional IPv4 or IPv6 address(es).

This can (and should) be reverted once IPv6 support is added to
ejabberd's built-in STUN/TURN server.
2020-04-30 22:40:01 +02:00
Jerome Sautret 724d09a510 Set ejabberd version to 20.04 2020-04-29 16:29:59 +02:00
Badlop fba6a64648 Fix English typos in configure.ac 2020-04-29 12:07:35 +02:00
Jérôme Sautret 0539637d30 Merge pull request #3232 from weiss/enable-stun
Enable STUN/TURN support by default
2020-04-29 10:29:05 +02:00
Badlop 4a7d42647f Rewrite sentences in modules options examples, to not break Docs indentation 2020-04-28 21:31:35 +02:00
Paweł Chmielowski b56663ef07 Update dependences in mix 2020-04-28 17:23:36 +02:00
Paweł Chmielowski 25597a4326 Run tests for mssql only if configured with --enable-mssql 2020-04-28 16:52:08 +02:00
Paweł Chmielowski 56c8f6b280 Update deps 2020-04-28 16:24:40 +02:00
ChaosKid42 abc3260e75 enable tests with mssql-backend (#3136) 2020-04-28 16:22:42 +02:00
Jérôme Sautret 24a11fc8e8 Merge pull request #3235 from weiss/xep-0215
Support STUN/TURN service discovery
2020-04-28 16:03:21 +02:00
Holger Weiss 6eb2f07274 ejabberd_stun: Tone down 'auth_realm' warning
These days, STUN/TURN authentication can be performed with ephemeral
credentials, where the REALM is irrelevant. Therefore, just log an
[info] message rather than a [warning] in the case where no
authentication REALM is configured but multiple virtual domains exist.
2020-04-28 10:34:43 +02:00
Holger Weiss 9cd47d7085 Add tests for mod_stun_disco 2020-04-28 10:34:43 +02:00
Holger Weiss 69d1d62add Support XEP-0215: External Service Discovery
Add the 'mod_stun_disco' module, which allows XMPP clients to discover
STUN/TURN services and to obtain temporary credentials for using them as
per XEP-0215: External Service Discovery.  The temporary credentials
handed out to clients have the format described in:

https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00

Also add the new module to the example configuration file.

Closes #2947.
2020-04-28 10:34:43 +02:00
Badlop 3db9459591 Don't offer X-OAUTH2 if the only auth method enabled is Anonymous (#3209) 2020-04-27 20:03:21 +02:00
Paweł Chmielowski 6320dfd34e Don't store caps information for direct presences of muc room
We really don't need those, and thanks to each individual room having
different hash (as one of hashed data is room description) we end with
lot of data that we really don't need.
2020-04-27 13:17:51 +02:00
Badlop 055fe744d3 Clean some unused functions in ejabberd_ctl, this makes "make hooks" happy 2020-04-24 20:36:24 +02:00
Christoph Scholz d7c696f97c mix.exs: Update 'xmpp' and 'stun' 2020-04-23 20:05:40 +02:00
Holger Weiss fc444ce503 rebar.config: Update 'xmpp' and 'stun'
Use the current versions of 'xmpp' (to get XEP-0215 support) and 'stun'
(to fix TURN issues).
2020-04-23 20:05:40 +02:00
Holger Weiss 88f392721b gen_mod: Reload modules after reloading listeners
Make sure modules won't be reloaded before listeners.  This is necessary
to allow the (not yet committed) 'mod_stun_disco' module to parse the
listener configuration after configuration reloads.
2020-04-23 20:05:40 +02:00
Holger Weiss c55e7b8499 ejabberd_stun: Fix 'turn_ip' fallback
The 'turn_ip' option validator doesn't accept an inet:ip4_address()
tuple.

While at it, change the logic to only perform the fallback address
lookup if no 'turn_ip' is configured (analogous to the fallback
mechanism for the case where the 'auth_realm' is undefined).
2020-04-23 18:32:40 +02:00
ChaosKid42 1f7ca91670 use dsn-less config for mssql (#3131) 2020-04-23 13:56:41 +02:00
Licaon_Kter d9131c854d Bump jiffy so it compiles on older GCC (#3218)
* Update jiffy

* And here
2020-04-23 13:29:33 +02:00
Holger Weiss 09a87f5a0c ejabberd_stun: Handle hashed passwords gracefully
Don't crash when STUN/TURN authentication is performed against a
SCRAM-hashed password.
2020-04-22 00:16:03 +02:00
Holger Weiss 1db70edcf8 ejabberd_stun: Add 'stun_get_password' hook
Add a hook that allows modules to offer a password for STUN/TURN
authentication.
2020-04-22 00:09:42 +02:00
Badlop 1a3533e4a2 Fix some English typos 2020-04-21 20:58:01 +02:00
Badlop 3db9de26e9 Rephrase mod_admin_extra doc, a2x screwed the format when building Docs 2020-04-21 20:11:39 +02:00
Badlop 78f0439e78 Make a few more strings translatable in MUC and Shared Roster WebAdmin 2020-04-20 20:24:56 +02:00
Badlop b124e911d3 Update some translated strings where only print chars had changed 2020-04-20 20:24:50 +02:00
Holger Weiss c836dc66a8 ejabberd_stun: Set a default 'turn_ip'
Try to resolve the local hostname, use the result as the default
'turn_ip', and only log a warning if that fails.  Using the local
hostname's address by default is analogous to mod_proxy65's behavior.
2020-04-20 08:42:32 +02:00
Holger Weiss b1b3c4cdcf Enable STUN/TURN by default
Build ejabberd with STUN/TURN support by default, and add a STUN/TURN
listener to the example configuration file.
2020-04-20 00:37:41 +02:00
Holger Weiss b0f95975c2 Travis CI: Test against Erlang/OTP 22.3 2020-04-19 15:39:34 +02:00
Badlop 2e48c24638 Updated Spanish translation 2020-04-17 19:29:17 +02:00
Badlop 7359eb6246 Updated Catalan translation 2020-04-17 19:23:21 +02:00
Badlop 99d21bca49 Don't extract for translation strings from man pages, at least for now 2020-04-17 19:23:18 +02:00
Badlop 1b98084918 Fix previous commit 2020-04-17 19:23:13 +02:00
Badlop d311eaf8f3 Log messages generated by msgmerge and display unexpected ones 2020-04-17 17:28:43 +02:00
Badlop 0355e15a42 Fix doc content in mod_admin_extra so it can be extracted by make translations 2020-04-17 17:28:39 +02:00
Badlop 101f7a6d63 Check if mod_muc_log is enabled before setting logging option (#3215) 2020-04-17 16:19:58 +02:00
Badlop 4aa85c538c When rescode is some unexpected, probably error message, print it 2020-04-17 16:19:55 +02:00
Paweł Chmielowski 22980ed8a5 Restart offline pop_messages when there is mismatch between select and delete
When another connection is inserting something to spool at this same time
as we do pop_messages, it's possible that insert will happen between we
fetch messages and delete them, so we effectively will delete it without
delivering it to client. This change catch this situation and restart
transaction, so we should always have consistent results.
2020-04-17 15:30:28 +02:00
Paweł Chmielowski cb1c0a3188 Update mysql driver to get rid of warning 2020-04-16 18:26:13 +02:00
Badlop 0705695e02 Update documentation of mod_shared_roster (#3214) 2020-04-16 13:12:32 +02:00
Paweł Chmielowski c11922e2a2 Make session iq response have from be set to server jid
It looks like old version of Smack don't accept request that are have
from sent to sender jid, but are only working when jid is set to server
address. This is also how it looks in old xmpp rfc examples.
2020-04-16 13:05:42 +02:00
Paweł Chmielowski 37226dd41f Resending unacked stanzas should send even archived msgs if mod_offline is enabled
Messages that are received when no c2s is active will be stored in offline,
even when mam archived them, so i don't think we should be doing something
different in this case.
2020-04-16 13:04:12 +02:00
Badlop cd0b65f4d5 Fix unused variables from previous commit 2020-04-14 15:00:45 +02:00
Badlop b7c088d4b0 Update links to the ejabberd Docs page in WebAdmin 2020-04-14 13:59:11 +02:00
Badlop e197b25e82 Rename opts->name to label, to avoid confusion with the group name (#3214)
Also updated WebAdmin to show more meaningful explanations
Also fixed a bug that break support for group@host in Displayed
2020-04-14 13:58:53 +02:00
Jérôme Sautret b02506eaaf Merge pull request #3132 from area-42/publisher_mssql_text_to_varchar
change PubSub publisher from text to varchar for mssql
2020-04-10 16:20:43 +02:00
Badlop 8694517c34 Minor fixes in doc 2020-04-09 16:30:21 +02:00
Badlop 2febd1c220 Copy more option explanations from ejabberd Docs site 2020-04-08 18:49:41 +02:00
Badlop aa0ed37034 Add ejabberd version number to man pages 2020-04-08 18:48:09 +02:00
Badlop da18245d9a Indicate which ejabberd version is used to produce the page 2020-04-08 18:47:50 +02:00
Badlop 5cc9a1fe44 Don't make commands subsections, so Docs TOC plage is cleaner 2020-04-08 18:45:29 +02:00
Badlop de0aead1cd Fix set_loglevel example argument documentation 2020-04-08 18:44:09 +02:00
Badlop 624ba7e94f Improve formatting of mod_announce doc 2020-04-08 18:42:45 +02:00
Paweł Chmielowski 9bb3aee0e2 Make resumed sessions try to deliver possibly queued messages to new session
Between receiving resume request and being closed by new session, it's
possible (even if not very likely) that new messages would arrive to
process that is resumed. In that case try to reroute messages that were
received after we sent resume reply to new process.
2020-04-07 14:51:49 +02:00
Paweł Chmielowski 16585713f8 Log errors that happen when retrieving http headers in ejabberd_http
It seems that ssl errors can be generated here, so lets have abily to show
them instead of swallowing them silently.
2020-04-07 13:50:01 +02:00
Holger Weiss e01e528235 mod_carboncopy: Bump supported XEP revision
Since mod_carboncopy supports "urn:xmpp:carbons:rules:0", it implements
version 0.13.x of XEP-0280.
2020-04-05 22:52:55 +02:00
Paweł Chmielowski eac7e3488c Remove bash-izm from ejabberdctl.template introduced recently 2020-04-03 17:28:27 +02:00
Jerome Sautret 762486d199 Limit number of atoms used by ejabberdctl ( #2977) 2020-04-02 15:51:16 +02:00
Badlop 23493ce239 Document mod_shared_roster_ldap options 2020-04-02 12:56:43 +02:00
Badlop 510ab53341 Add ejabberd_auth_http auth_opts brief description 2020-04-02 12:56:40 +02:00
Badlop 220cf73318 Document sql_prepared_statements 2020-04-02 12:56:38 +02:00
Badlop f6d102f5e2 Quick document with forward link api_permissions 2020-04-02 12:56:36 +02:00
Badlop 05b68764cc Document some global options 2020-04-02 12:56:33 +02:00
Badlop 4e51e82ccf Add three missing mod_bosh options 2020-04-02 12:56:31 +02:00
Badlop 116fa8e9ca add missing mod_mam options 2020-04-02 12:56:28 +02:00
Badlop ce6fd654a0 Fix mod_pubsub indentation 2020-04-02 12:56:26 +02:00
Badlop 5ee2f48aea Add mod_pubsub configuration documentation 2020-04-02 12:56:23 +02:00
Paweł Chmielowski ccb47a67c4 Don't replace %25 in webadmin test on older erlangs
It seems that is a bug in R21+ httpc, so let's try to keep that test
working with older versions
2020-04-01 17:11:19 +02:00
Paweł Chmielowski a2e6d8bb6b Make stop_ejabberd test also work without receiving </stream:stream> 2020-04-01 15:34:06 +02:00
Paweł Chmielowski 1bd560f3f2 Fix potential message loss in terminating c2s sessions
Calling sync version of xmpp_stream_in/out:stop could lead to messages
never being processed by c2s process if they were queued in p1_server.

This could be reproduced by when having messages in offline storage,
starting sessions, enabling stream_mgmt, sending initial presence, and then immediately
</stream:stream>, messages that mod_offline would send process would not
be bounced back by stream_mgmt.
2020-04-01 14:36:01 +02:00
Badlop 222bb1d55d Use different username than other tests, but still include the test chars 2020-04-01 12:50:52 +02:00
Paweł Chmielowski a5ea3fa282 Better error reporting in pubsub tests 2020-04-01 11:45:01 +02:00
Paweł Chmielowski 6c52438128 Make webadmin tests use different user for changepassword/unregister
Using username that is shared with other tests causes login problems in
other places.
2020-04-01 11:44:38 +02:00
Badlop 0508dce2ed Add more webadmin tests 2020-03-31 19:28:36 +02:00
Boris Chernov 87dda1b638 sql_type should be taken for LServer, not LHost (#3202)
sql_type option should be retrieved for the main domain, not the MUC subdomain
2020-03-30 09:47:36 +02:00
Paweł Chmielowski 5ec214386e Make webadmin redirect to page that end with / 2020-03-26 14:17:48 +01:00
Paweł Chmielowski 73ba38ae35 Revert "Pass base path instead of level to support URL missing slash (#3177)"
This reverts commit e9d1201ea8.
2020-03-26 13:43:24 +01:00
Paweł Chmielowski 1ffa9a0cf5 Do not change to attribute of sent messages from bare to full jid
This is not correct per xmpp spec
2020-03-25 16:00:16 +01:00
Jerome Sautret 633b362577 Increase version to 20.3.0 2020-03-25 11:35:38 +01:00
Badlop 150b7e7219 Fix unsubscribe command result, handle_sync_event result, and dialyzer
How to reproduce the problems fixed by this commit:
Create temporary room, other account subscribes, and owner leaves
Unsubscribe that account with the command: ejabberdctl unsubscribe_room ...
2020-03-24 11:44:22 +01:00
Paweł Chmielowski e6065bf08f Update changelog 2020-03-23 17:55:11 +01:00
Paweł Chmielowski c2aa5f77bf Update mix.lock 2020-03-23 17:42:57 +01:00
Paweł Chmielowski 7caec56e96 Make bounce_message_queue wait for 100ms for incoming messages
There is possibilty that between c2s process unregistering itself from sm
and terminating, some other process could try to send something to c2s,
which could result in messages to triggering mam/offline hooks, and causing
them not to be stored in any way.
2020-03-23 15:16:33 +01:00
Paweł Chmielowski 97354426cf Make mod_muc_room:unsubscirbe handle that unsubscribe may stop room 2020-03-23 13:16:48 +01:00
Paweł Chmielowski 63e3fb92d1 Better handling of xml parse errors in send_stanza 2020-03-23 12:59:30 +01:00
Paweł Chmielowski a2d1ffffe6 Add baisc tests for webadmin 2020-03-23 10:52:07 +01:00
Paweł Chmielowski f17d4c0adc Update deps 2020-03-19 12:11:46 +01:00
Paweł Chmielowski 92a09fdb71 Also add "escape '\'" to prepared statements in pgsqllike_escape 2020-03-18 14:36:17 +01:00
Paweł Chmielowski 039d786e1f Add escape '\' to like expression in pgsql to fix problem cockroachdb
Cockroachdb doesn't properly handle escaping of _ in like expressions,
having "like ... escape '\'" makes it work, by disabling optimization that
causes this broken behaviour
2020-03-18 14:31:13 +01:00
Paweł Chmielowski 2d707cc0d2 Fix type of computed field in node_flat sql query 2020-03-18 14:05:05 +01:00
Paweł Chmielowski 0a88d03dc9 Use correct type for seconds field in mod_last sql queries 2020-03-18 14:05:05 +01:00
Paweł Chmielowski f12ee28660 Change conversion of boolean values for cockroachdb 2020-03-18 14:05:05 +01:00
Badlop 260c289d34 Fix Dialyzer warning that jid can't be 'undefined' 2020-03-18 12:02:16 +01:00
Paweł Chmielowski d8899ca9ac Add cache to mod_shared_roster
This should help with excessive queries that sql backend generates
Should fix issue #3158.
2020-03-17 14:35:43 +01:00
Paweł Chmielowski 1e456065f6 Fix issue with family field on cockroachdb 2020-03-17 11:35:54 +01:00
Paweł Chmielowski 82074190fb Replace mod_shared_roster:X call with just X inside that module 2020-03-16 14:57:55 +01:00
Paweł Chmielowski 6fe7c5cac5 Try to limit calls to groups_with_opts in mod_shared_roster 2020-03-16 13:29:05 +01:00
Badlop e9d1201ea8 Pass base path instead of level to support URL missing slash (#3177) 2020-03-11 16:26:33 +01:00
Paweł Chmielowski 9a89b360c0 fix command rooms_empty_destroy (#3183) 2020-03-05 11:41:51 +01:00
Paweł Chmielowski b39a1e2d74 Add reload handler to ejabberd_auth_ldap
This will restart ldap process with new options, and should made it
recognize new values.

This fixes issue #3181
2020-03-04 13:19:41 +01:00
Paweł Chmielowski 151b818af4 Use compilation flags used during build to compile modules in ext_mod
This fixes issue #3178
2020-03-03 11:25:17 +01:00
Paweł Chmielowski df47e2a93f Fix list parameters in sql queries on pgsql 2020-02-27 11:10:30 +01:00
Mickaël Rémond d0e93f9219 Merge pull request #3125 from area-42/enable_odbc_in_mix
enable odbc in mix build
2020-02-26 14:45:01 +01:00
Badlop 47c5aba1e5 Allow mod_register_web to be accessed from now-served vhosts (#3173) 2020-02-26 13:57:19 +01:00
Badlop 00abf5d42c Fix handle of 'http' atom in Headers, problem introduced in 357e7e11 2020-02-26 13:56:38 +01:00
Paweł Chmielowski 9c25d1024a Support ssl connection on mysql 2020-02-26 10:54:04 +01:00
Christoph Scholz 248cc2d013 change publisher from text to varchar for mssql 2019-12-28 15:49:37 +01:00
Christoph Scholz 8eccbade56 enable odbc in mix build 2019-12-25 00:38:48 +01:00
142 changed files with 5796 additions and 2622 deletions
+7 -2
View File
@@ -2,10 +2,15 @@ language: erlang
otp_release:
- 19.3
- 22.2
- 22.3
- 23.0
os: linux
dist: xenial
services:
- redis-server
- redis
- postgresql
before_install:
+47
View File
@@ -1,3 +1,50 @@
# Version 20.07
* Changes in this version
- Add support for using unix sockets in listeners.
- Make this version compatible with erlang R23
- Make room permissions checks more strict for subscribers
- Fix problem with muc rooms crashing when using muc logger
with some locales
- Limit stat calls that logger module issues
- Don't throw errors when using user_regexp acl rule and
having non-matching host
- Fix problem with leaving old data when updating shared rosters
- Fix edge case that caused failure of resuming old sessions with
stream management.
- Fix crash when room that was started with loging enabled was later
changed to logging disabled
- Increase default shaper limits (this should help with delays for
clients that are using jingle)
- Fix couple compatibility problems which prevented working on
erlang R19
- Fix sending presence unavailable when session terminates for
clients that only send directed presences (helps with sometimes
not leaving muc rooms on disconnect).
- Prevent supervisor errors for sockets that were closed before
they were passed to handler modules
- Make stun module work better with ipv6 addresses
# Version 20.03
* Changes in this version
- Add support of ssl connection when connection to mysql
database (configured with `sql_ssl: true` option)
- Experimental support for cockroachdb when configured
with postgres connector
- Add cache and optimize queries issued by `mod_shared_roster`,
this should greatly improve performance of this module when
used with `sql` backend
- Fix problem with accessing webadmin
- Make webadmin work even when url is missing trailing slash
- When compiling external modules with ext_mod, use flags
that were detected during compilation of ejabberd
- Make config changed to ldap options be updated when issued
`reload_config` command
- Fix `room_empty_destory` command
- Fix reporting errors in `send_stanza` command when xml
passed to it couldn't be passed correctly
# Version 20.02
* Changes in this version
+6 -6
View File
@@ -14,24 +14,24 @@ solutions very cost effectively.
Key Features
------------
- **Cross-platform**
- **Cross-platform**
ejabberd runs under Microsoft Windows and Unix-derived systems such as
Linux, FreeBSD and NetBSD.
- **Distributed**
- **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**
- **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**
- **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.
@@ -46,13 +46,13 @@ Key Features
- Can integrate with existing authentication mechanisms.
- Capability to send announce messages.
- **Internationalized**
- **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**
- **Open Standards**
ejabberd is the first Open Source Jabber server claiming to fully comply to
the XMPP standard.
- Fully XMPP-compliant.
+170 -169
View File
@@ -35,18 +35,6 @@ AC_PATH_TOOL(EPMD, epmd, , [${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
@@ -68,45 +56,9 @@ fi
# Change default prefix
AC_PREFIX_DEFAULT(/usr/local)
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(new_sql_schema,
[AC_HELP_STRING([--enable-new-sql-schema], [use new SQL schema (default: no)])],
[case "${enableval}" in
yes) new_sql_schema=true ;;
no) new_sql_schema=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-new-sql-schema) ;;
esac],[new_sql_schema=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_CONFIG_FILES([Makefile
vars.config
src/ejabberd.app.src])
AC_ARG_ENABLE(all,
[AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-redis --enable-elixir --enable-stun --enable-sip --enable-debug --enable-tools (useful for Dialyzer checks, default: no)])],
@@ -116,69 +68,13 @@ AC_ARG_ENABLE(all,
*) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;;
esac],[])
AC_ARG_ENABLE(tools,
[AC_HELP_STRING([--enable-tools], [build development tools (default: no)])],
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])],
[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(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])
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(elixir,
[AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])],
@@ -188,63 +84,26 @@ AC_ARG_ENABLE(elixir,
*) AC_MSG_ERROR(bad value ${enableval} for --enable-elixir) ;;
esac],[if test "x$elixir" = "x"; then elixir=false; fi])
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])],
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
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) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
esac],[if test "x$debug" = "x"; then debug=true; fi])
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(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_ARG_ENABLE(system_deps,
[AC_HELP_STRING([--enable-system-deps], [makes rebar use localy installed dependences instead of downloading them (default: no)])],
[case "${enableval}" in
yes) system_deps=true ;;
no) system_deps=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-system-deps) ;;
esac],[if test "x$system_deps" = "x"; then system_deps=false; fi])
AC_ARG_ENABLE(stun,
[AC_HELP_STRING([--enable-stun], [enable STUN/TURN support (default: no)])],
[case "${enableval}" in
yes) stun=true ;;
no) stun=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-stun) ;;
esac],[if test "x$stun" = "x"; then stun=false; fi])
AC_ARG_ENABLE(sip,
[AC_HELP_STRING([--enable-sip], [enable SIP support (default: no)])],
[case "${enableval}" in
yes) sip=true ;;
no) sip=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-sip) ;;
esac],[if test "x$sip" = "x"; then sip=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
ENABLEGROUP=""
AC_ARG_ENABLE(group,
[AS_HELP_STRING([--enable-group[[[[=GROUP]]]]], [allow this system group to start ejabberd (default: no)])],
@@ -259,6 +118,148 @@ if test "$ENABLEGROUP" != ""; then
AC_SUBST([INSTALLGROUP], [$ENABLEGROUP])
fi
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(latest_deps,
[AC_HELP_STRING([--enable-latest-deps], [makes rebar use latest commits for dependencies 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_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; mssql=true ;;
no) db_type=generic; mssql=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
esac],[db_type=generic])
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(new_sql_schema,
[AC_HELP_STRING([--enable-new-sql-schema], [use new SQL schema (default: no)])],
[case "${enableval}" in
yes) new_sql_schema=true ;;
no) new_sql_schema=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-new-sql-schema) ;;
esac],[new_sql_schema=false])
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(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(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(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(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(sip,
[AC_HELP_STRING([--enable-sip], [enable SIP support (default: no)])],
[case "${enableval}" in
yes) sip=true ;;
no) sip=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-sip) ;;
esac],[if test "x$sip" = "x"; then sip=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(stun,
[AC_HELP_STRING([--enable-stun], [enable STUN/TURN support (default: yes)])],
[case "${enableval}" in
yes) stun=true ;;
no) stun=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-stun) ;;
esac],[if test "x$stun" = "x"; then stun=true; fi])
AC_ARG_ENABLE(system_deps,
[AC_HELP_STRING([--enable-system-deps], [makes rebar use locally installed dependencies instead of downloading them (default: no)])],
[case "${enableval}" in
yes) system_deps=true ;;
no) system_deps=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-system-deps) ;;
esac],[if test "x$system_deps" = "x"; then system_deps=false; fi])
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])
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
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])
if test "$sqlite" = "true"; then
AX_LIB_SQLITE3([3.6.19])
if test "x$SQLITE3_VERSION" = "x"; then
@@ -267,7 +268,7 @@ if test "$sqlite" = "true"; then
fi
enabled_backends=""
for backend in odbc mysql pgsql sqlite redis; do
for backend in odbc mysql pgsql sqlite redis mssql; do
if eval test x\${$backend} = xtrue; then
if test "x$enabled_backends" = "x"; then
enabled_backends=$backend
+23 -6
View File
@@ -57,6 +57,16 @@ listen:
request_handlers:
/admin: ejabberd_web_admin
/.well-known/acme-challenge: ejabberd_acme
-
port: 3478
ip: "::"
transport: udp
module: ejabberd_stun
use_turn: true
## The server's public IPv4 address:
# turn_ipv4_address: "203.0.113.3"
## The server's public IPv6 address:
# turn_ipv6_address: "2001:db8::3"
-
port: 1883
ip: "::"
@@ -100,14 +110,14 @@ api_permissions:
who:
access:
allow:
acl: loopback
acl: admin
- acl: loopback
- acl: admin
oauth:
scope: "ejabberd:admin"
access:
allow:
acl: loopback
acl: admin
- acl: loopback
- acl: admin
what:
- "*"
- "!stop"
@@ -120,8 +130,10 @@ api_permissions:
- connected_users_number
shaper:
normal: 1000
fast: 50000
normal:
rate: 3000
burst_size: 20000
fast: 100000
shaper_rules:
max_user_sessions: 10
@@ -150,6 +162,10 @@ modules:
mod_http_api: {}
mod_http_upload:
put_url: https://@HOST@:5443/upload
custom_headers:
"Access-Control-Allow-Origin": "https://@HOST@"
"Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
"Access-Control-Allow-Headers": "Content-Type"
mod_last: {}
mod_mam:
## Mnesia is limited to 2GB, better to use an SQL backend
@@ -203,6 +219,7 @@ modules:
mod_shared_roster: {}
mod_stream_mgmt:
resend_on_timeout: if_offline
mod_stun_disco: {}
mod_vcard: {}
mod_vcard_xupdate: {}
mod_version:
-2
View File
@@ -63,8 +63,6 @@
#.
#' 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
+13 -1
View File
@@ -60,6 +60,8 @@ done
: "${SPOOL_DIR:="{{localstatedir}}/lib/ejabberd"}"
: "${EJABBERD_CONFIG_PATH:="$ETC_DIR/ejabberd.yml"}"
: "${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR/ejabberdctl.cfg"}"
# Allows passing extra Erlang command-line arguments in vm.args file
: "${VMARGS:="$ETC_DIR/vm.args"}"
[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH"
[ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG"
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
@@ -77,6 +79,8 @@ if [ -n "$INET_DIST_INTERFACE" ] ; then
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2"
fi
fi
# if vm.args file exists in config directory, pass it to Erlang VM
[ -f "$VMARGS" ] && ERLANG_OPTS="$ERLANG_OPTS -args_file $VMARGS"
ERL_LIBS={{libdir}}
ERL_CRASH_DUMP="$LOGS_DIR"/erl_crash_$(date "+%Y%m%d-%H%M%S").dump
ERL_INETRC="$ETC_DIR"/inetrc
@@ -126,6 +130,14 @@ exec_iex()
# usage
debugwarning()
{
if [ "$OSTYPE" != "cygwin" ] && [ "$OSTYPE" != "win32" ]; then
if [ "a$TERM" == "a" ] || [ "$TERM" == "dumb" ] ; then
echo "Terminal type not supported."
echo "You may have to set the TERM environnement variable to fix this."
exit 8
fi
fi
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
echo "--------------------------------------------------------------------"
echo ""
@@ -198,7 +210,7 @@ uid()
uuid=$(uuidgen 2>/dev/null)
[ -z "$uuid" ] && [ -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid)
[ -z "$uuid" ] && uuid=$(printf "%X" "${RANDOM:-$$}$(date +%M%S)")
uuid=${uuid%%-*}
uuid=$(printf '%s' $uuid | sed 's/^\(...\).*$/\1/')
[ $# -eq 0 ] && echo "${uuid}-${ERLANG_NODE}"
[ $# -eq 1 ] && echo "${uuid}-${1}-${ERLANG_NODE}"
[ $# -eq 2 ] && echo "${uuid}-${1}@${2}"
+1
View File
@@ -21,6 +21,7 @@
-record(request,
{method :: method(),
path = [] :: [binary()],
raw_path :: binary(),
q = [] :: [{binary() | nokey, binary()}],
us = {<<>>, <<>>} :: {binary(), binary()},
auth :: {binary(), binary()} | {oauth, binary(), []} | undefined | invalid,
+2 -2
View File
@@ -93,9 +93,9 @@
-define(GL(Ref, Title),
?XAE(<<"div">>, [{<<"class">>, <<"guidelink">>}],
[?XAE(<<"a">>,
[{<<"href">>, <<"https://docs.ejabberd.im/admin/configuration/#", Ref/binary>>},
[{<<"href">>, <<"https://docs.ejabberd.im/admin/configuration/", Ref/binary>>},
{<<"target">>, <<"_blank">>}],
[?C(<<"[Guide: ", Title/binary, "]">>)])])).
[?C(<<"docs: ", Title/binary>>)])])).
%% h1 with a Guide Link
-define(H1GL(Name, Ref, Title),
+1178 -74
View File
File diff suppressed because it is too large Load Diff
+22 -8
View File
@@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do
def project do
[app: :ejabberd,
version: "20.2.0",
version: "20.4.0",
description: description(),
elixir: "~> 1.4",
elixirc_paths: ["lib"],
@@ -51,12 +51,25 @@ defmodule Ejabberd.Mixfile do
end
end
defp if_version_below(ver, okResult) do
if :erlang.system_info(:otp_release) < ver do
okResult
else
[]
end
end
defp erlc_options do
# Use our own includes + includes from all dependencies
includes = ["include"] ++ deps_include(["fast_xml", "xmpp", "p1_utils"])
[:debug_info, {:d, :ELIXIR_ENABLED}] ++ cond_options() ++ Enum.map(includes, fn(path) -> {:i, path} end) ++
if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
if_function_exported(:erl_error, :format_exception, 6, [{:d, :HAVE_ERL_ERROR}])
result = [:debug_info, {:d, :ELIXIR_ENABLED}] ++
cond_options() ++
Enum.map(includes, fn (path) -> {:i, path} end) ++
if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
if_version_below('22', [{:d, :LAGER}]) ++
if_function_exported(:erl_error, :format_exception, 6, [{:d, :HAVE_ERL_ERROR}])
defines = for {:d, value} <- result, do: {:d, value}
result ++ [{:d, :ALL_DEFS, defines}]
end
defp cond_options do
@@ -72,17 +85,17 @@ defmodule Ejabberd.Mixfile do
[{:lager, "~> 3.6.0"},
{:p1_utils, "~> 1.0"},
{:fast_xml, "~> 1.1"},
{:xmpp, "~> 1.4"},
{:xmpp, ">= 1.4.6"},
{:cache_tab, "~> 1.0"},
{:stringprep, "~> 1.0"},
{:fast_yaml, "~> 1.0"},
{:fast_tls, "~> 1.1"},
{:stun, "~> 1.0"},
{:esip, "~> 1.0"},
{:stun, "~> 1.0.34"},
{:esip, "~> 1.0.32"},
{:p1_mysql, "~> 1.0"},
{:mqtree, "~> 1.0"},
{:p1_pgsql, "~> 1.1"},
{:jiffy, "~> 1.0"},
{:jiffy, "~> 1.0.4"},
{:p1_oauth2, "~> 0.6.1"},
{:distillery, "~> 2.0"},
{:pkix, "~> 1.0"},
@@ -120,6 +133,7 @@ defmodule Ejabberd.Mixfile do
defp cond_apps do
for {:true, app} <- [{config(:redis), :eredis},
{config(:mysql), :p1_mysql},
{config(:odbc), :odbc},
{config(:pgsql), :p1_pgsql},
{config(:sqlite), :sqlite3},
{config(:zlib), :ezlib}], do:
+36 -35
View File
@@ -1,38 +1,39 @@
%{
"artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm"},
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
"cache_tab": {:hex, :cache_tab, "1.0.22", "ad16577e7f26709cacdcb86e6a4960c8d158cab9d189cdf49cc1e2dc33106a70", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm"},
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm"},
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"epam": {:hex, :epam, "1.0.6", "6e57e1f5a330fa02a08ee0d4b16d9161f95177351e48c6dfede2f89b7e2f589f", [:rebar3], [], "hexpm"},
"artificery": {:hex, :artificery, "0.4.3", "0bc4260f988dcb9dda4b23f9fc3c6c8b99a6220a331534fdf5bf2fd0d4333b02", [:mix], [], "hexpm", "12e95333a30e20884e937abdbefa3e7f5e05609c2ba8cf37b33f000b9ffc0504"},
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm", "fab09b20e3f5db886725544cbcf875b8e73ec93363954eb8a1a9ed834aa8c1f9"},
"cache_tab": {:hex, :cache_tab, "1.0.25", "1e94d4d38ad18abd92f0d076bd4bab0f3b7189e28927c358beea0c5c2ea9d2ae", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "cd04c19ffa1b8ba34611668cea28b1a76536ec2246f5ffb77697a4a0111c70dc"},
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm", "bbc7008b0161a6f130d8d903b5b3232351fccc9c31a991f8fcbf2a12ace22995"},
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
"earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"},
"eimp": {:hex, :eimp, "1.0.17", "3d62a8edf67b204a200c92b099125bada62fc4b2d348fe186e775014df31e6e5", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "c241c79cf5149d477ba613114d4d95d346f145fade70bdd657b03fd5dc9fcdc5"},
"epam": {:hex, :epam, "1.0.7", "55889bbfdc5ab9f2e785a710229f34e550784c5ead1960d7839ea77514aef44d", [:rebar3], [], "hexpm", "6b029ebd2b244bc339cbf5cb5908d0f2d50e43f33a6e7f70818912ea5d3fd596"},
"eredis": {:hex, :eredis, "1.2.0", "0b8e9cfc2c00fa1374cd107ea63b49be08d933df2cf175e6a89b73dd9c380de4", [:rebar3], [], "hexpm"},
"esip": {:hex, :esip, "1.0.32", "b6d5d9eb8342b86509de02ac79e6a9a772dab011e936092441d4e92a7986ca29", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.31", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"ezlib": {:hex, :ezlib, "1.0.7", "c8adffd32e66831df77955d163d705cdcf0a3d66762e6f68f8123012e714bf05", [:rebar3], [], "hexpm"},
"fast_tls": {:hex, :fast_tls, "1.1.4", "a0320baf14be72fc9f99211543e411bb98077bf72c42e2d86fc4e2c10d60c258", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_xml": {:hex, :fast_xml, "1.1.39", "687080c0190a8c45d564a3576201f1a89f31ae413dd700a2def0821736f98d4d", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_yaml": {:hex, :fast_yaml, "1.0.23", "0c74d6274c232609467bf55563066840c265e70081ee0c23215d1f3ca2624dfc", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"jiffy": {:hex, :jiffy, "1.0.1", "4f25639772ca41202f41ba9c8f6ca0933554283dd4742c90651e03471c55e341", [:rebar3], [], "hexpm"},
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm"},
"lager": {:hex, :lager, "3.6.10", "6172b43ab720ac33914ccd0aeb21fdbdf88213847707d4b91e6af57b2ae5c4d2", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm"},
"luerl": {:hex, :luerl, "0.3.1", "5412807630aac1aaf59ffe5a1bc09259c447b4faeb1d3fe2d4ef41b87676cb04", [:rebar3], [], "hexpm"},
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
"mqtree": {:hex, :mqtree, "1.0.7", "0d8f6101eb2bb6a6e27f0e5a60cfad04b27dd552e75f30294e565605ce7cd0d2", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm"},
"p1_acme": {:hex, :p1_acme, "1.0.4", "2d118dbc38e7bc8eda34f4c5bf7afa6bce1345affc022bba514f42e194818820", [:rebar3], [{:idna, "~>6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~>1.0.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~>1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~>1.0.3", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm"},
"p1_mysql": {:hex, :p1_mysql, "1.0.13", "6a17bfd7a33d035673d633572e93370bdd2fcf4077362ed13b1a8fd8176a1643", [:rebar3], [], "hexpm"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.6", "b17053bd7a34621f9a1a7327285a3e37abd38eb1d176afccc8cfc39882ff0a44", [:rebar3], [], "hexpm"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.9", "07ff9b037954dec06b4e30e33a82ac69a5a513e2860d2e59b7f6f4af23493c45", [:rebar3], [], "hexpm"},
"p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm"},
"pkix": {:hex, :pkix, "1.0.5", "407c02c70191d0791cd9b422ac2380df5f7f8304ec26a6d3b06e0e02be688fca", [:rebar3], [], "hexpm"},
"sqlite3": {:hex, :sqlite3, "1.1.6", "4ea71af0b45908b5f02c9b09e4c87177039ef404f20accb35049cd8924cc417c", [:rebar3], [], "hexpm"},
"stringprep": {:hex, :stringprep, "1.0.19", "79761de42960a625fb0cd6d31686f6118aef30540a7abb884b92f72861b6adde", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"stun": {:hex, :stun, "1.0.31", "577d845d4b77b155bad234598c2056f6e182f178468727de083bedf275dc83a1", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
"xmpp": {:hex, :xmpp, "1.4.5", "b226baa9ad960e8de041289b94bbcb6148a7980acc0c1ec58dfc8f24acded3ad", [:rebar3], [{:ezlib, "1.0.7", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.39", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.19", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm"},
"yconf": {:hex, :yconf, "1.0.3", "7f71d0fe0e95ecb0f4004acee7b7db46c13e38c216d0bd03ef2a595a898d21a3", [:rebar3], [{:fast_yaml, "1.0.23", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm"},
"esip": {:hex, :esip, "1.0.37", "eb26a0bceda2019c40fd6ac3935f8d7f76c1a36fdd89ed2e3356696d33503737", [:rebar3], [{:fast_tls, "1.1.8", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.37", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "19bacbf089aaa2c11a59c1daffd7819d7917baf457a8ee67f969a99d76160714"},
"ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"},
"ezlib": {:hex, :ezlib, "1.0.8", "9bd3a4d905c4694da5054aefe0113303c6ad56701f6625bde94b4bcc06e50dc9", [:rebar3], [], "hexpm", "852c2b2fe0166d5e7454fa7667cafcb0dadb9d6571b3808a93cf935c0a39e4ef"},
"fast_tls": {:hex, :fast_tls, "1.1.8", "d8f78d433b7cfae0548c2bc00b9ca4f9644ba894834ae34a0d2b39c8c97a316b", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "6cca3c9b14c2bcacbeb271959adc9f655707b301b7a483438c77c20068121668"},
"fast_xml": {:hex, :fast_xml, "1.1.43", "a3b1a14270bae7191e9fcd42628d5987642632a9b28604937c51b55094c387c1", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "78651c9eedb88322a0359a213a6e68b65d1c88d5738f37650030588599677a32"},
"fast_yaml": {:hex, :fast_yaml, "1.0.27", "c6b2fda782d0987f0d5463f42c44a2f220ae88ac1d8eae98f75e260f6c8a9739", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "51177f885466546bea70eadd9775610f008930b3de61a18901ff223de6e70f30"},
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm", "99cb4128cffcb3227581e5d4d803d5413fa643f4eb96523f77d9e6937d994ceb"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
"jiffy": {:hex, :jiffy, "1.0.4", "72adeff75c52a2ff07de738f0813768abe7ce158026cc1115a170340259c0caa", [:rebar3], [], "hexpm", "113e5299ee4e6b9f40204256d7bbbd1caf646edeaef31ef0f7f5f842c0dad39e"},
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm", "6429c4fee52b2dda7861ee19a4f09c8c1ffa213bee3a1ec187828fde95d447ed"},
"lager": {:hex, :lager, "3.6.10", "6172b43ab720ac33914ccd0aeb21fdbdf88213847707d4b91e6af57b2ae5c4d2", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm", "5d10499461826b79c5abee18bb594b3949cbdf76d9d9fd7e66d0a558137c21c9"},
"luerl": {:hex, :luerl, "0.3.1", "5412807630aac1aaf59ffe5a1bc09259c447b4faeb1d3fe2d4ef41b87676cb04", [:rebar3], [], "hexpm", "1bc011c7297e43aec762e53b17ecb15b0ff29f9546cd153110b343cf5b043f5f"},
"makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
"mqtree": {:hex, :mqtree, "1.0.10", "224c74694c3720da707eda6c0863dbb21a6a74dd56b606534e511b58dd6aba62", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "e8d2c37e0fa6c69ba168c0cb8130ae92d3042bafc363cee346cb5602ff17b2fa"},
"nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
"p1_acme": {:hex, :p1_acme, "1.0.6", "0b007b776331e3d6effe700fa85d63236a98dc4e6e8c3abbbf816d1bec70df3f", [:rebar3], [{:idna, "~>6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~>1.0.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~>1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~>1.0.5", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "7cc6528cbbe7a98929e954604ec670de56ca9f7a69a14d22166e8746fbe86f10"},
"p1_mysql": {:hex, :p1_mysql, "1.0.16", "ef063cd8cc85fd902568a82839b359fdf3d83b27cd13fbcc4fb3a3edcd728b6b", [:rebar3], [], "hexpm", "e68e861043dc311f35e2bf8b97812b654c3d91488cc4aa3084d45c7366fe1555"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.7", "28a1c3ba36d6ccf5b054604ef4cde47358c835f93a260fb216e9b257ca1a478b", [:rebar3], [], "hexpm", "2768d7659f213b143279fa2c1ee07101df3d24b177eb79cf175afd9fcffd01e2"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.10", "e4b19c9768ef4047f9c56090a91bfefc7337abb3809a28aa4a6538eef6ad76b0", [:rebar3], [], "hexpm", "5458c0db9e47425f8cc1f592356a29359267c624785b316b34a46ad7439e9367"},
"p1_utils": {:hex, :p1_utils, "1.0.20", "559313c0ea267a646317fd122cdfbb041db86b1ed00df91902fd273ce08d4a45", [:rebar3], [], "hexpm", "0b2c98edfe3e82dd49b287a70913f265e09eb630e40774bee88e0a9f06b0c061"},
"pkix": {:hex, :pkix, "1.0.6", "f2b64118a25c5f80064b60a235eb299f44dd9b33a554e42df5369eae3d23c12f", [:rebar3], [], "hexpm", "9082d29e9abc965f763f1c7d7e90408dc6de91f5c1886228c3500fedf2ee183c"},
"sqlite3": {:hex, :sqlite3, "1.1.6", "4ea71af0b45908b5f02c9b09e4c87177039ef404f20accb35049cd8924cc417c", [:rebar3], [], "hexpm", "cf9fa59c5b27de0d5d94a2ef464521379e23d8c6e9fa939abf8415c767f514bb"},
"stringprep": {:hex, :stringprep, "1.0.22", "c6389cb635930044bc60973925d17abe9f259edba0a3dd155cccae2db79c0c52", [:rebar3], [{:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "956c5909016532d0445f1eb73bb15a1d81bf46ee452b92fdf67993becb5549cf"},
"stun": {:hex, :stun, "1.0.37", "30c7012cd2a48de4177283aeb13719f84e8570f0b97b791c476bc384605a4c83", [:rebar3], [{:fast_tls, "1.1.8", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "9f46745405f495446817908fe735fb1e2c38eb776021cbda44cc18cab0b16ede"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"},
"xmpp": {:hex, :xmpp, "1.4.9", "4b33ba41f9efc2eb2c4b89a9c3aac61aa0d2e5efafd681c37caa23a2bc2bc6ad", [:rebar3], [{:ezlib, "1.0.8", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.8", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.43", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.20", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.22", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "e4958505ff4e2e4cd0aa6a7cb18d19ace7bf4450be8c0b375522fb4ca623c529"},
"yconf": {:hex, :yconf, "1.0.7", "941fa712f7c01f0e5649c5cf9b2787853802bc406dc3b6a80417475b1d63d209", [:rebar3], [{:fast_yaml, "1.0.27", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "8b09f5249b9197f0c542eb67a05b9d50e8f98df08c9dac11ce2c80fbabe05e5e"},
}
-1
View File
@@ -243,7 +243,6 @@ p[dir=ltr] a {
background: #3eaffa;
text-transform: uppercase;
font-size: 0.75em;
color: #fff;
}
+18 -16
View File
@@ -60,7 +60,7 @@
{"Client acknowledged more stanzas than sent by server","El client ha reconegut més paquets dels que ha enviat el servidor"}.
{"Commands","Comandaments"}.
{"Conference room does not exist","La sala de conferències no existeix"}.
{"Configuration of room ~ts","Configuració de la sala ~ts"}.
{"Configuration of room ~s","Configuració de la sala ~s"}.
{"Configuration","Configuració"}.
{"Connected Resources:","Recursos connectats:"}.
{"Country","Pais"}.
@@ -79,7 +79,8 @@
{"Delete User","Eliminar Usuari"}.
{"Description:","Descripció:"}.
{"Disc only copy","Còpia sols en disc"}.
{"Displayed Groups:","Mostrar grups:"}.
{"'Displayed groups' not added (they do not exist!): ","'Mostrats' no afegits (no existeixen!): "}.
{"Displayed:","Mostrats:"}.
{"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"}.
@@ -116,7 +117,7 @@
{"Failed to extract JID from your voice request approval","No s'ha pogut extraure el JID de la teva aprovació de petició de veu"}.
{"Failed to map delegated namespace to external component","Ha fallat mapejar la delegació de l'espai de noms al component extern"}.
{"Failed to parse HTTP response","Ha fallat el processat de la resposta HTTP"}.
{"Failed to process option '~ts'","Ha fallat el processat de la opció '~ts'"}.
{"Failed to process option '~s'","Ha fallat el processat de la opció '~s'"}.
{"Family Name","Cognom"}.
{"February","Febrer"}.
{"File larger than ~w bytes","El fitxer es més gran que ~w bytes"}.
@@ -132,7 +133,7 @@
{"Get User Password","Obtenir Contrasenya d'usuari"}.
{"Get User Statistics","Obtenir Estadístiques d'Usuari"}.
{"Given Name","Nom propi"}.
{"Group ","Grup "}.
{"Group","Grup"}.
{"Groups","Grups"}.
{"has been banned","ha sigut bloquejat"}.
{"has been kicked because of a system shutdown","ha sigut expulsat perquè el sistema va a apagar-se"}.
@@ -169,7 +170,7 @@
{"Invitations are not allowed in this conference","Les invitacions no estan permeses en aquesta sala de conferència"}.
{"IP addresses","Adreça IP"}.
{"is now known as","ara es conegut com"}.
{"It is not allowed to send error messages to the room. The participant (~ts) has sent an error message (~ts) and got kicked from the room","No està permés enviar missatges d'error a la sala. El participant (~ts) ha enviat un missatge d'error (~ts) i ha sigut expulsat de la sala"}.
{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","No està permés enviar missatges d'error a la sala. El participant (~s) ha enviat un missatge d'error (~s) i ha sigut expulsat de la sala"}.
{"It is not allowed to send private messages 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"}.
{"It is not allowed to send private messages","No està permés enviar missatges privats"}.
@@ -181,6 +182,7 @@
{"joins the room","entra a la sala"}.
{"July","Juliol"}.
{"June","Juny"}.
{"Label:","Etiqueta:"}.
{"Last Activity","Última activitat"}.
{"Last login","Últim login"}.
{"Last month","Últim mes"}.
@@ -200,7 +202,7 @@
{"March","Març"}.
{"Maximum Number of Occupants","Número màxim d'ocupants"}.
{"May","Maig"}.
{"Members not added (inexistent vhost): ","Membres no afegits (perque el vhost no existeix): "}.
{"Members not added (inexistent vhost!): ","Membres no afegits (perquè el vhost no existeix): "}.
{"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."}.
@@ -224,7 +226,7 @@
{"New Password:","Nova Contrasenya:"}.
{"Nickname can't be empty","El sobrenom no pot estar buit"}.
{"Nickname Registration at ","Registre del sobrenom en "}.
{"Nickname ~ts does not exist in the room","El sobrenom ~ts no existeix a la sala"}.
{"Nickname ~s does not exist in the room","El sobrenom ~s no existeix a la sala"}.
{"Nickname","Sobrenom"}.
{"No address elements found","No s'han trobat elements d'adreces ('address')"}.
{"No addresses element found","No s'ha trobat l'element d'adreces ('addresses')"}.
@@ -349,6 +351,7 @@
{"Roster","Llista de contactes"}.
{"RPC Call Error","Error de cridada RPC"}.
{"Running Nodes","Nodes funcionant"}.
{"~s invites you to the room ~s","~s et convida a la sala ~s"}.
{"Saturday","Dissabte"}.
{"Script check","Comprovar script"}.
{"Search Results for ","Resultats de la búsqueda "}.
@@ -409,12 +412,12 @@
{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Aquesta pàgina permet crear un compte Jabber en aquest servidor Jabber. El teu JID (Jabber IDentifier; Identificador Jabber) tindrà aquesta forma: usuari@servidor. Si us plau, llegeix amb cura les instruccions per emplenar correctament els camps."}.
{"This page allows to unregister a Jabber account in this Jabber server.","Aquesta pàgina permet anul·lar el registre d'un compte Jabber en aquest servidor Jabber."}.
{"This room is not anonymous","Aquesta sala no és anònima"}.
{"This service can not process the address: ~ts","Este servei no pot processar la direcció: ~ts"}.
{"This service can not process the address: ~s","Este servei no pot processar la direcció: ~s"}.
{"Thursday","Dijous"}.
{"Time delay","Temps de retard"}.
{"Timed out waiting for stream resumption","Massa temps esperant que es resumisca la connexió"}.
{"Time","Data"}.
{"To register, visit ~ts","Per a registrar-te, visita ~ts"}.
{"To register, visit ~s","Per a registrar-te, visita ~s"}.
{"To ~ts","A ~ts"}.
{"Token TTL","Token TTL"}.
{"Too many active bytestreams","N'hi ha massa Bytestreams actius"}.
@@ -422,7 +425,7 @@
{"Too many child elements","N'hi ha massa subelements"}.
{"Too many <item/> elements","N'hi ha massa elements <item/>"}.
{"Too many <list/> elements","N'hi ha massa elements <list/>"}.
{"Too many (~p) failed authentications from this IP address (~ts). The address will be unblocked at ~ts UTC","Massa autenticacions (~p) han fallat des d'aquesta adreça IP (~ts). L'adreça serà desbloquejada en ~ts UTC"}.
{"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 receiver fields were specified","S'han especificat massa camps de receptors"}.
{"Too many unacked stanzas","Massa missatges sense haver reconegut la seva recepció"}.
{"Too many users in this conference","N'hi ha massa usuaris en esta sala de conferència"}.
@@ -433,7 +436,6 @@
{"Transactions Committed:","Transaccions Realitzades:"}.
{"Transactions Logged:","Transaccions registrades:"}.
{"Transactions Restarted:","Transaccions reiniciades:"}.
{"~ts invites you to the room ~ts","~ts et convida a la sala ~ts"}.
{"~ts's Offline Messages Queue","~ts's cua de missatges offline"}.
{"Tuesday","Dimarts"}.
{"Unable to generate a CAPTCHA","No s'ha pogut generar un CAPTCHA"}.
@@ -467,12 +469,11 @@
{"User","Usuari"}.
{"Validate","Validar"}.
{"Value 'get' of 'type' attribute is not allowed","El valor 'get' a l'atribut 'type' no és permès"}.
{"Value of '~ts' should be boolean","El valor de '~ts' deuria ser booleà"}.
{"Value of '~ts' should be datetime string","El valor de '~ts' deuria ser una data"}.
{"Value of '~ts' should be integer","El valor de '~ts' deuria ser un numero enter"}.
{"Value of '~s' should be boolean","El valor de '~s' deuria ser booleà"}.
{"Value of '~s' should be datetime string","El valor de '~s' deuria ser una data"}.
{"Value of '~s' should be integer","El valor de '~s' deuria ser un numero enter"}.
{"Value 'set' of 'type' attribute is not allowed","El valor 'set' a l'atribut 'type' no és permès"}.
{"vCard User Search","vCard recerca d'usuari"}.
{"Virtual Hosting","Hosts virtuals"}.
{"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"}.
@@ -481,6 +482,7 @@
{"Wednesday","Dimecres"}.
{"Wrong parameters in the web formulary","Paràmetres incorrectes en el formulari web"}.
{"Wrong xmlns","El xmlns ès incorrecte"}.
{"XMPP Domains","Dominis XMPP"}.
{"You are being removed from the room because of a system shutdown","Has sigut expulsat de la sala perquè el sistema va a apagar-se"}.
{"You are not joined to the channel","No t'has unit al canal"}.
{"You can later change your password using a Jabber client.","Podràs canviar la teva contrasenya més endavant utilitzant un client Jabber."}.
@@ -494,5 +496,5 @@
{"Your contact offline message queue is full. The message has been discarded.","La teua 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 subscription request and/or messages to ~ts have been blocked. To unblock your subscription request, visit ~ts","La teua petició de subscripció i/o missatges a ~ts han sigut bloquejats. Per a desbloquejar-los, visita ~ts"}.
{"Your subscription request and/or messages to ~s have been blocked. To unblock your subscription request, visit ~s","La teua petició de subscripció i/o missatges a ~s han sigut bloquejats. Per a desbloquejar-los, visita ~s"}.
{"You're not allowed to create nodes","No tens permís per a crear nodes"}.
+366 -355
View File
File diff suppressed because it is too large Load Diff
+15 -25
View File
@@ -291,8 +291,7 @@ msgid "Configuration"
msgstr "Konfigurace"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Konfigurace místnosti ~s"
#: ejabberd_web_admin.erl:937
@@ -495,8 +494,7 @@ msgid "Failed to parse HTTP response"
msgstr "Chyba parsování HTTP odpovědi"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "Chyba při zpracování možnosti '~s'"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -565,8 +563,8 @@ msgid "Given Name"
msgstr "Křestní jméno"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Skupina "
msgid "Group"
msgstr "Skupina"
#: mod_roster.erl:956
msgid "Groups"
@@ -694,10 +692,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "Pozvánky nejsou povoleny v této místnosti"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Není povoleno posílat chybové zprávy do místnosti. Účastník (~s) odeslal "
"chybovou zprávu (~s) a byl vyhozen z místnosti"
@@ -933,8 +930,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Přezdívka ~s v místnosti neexistuje"
#: mod_muc_room.erl:3396
@@ -1767,8 +1763,7 @@ msgid "To"
msgstr "Pro"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "Pokud se chcete zaregistrovat, navštivte ~s"
#: mod_configure.erl:666
@@ -1781,10 +1776,9 @@ msgid "Token TTL"
msgstr "Token TTL"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr ""
"Příliš mnoho (~p) chybných pokusů o přihlášení z této IP adresy (~s). Adresa "
"bude zablokována do ~s UTC"
@@ -1996,19 +1990,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "Hodnota 'set' atrubutu 'type' není povolena"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "Hodnota '~s' by měla být boolean"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "Hodnota '~s' by měla být datetime řetězec"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "Hodnota '~s' by měla být celé číslo"
#: ejabberd_web_admin.erl:433
@@ -2109,10 +2100,9 @@ msgid ""
msgstr "Fronta offline zpráv pro váš kontakt je plná. Zpráva byla zahozena."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "Nesmíte posílat zprávy na ~s. Pro povolení navštivte ~s"
#: mod_disco.erl:438
+15 -25
View File
@@ -300,8 +300,7 @@ msgid "Configuration"
msgstr "Konfiguration"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Konfiguration für Raum ~s"
#: ejabberd_web_admin.erl:937
@@ -507,8 +506,7 @@ msgid "Failed to parse HTTP response"
msgstr "Konnte HTTP-Antwort nicht parsen"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "Konnte Option '~s' nicht verarbeiten"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -578,8 +576,8 @@ msgid "Given Name"
msgstr "Vorname"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Gruppe "
msgid "Group"
msgstr "Gruppe"
#: mod_roster.erl:956
msgid "Groups"
@@ -708,10 +706,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "Einladungen sind in dieser Konferenz nicht erlaubt"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Es ist nicht erlaubt Fehlermeldungen an den Raum zu senden. Der Teilnehmer "
"(~s) hat eine Fehlermeldung (~s) gesendet und wurde aus dem Raum gekickt"
@@ -949,8 +946,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Der Benutzername ~s existiert im Raum nicht"
#: mod_muc_room.erl:3396
@@ -1790,8 +1786,7 @@ msgid "To"
msgstr "An"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "Um sich anzumelden, besuchen Sie ~s"
#: mod_configure.erl:666
@@ -1804,10 +1799,9 @@ msgid "Token TTL"
msgstr "Token TTL"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"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."
@@ -2019,19 +2013,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "Wert 'set' des 'type'-Attributs ist nicht erlaubt"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "Wert von '~s' sollte boolesch sein"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "Wert von '~s' sollte datetime-String sein"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "Wert von '~s' sollte eine Ganzzahl sein"
#: ejabberd_web_admin.erl:433
@@ -2140,10 +2131,9 @@ msgstr ""
"verworfen."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"Ihre Nachrichten an ~s werden blockiert. Um dies zu ändern, besuchen Sie ~s"
+20 -29
View File
@@ -294,8 +294,7 @@ msgid "Configuration"
msgstr "Διαμόρφωση"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Διαμόρφωση Αίθουσας σύνεδριασης ~s"
#: ejabberd_web_admin.erl:937
@@ -505,9 +504,8 @@ msgid "Failed to parse HTTP response"
msgstr "Αποτυχία ανάλυσης της απόκρισης HTTP"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgstr "Αποτυχία επεξεργασίας της επιλογής '~ s'"
msgid "Failed to process option '~s'"
msgstr "Αποτυχία επεξεργασίας της επιλογής '~s'"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
#: mod_vcard_sql.erl:174 mod_vcard_ldap.erl:330 mod_vcard_ldap.erl:343
@@ -576,8 +574,8 @@ msgid "Given Name"
msgstr "Ονομα"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Ομάδα "
msgid "Group"
msgstr "Ομάδα"
#: mod_roster.erl:956
msgid "Groups"
@@ -705,13 +703,12 @@ msgid "Invitations are not allowed in this conference"
msgstr "Οι προσκλήσεις δεν επιτρέπονται σε αυτή τη διάσκεψη"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Δεν επιτρέπεται η αποστολή μηνυμάτων σφάλματος στο δωμάτιο. Ο συμμετέχων (~ "
"s) έχει στείλει ένα μήνυμα σφάλματος (~ s) και έχει πέταχτεί έξω από την "
"Δεν επιτρέπεται η αποστολή μηνυμάτων σφάλματος στο δωμάτιο. Ο συμμετέχων (~s"
") έχει στείλει ένα μήνυμα σφάλματος (~s) και έχει πέταχτεί έξω από την "
"αίθουσα"
#: mod_muc_room.erl:564 mod_muc_room.erl:575
@@ -946,8 +943,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Ψευδώνυμο ~s δεν υπάρχει σε αυτή την αίθουσα"
#: mod_muc_room.erl:3396
@@ -1797,9 +1793,8 @@ msgid "To"
msgstr "Πρώς"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgstr "Για να εγγραφείτε, επισκεφθείτε το ~ s"
msgid "To register, visit ~s"
msgstr "Για να εγγραφείτε, επισκεφθείτε το ~s"
#: mod_configure.erl:666
#, fuzzy
@@ -2025,20 +2020,17 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "Δεν επιτρέπεται η παράμετρος 'set' του 'type'"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgstr "Η τιμή του '~ s' πρέπει να είναι boolean"
msgid "Value of '~s' should be boolean"
msgstr "Η τιμή του '~s' πρέπει να είναι boolean"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgstr "Η τιμή του '~ s' θα πρέπει να είναι χρονοσειρά"
msgid "Value of '~s' should be datetime string"
msgstr "Η τιμή του '~s' θα πρέπει να είναι χρονοσειρά"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgstr "Η τιμή του '~ s' θα πρέπει να είναι ακέραιος"
msgid "Value of '~s' should be integer"
msgstr "Η τιμή του '~s' θα πρέπει να είναι ακέραιος"
#: ejabberd_web_admin.erl:433
#, fuzzy
@@ -2146,10 +2138,9 @@ msgstr ""
"Η μνήμη χωρίς σύνδεση μήνυματών είναι πλήρης. Το μήνυμα έχει απορριφθεί."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"Τα μηνύματά σας πρως ~s είναι αποκλεισμένα. Για αποδεσμεύση, επισκεφθείτε ~s"
+8 -12
View File
@@ -290,8 +290,7 @@ msgid "Configuration"
msgstr "Agordo"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Agordo de babilejo ~s"
#: ejabberd_web_admin.erl:937
@@ -566,8 +565,8 @@ msgid "Given Name"
msgstr "Meza Nomo"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Grupo "
msgid "Group"
msgstr "Grupo"
#: mod_roster.erl:956
msgid "Groups"
@@ -936,8 +935,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Kaŝnomo ~s ne ekzistas en la babilejo"
#: mod_muc_room.erl:3396
@@ -1782,10 +1780,9 @@ msgid "Token TTL"
msgstr ""
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"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."
@@ -2113,10 +2110,9 @@ msgstr ""
"forĵetita"
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "Viaj mesaĝoj al ~s estas blokata. Por malbloki ilin, iru al ~s"
#: mod_disco.erl:438
+18 -16
View File
@@ -60,7 +60,7 @@
{"Client acknowledged more stanzas than sent by server","El cliente ha reconocido más paquetes de los que el servidor ha enviado"}.
{"Commands","Comandos"}.
{"Conference room does not exist","La sala de conferencias no existe"}.
{"Configuration of room ~ts","Configuración para la sala ~ts"}.
{"Configuration of room ~s","Configuración para la sala ~s"}.
{"Configuration","Configuración"}.
{"Connected Resources:","Recursos conectados:"}.
{"Country","País"}.
@@ -79,7 +79,8 @@
{"Delete User","Borrar usuario"}.
{"Description:","Descripción:"}.
{"Disc only copy","Copia en disco solamente"}.
{"Displayed Groups:","Mostrar grupos:"}.
{"'Displayed groups' not added (they do not exist!): ","'Mostrados' que no han sido añadidos (¡no existen!): "}.
{"Displayed:","Mostrados:"}.
{"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"}.
@@ -116,7 +117,7 @@
{"Failed to extract JID from your voice request approval","Fallo al extraer el Jabber ID de tu aprobación de petición de voz"}.
{"Failed to map delegated namespace to external component","Falló el mapeo de espacio de nombres delegado al componente externo"}.
{"Failed to parse HTTP response","Falló la comprensión de la respuesta HTTP"}.
{"Failed to process option '~ts'","Falló el procesado de la opción '~ts'"}.
{"Failed to process option '~s'","Falló el procesado de la opción '~s'"}.
{"Family Name","Apellido"}.
{"February","febrero"}.
{"File larger than ~w bytes","El fichero es más grande que ~w bytes"}.
@@ -132,7 +133,7 @@
{"Get User Password","Ver contraseña de usuario"}.
{"Get User Statistics","Ver estadísticas de usuario"}.
{"Given Name","Nombre"}.
{"Group ","Grupo "}.
{"Group","Grupo"}.
{"Groups","Grupos"}.
{"has been banned","ha sido bloqueado"}.
{"has been kicked because of a system shutdown","ha sido expulsado porque el sistema se va a detener"}.
@@ -169,7 +170,7 @@
{"Invitations are not allowed in this conference","Las invitaciones no están permitidas en esta sala"}.
{"IP addresses","Direcciones IP"}.
{"is now known as","se cambia el nombre a"}.
{"It is not allowed to send error messages to the room. The participant (~ts) has sent an error message (~ts) and got kicked from the room","No está permitido enviar mensajes de error a la sala. Este participante (~ts) ha enviado un mensaje de error (~ts) y fue expulsado de la sala"}.
{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","No está permitido enviar mensajes de error a la sala. Este participante (~s) ha enviado un mensaje de error (~s) y fue expulsado de la sala"}.
{"It is not allowed to send private messages 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"}.
{"It is not allowed to send private messages","No está permitido enviar mensajes privados"}.
@@ -181,6 +182,7 @@
{"joins the room","entra en la sala"}.
{"July","julio"}.
{"June","junio"}.
{"Label:","Etiqueta:"}.
{"Last Activity","Última actividad"}.
{"Last login","Última conexión"}.
{"Last month","Último mes"}.
@@ -200,7 +202,7 @@
{"March","marzo"}.
{"Maximum Number of Occupants","Número máximo de ocupantes"}.
{"May","mayo"}.
{"Members not added (inexistent vhost): ","Miembros no añadidos (el vhost no existe): "}.
{"Members not added (inexistent vhost!): ","Miembros no añadidos (el vhost no existe): "}.
{"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."}.
@@ -224,7 +226,7 @@
{"New Password:","Nueva contraseña:"}.
{"Nickname can't be empty","El apodo no puede estar vacío"}.
{"Nickname Registration at ","Registro del apodo en "}.
{"Nickname ~ts does not exist in the room","El apodo ~ts no existe en la sala"}.
{"Nickname ~s does not exist in the room","El apodo ~s no existe en la sala"}.
{"Nickname","Apodo"}.
{"No address elements found","No se encontraron elementos de dirección ('address')"}.
{"No addresses element found","No se encontró elemento de direcciones ('addresses')"}.
@@ -349,6 +351,7 @@
{"Roster","Lista de contactos"}.
{"RPC Call Error","Error en la llamada RPC"}.
{"Running Nodes","Nodos funcionando"}.
{"~s invites you to the room ~s","~s te invita a la sala ~s"}.
{"Saturday","sábado"}.
{"Script check","Comprobación de script"}.
{"Search Results for ","Buscar resultados por "}.
@@ -409,12 +412,12 @@
{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Esta página te permite crear una cuenta Jabber este servidor Jabber. Tu JID (Jabber IDentificador) será de la forma: nombredeusuario@servidor. Por favor lee detenidamente las instrucciones para rellenar correctamente los campos."}.
{"This page allows to unregister a Jabber account in this Jabber server.","Esta página te permite borrar tu cuenta Jabber en este servidor Jabber."}.
{"This room is not anonymous","Sala no anónima"}.
{"This service can not process the address: ~ts","Este servicio no puede procesar la dirección: ~ts"}.
{"This service can not process the address: ~s","Este servicio no puede procesar la dirección: ~s"}.
{"Thursday","jueves"}.
{"Time delay","Retraso temporal"}.
{"Timed out waiting for stream resumption","Ha pasado demasiado tiempo esperando que la conexión se restablezca"}.
{"Time","Fecha"}.
{"To register, visit ~ts","Para registrarte, visita ~ts"}.
{"To register, visit ~s","Para registrarte, visita ~s"}.
{"To ~ts","A ~ts"}.
{"Token TTL","Token TTL"}.
{"Too many active bytestreams","Demasiados bytestreams activos"}.
@@ -422,7 +425,7 @@
{"Too many child elements","Demasiados subelementos"}.
{"Too many <item/> elements","Demasiados elementos <item/>"}.
{"Too many <list/> elements","Demasiados elementos <list/>"}.
{"Too many (~p) failed authentications from this IP address (~ts). The address will be unblocked at ~ts UTC","Demasiadas (~p) autenticaciones fallidas de esta dirección IP (~ts). La dirección será desbloqueada en ~ts UTC"}.
{"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 receiver fields were specified","Se han especificado demasiados campos de destinatario"}.
{"Too many unacked stanzas","Demasiados mensajes sin haber reconocido recibirlos"}.
{"Too many users in this conference","Demasiados usuarios en esta sala"}.
@@ -433,7 +436,6 @@
{"Transactions Committed:","Transacciones finalizadas:"}.
{"Transactions Logged:","Transacciones registradas:"}.
{"Transactions Restarted:","Transacciones reiniciadas:"}.
{"~ts invites you to the room ~ts","~ts te invita a la sala ~ts"}.
{"~ts's Offline Messages Queue","Cola de mensajes diferidos de ~ts"}.
{"Tuesday","martes"}.
{"Unable to generate a CAPTCHA","No se pudo generar un CAPTCHA"}.
@@ -467,12 +469,11 @@
{"User","Usuario"}.
{"Validate","Validar"}.
{"Value 'get' of 'type' attribute is not allowed","El valor 'get' del atributo 'type' no está permitido"}.
{"Value of '~ts' should be boolean","El valor de '~ts' debería ser booleano"}.
{"Value of '~ts' should be datetime string","El valor de '~ts' debería ser una fecha"}.
{"Value of '~ts' should be integer","El valor de '~ts' debería ser un entero"}.
{"Value of '~s' should be boolean","El valor de '~s' debería ser booleano"}.
{"Value of '~s' should be datetime string","El valor de '~s' debería ser una fecha"}.
{"Value of '~s' should be integer","El valor de '~s' debería ser un entero"}.
{"Value 'set' of 'type' attribute is not allowed","El valor 'set' del atributo 'type' no está permitido"}.
{"vCard User Search","Buscar vCard de usuario"}.
{"Virtual Hosting","Dominios Virtuales"}.
{"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"}.
@@ -481,6 +482,7 @@
{"Wednesday","miércoles"}.
{"Wrong parameters in the web formulary","Parámetros incorrectos en el formulario web"}.
{"Wrong xmlns","xmlns incorrecto"}.
{"XMPP Domains","Dominios XMPP"}.
{"You are being removed from the room because of a system shutdown","Estás siendo expulsado de la sala porque el sistema se va a detener"}.
{"You are not joined to the channel","No has entrado en el canal"}.
{"You can later change your password using a Jabber client.","Puedes cambiar tu contraseña después, usando un cliente Jabber."}.
@@ -494,5 +496,5 @@
{"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 subscription request and/or messages to ~ts have been blocked. To unblock your subscription request, visit ~ts","Tu petición de suscripción y/o mensajes a ~ts ha sido bloqueado. Para desbloquear tu petición de suscripción visita ~ts"}.
{"Your subscription request and/or messages to ~s have been blocked. To unblock your subscription request, visit ~s","Tu petición de suscripción y/o mensajes a ~s ha sido bloqueado. Para desbloquear tu petición de suscripción visita ~s"}.
{"You're not allowed to create nodes","No tienes permitido crear nodos"}.
+422 -412
View File
File diff suppressed because it is too large Load Diff
+15 -25
View File
@@ -293,8 +293,7 @@ msgid "Configuration"
msgstr "Configuration"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Configuration pour le salon ~s"
#: ejabberd_web_admin.erl:937
@@ -501,8 +500,7 @@ msgid "Failed to parse HTTP response"
msgstr "Echec de lecture de la réponse HTTP"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "Echec de traitement de l'option '~s'"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -571,8 +569,8 @@ msgid "Given Name"
msgstr "Nom"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Groupe "
msgid "Group"
msgstr "Groupe"
#: mod_roster.erl:956
msgid "Groups"
@@ -701,10 +699,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "Les invitations ne sont pas autorisées dans ce salon"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"L'envoyer de messages d'erreur au salon n'est pas autorisé. Le participant "
"(~s) à envoyé un message d'erreur (~s) et à été expulsé du salon"
@@ -942,8 +939,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Le pseudo ~s n'existe pas dans ce salon"
#: mod_muc_room.erl:3396
@@ -1784,8 +1780,7 @@ msgid "To"
msgstr "A"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "Pour vous enregistrer, visitez ~s"
#: mod_configure.erl:666
@@ -1798,10 +1793,9 @@ msgid "Token TTL"
msgstr "Jeton TTL"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"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"
@@ -2016,19 +2010,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "La valeur de l'attribut 'type' ne peut être 'set'"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "La valeur de '~s' ne peut être booléen"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "La valeur de '~s' doit être une chaine datetime"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "La valeur de '~s' doit être un entier"
#: ejabberd_web_admin.erl:433
@@ -2139,10 +2130,9 @@ msgstr ""
"été détruit."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"Vos messages pour ~s sont bloqués. Pour les débloquer, veuillez visiter ~s"
+15 -25
View File
@@ -291,8 +291,7 @@ msgid "Configuration"
msgstr "Configuración"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Configuración para a sala ~s"
#: ejabberd_web_admin.erl:937
@@ -498,8 +497,7 @@ msgid "Failed to parse HTTP response"
msgstr "Non se puido analizar a resposta HTTP"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "Fallo ao procesar a opción '~s'"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -568,8 +566,8 @@ msgid "Given Name"
msgstr "Nome"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Grupo "
msgid "Group"
msgstr "Grupo"
#: mod_roster.erl:956
msgid "Groups"
@@ -697,10 +695,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "As invitacións non están permitidas nesta sala"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Non está permitido enviar mensaxes de erro á sala. Este participante (~s) "
"enviou unha mensaxe de erro (~s) e foi expulsado da sala"
@@ -937,8 +934,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "O alcume ~s non existe na sala"
#: mod_muc_room.erl:3396
@@ -1776,8 +1772,7 @@ msgid "To"
msgstr "Para"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "Para rexistrarse, visita ~s"
#: mod_configure.erl:666
@@ -1790,10 +1785,9 @@ msgid "Token TTL"
msgstr "Token TTL"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr ""
"Demasiados (~p) fallou autenticaciones desde esta dirección IP (~s). A "
"dirección será desbloqueada as ~s UTC"
@@ -2005,19 +1999,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "O valor \"set\" do atributo 'type' non está permitido"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "O valor de '~s' debería ser booleano"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "O valor de '~s' debería ser unha data"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "O valor de '~s' debería ser un enteiro"
#: ejabberd_web_admin.erl:433
@@ -2122,10 +2113,9 @@ msgstr ""
"descartouse."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"As súas mensaxes a ~s encóntranse bloqueadas. Para desbloquear, visite ~s"
+14 -23
View File
@@ -295,8 +295,7 @@ msgstr "תצורה"
# תצורה של חדר
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "תצורת חדר ~s"
#: ejabberd_web_admin.erl:937
@@ -500,8 +499,7 @@ msgid "Failed to parse HTTP response"
msgstr "נכשל לפענח תגובת HTTP"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "נכשל לעבד אפשרות '~s'"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -572,8 +570,8 @@ msgid "Given Name"
msgstr "שם פרטי"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "קבוצה "
msgid "Group"
msgstr "קבוצה"
#: mod_roster.erl:956
msgid "Groups"
@@ -702,10 +700,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "הזמנות אינן מותרות בועידה זו"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"אין זה מותר לשלוח הודעות שגיאה לחדר. משתתף זה (~s) שלח הודעת שגיאה (~s) "
"ונבעט מתוך החדר"
@@ -1784,8 +1781,7 @@ msgid "To"
msgstr "לכבוד"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "כדי להירשם, בקרו ~s"
#: mod_configure.erl:666
@@ -1798,10 +1794,9 @@ msgid "Token TTL"
msgstr "סימן TTL"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr ""
"יותר מדי (~p) אימותים כושלים מתוך כתובת IP זו (~s). הכתובת תורשה לקבל גישה "
"בשעה ~s UTC"
@@ -2015,19 +2010,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr ""
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "ערך של '~s' צריך להיות boolean"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "ערך של '~s' צריך להיות מחרוזת datetime"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "ערך של '~s' צריך להיות integer"
# וירטואליים
@@ -2132,10 +2124,9 @@ msgid ""
msgstr "תור הודעות קשר לא מקוונות הינו מלא. ההודעה סולקה."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "ההודעות שלך לערוץ ~s הינן חסומות. כדי לבטל את חסימתן, בקר בכתובת ~s"
#: mod_disco.erl:438
+24 -25
View File
@@ -295,8 +295,8 @@ msgid "Configuration"
msgstr "Beállítás"
#: mod_muc_room.erl:3489
msgid "Configuration of room ~ts"
msgstr "A(z) ~ts szoba beállítása"
msgid "Configuration of room ~s"
msgstr "A(z) ~s szoba beállítása"
#: ejabberd_web_admin.erl:937
msgid "Connected Resources:"
@@ -567,8 +567,8 @@ msgid "Given Name"
msgstr "Keresztnév"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Csoport "
msgid "Group"
msgstr "Csoport"
#: mod_roster.erl:956
msgid "Groups"
@@ -694,11 +694,11 @@ msgstr "Meghívások nem engedélyezettek ebben a konferenciában"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Nem engedélyezett hibaüzeneteket küldeni a szobába. A résztvevő (~ts) "
"hibaüzenetet (~ts) küldött, és ki lett rúgva a szobából"
"Nem engedélyezett hibaüzeneteket küldeni a szobába. A résztvevő (~s) "
"hibaüzenetet (~s) küldött, és ki lett rúgva a szobából"
#: mod_muc_room.erl:564 mod_muc_room.erl:575
msgid "It is not allowed to send private messages"
@@ -1734,8 +1734,8 @@ msgid "This room is not anonymous"
msgstr "Ez a szoba nem névtelen"
#: mod_multicast.erl:498
msgid "This service can not process the address: ~ts"
msgstr "Ez a szolgáltatás nem tudja feldolgozni a címet: ~ts"
msgid "This service can not process the address: ~s"
msgstr "Ez a szolgáltatás nem tudja feldolgozni a címet: ~s"
#: mod_muc_log.erl:470
msgid "Thursday"
@@ -1758,8 +1758,8 @@ msgid "To"
msgstr "Címzett"
#: mod_register.erl:226
msgid "To register, visit ~ts"
msgstr "Regisztráláshoz látogassa meg ezt az oldalt: ~ts"
msgid "To register, visit ~s"
msgstr "Regisztráláshoz látogassa meg ezt az oldalt: ~s"
#: mod_configure.erl:666
msgid "To ~ts"
@@ -1769,10 +1769,9 @@ msgstr "Címzett: ~ts"
msgid "Token TTL"
msgstr "Token élettartama"
#: mod_fail2ban.erl:219
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr ""
"Túl sok (~p) sikertelen hitelesítés erről az IP-címről (~ts) A cím ~ts-kor "
"lesz feloldva UTC szerint"
@@ -1981,17 +1980,17 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "A „type” attribútum „set” értéke nem engedélyezett"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
msgid "Value of '~ts' should be boolean"
msgstr "A(z) „~ts” értéke csak logikai lehet"
msgid "Value of '~s' should be boolean"
msgstr "A(z) „~s” értéke csak logikai lehet"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
msgid "Value of '~ts' should be datetime string"
msgstr "A(z) „~ts” értéke csak dátum és idő karakterlánc lehet"
msgid "Value of '~s' should be datetime string"
msgstr "A(z) „~s” értéke csak dátum és idő karakterlánc lehet"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
msgid "Value of '~ts' should be integer"
msgstr "A(z) „~ts” értéke csak egész szám lehet"
msgid "Value of '~s' should be integer"
msgstr "A(z) „~s” értéke csak egész szám lehet"
#: ejabberd_web_admin.erl:433
msgid "Virtual Hosting"
@@ -2097,12 +2096,12 @@ msgstr ""
#: ejabberd_captcha.erl:97
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"A feliratkozási kérelme és/vagy ~ts számára küldött üzenetei blokkolva "
"A feliratkozási kérelme és/vagy ~s számára küldött üzenetei blokkolva "
"lettek. A feliratkozási kérelmének feloldásához látogassa meg ezt az oldalt: "
"~ts"
"~s"
#: mod_disco.erl:438
msgid "ejabberd"
+6 -8
View File
@@ -291,8 +291,7 @@ msgid "Configuration"
msgstr "Pengaturan"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Pengaturan ruangan ~s"
#: ejabberd_web_admin.erl:937
@@ -568,10 +567,11 @@ msgid "Given Name"
msgstr "Nama Tengah"
#: mod_shared_roster.erl:879
msgid "Group "
msgid "Group"
msgstr "Grup"
#: mod_roster.erl:956
#, fuzzy
msgid "Groups"
msgstr "Grup"
@@ -940,8 +940,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Nama Julukan ~s tidak berada di dalam ruangan"
#: mod_muc_room.erl:3396
@@ -2126,10 +2125,9 @@ msgstr ""
"Kontak offline Anda pada antrian pesan sudah penuh. Pesan telah dibuang."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"Pesan Anda untuk ~s sedang diblokir. Untuk membuka blokir tersebut, kunjungi "
"~s"
+6 -9
View File
@@ -298,8 +298,7 @@ msgid "Configuration"
msgstr "Configurazione"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Configurazione per la stanza ~s"
#: ejabberd_web_admin.erl:937
@@ -577,8 +576,8 @@ msgid "Given Name"
msgstr "Altro nome"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Gruppo "
msgid "Group"
msgstr "Gruppo"
#: mod_roster.erl:956
msgid "Groups"
@@ -947,8 +946,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Il nickname ~s non esiste nella stanza"
#: mod_muc_room.erl:3396
@@ -2135,10 +2133,9 @@ msgstr ""
"scartato"
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "I messaggi verso ~s sono bloccati. Per sbloccarli, visitare ~s"
#: mod_disco.erl:438
+11 -14
View File
@@ -288,8 +288,7 @@ msgid "Configuration"
msgstr "設定"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "チャットルーム ~s の設定"
#: ejabberd_web_admin.erl:937
@@ -565,10 +564,12 @@ msgid "Given Name"
msgstr "ミドルネーム"
#: mod_shared_roster.erl:879
msgid "Group "
#, fuzzy
msgid "Group"
msgstr "グループ"
#: mod_roster.erl:956
#, fuzzy
msgid "Groups"
msgstr "グループ"
@@ -697,10 +698,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "この会議では、発言権の要求はできません"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"このルームにエラーメッセージを送ることは許可されていません。参加者(~s)はエ"
"ラーメッセージを(~s)を送信してルームからキックされました。"
@@ -939,8 +939,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "ニックネーム ~s はこのチャットルームにいません"
#: mod_muc_room.erl:3396
@@ -1783,10 +1782,9 @@ msgid "Token TTL"
msgstr ""
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr ""
"~p回の認証に失敗しました。このIPアドレス(~s)は~s UTCまでブロックされます。"
@@ -2109,10 +2107,9 @@ msgstr ""
"相手先のオフラインメッセージキューが一杯です。このメッセージは破棄されます。"
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"~s 宛のメッセージはブロックされています。解除するにはこちらを見てください ~s"
+8 -12
View File
@@ -292,8 +292,7 @@ msgid "Configuration"
msgstr "Instellingen"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Instellingen van chatruimte ~s"
#: ejabberd_web_admin.erl:937
@@ -571,8 +570,8 @@ msgid "Given Name"
msgstr "Tussennaam"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Groep "
msgid "Group"
msgstr "Groep"
#: mod_roster.erl:956
msgid "Groups"
@@ -946,8 +945,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "De bijnaam ~s bestaat niet in deze chatruimte"
#: mod_muc_room.erl:3396
@@ -1807,10 +1805,9 @@ msgid "Token TTL"
msgstr ""
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"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"
@@ -2138,10 +2135,9 @@ msgstr ""
"opgeslagen."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"Uw berichten aan ~s worden geblokkeerd. Om ze te deblokkeren, ga naar ~s"
+6 -9
View File
@@ -290,8 +290,7 @@ msgid "Configuration"
msgstr "Konfigurasjon"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Konfigurasjon for rom ~s"
#: ejabberd_web_admin.erl:937
@@ -566,8 +565,8 @@ msgid "Given Name"
msgstr "Mellomnavn"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Gruppe "
msgid "Group"
msgstr "Gruppe"
#: mod_roster.erl:956
msgid "Groups"
@@ -936,8 +935,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Kallenavn ~s eksisterer ikke i dette rommet"
#: mod_muc_room.erl:3396
@@ -2108,10 +2106,9 @@ msgid ""
msgstr "Kontaktens frakoblede meldingskø er full. Meldingen har blitt kassert."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "Dine meldinger til ~s blir blokkert. For å åpne igjen, besøk ~s"
#: mod_disco.erl:438
+14 -23
View File
@@ -294,8 +294,7 @@ msgid "Configuration"
msgstr "Konfiguracja"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Konfiguracja pokoju ~s"
#: ejabberd_web_admin.erl:937
@@ -500,8 +499,7 @@ msgid "Failed to parse HTTP response"
msgstr "Nie udało się zanalizować odpowiedzi HTTP"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "Nie udało się przetworzyć opcji '~s'"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -570,8 +568,8 @@ msgid "Given Name"
msgstr "Imię"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Grupa "
msgid "Group"
msgstr "Grupa"
#: mod_roster.erl:956
msgid "Groups"
@@ -699,10 +697,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "Zaproszenia są wyłączone w tym pokoju"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Użytkownik nie może wysyłać wiadomości o błędach do pokoju. Użytkownik (~s) "
"wysłał błąd (~s) i został wyrzucony z pokoju"
@@ -1776,8 +1773,7 @@ msgid "To"
msgstr "Do"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "Żeby się zarejestrować odwiedź ~s"
#: mod_configure.erl:666
@@ -1790,10 +1786,9 @@ msgid "Token TTL"
msgstr "Limit czasu tokenu"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"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"
@@ -2005,19 +2000,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "Wartość 'set' dla atrybutu 'type' jest niedozwolona"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "Wartość '~s' powinna być typu logicznego"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "Wartość '~s' powinna być typu daty"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "Wartość '~s' powinna być liczbą"
#: ejabberd_web_admin.erl:433
@@ -2118,10 +2110,9 @@ msgstr ""
"Kolejka wiadomości offline adresata jest pełna. Wiadomość została odrzucona."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "Twoje wiadomości do ~s są blokowane. Aby je odblokować, odwiedź ~s"
#: mod_disco.erl:438
+15 -25
View File
@@ -291,8 +291,7 @@ msgid "Configuration"
msgstr "Configuração"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Configuração para ~s"
#: ejabberd_web_admin.erl:937
@@ -499,8 +498,7 @@ msgid "Failed to parse HTTP response"
msgstr "Falha ao analisar resposta HTTP"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "Falha ao processar opção '~s'"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -570,8 +568,8 @@ msgid "Given Name"
msgstr "Nome do meio"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Grupo "
msgid "Group"
msgstr "Grupo"
#: mod_roster.erl:956
msgid "Groups"
@@ -701,10 +699,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "Convites estão desabilitados nesta sala de conferência"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Não é permitido o envio de mensagens de erro a esta sala. O membro (~s) "
"enviou uma mensagem de erro (~s) e foi desconectado (\"kicked\")."
@@ -942,8 +939,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "O apelido ~s não existe na sala"
#: mod_muc_room.erl:3396
@@ -1784,8 +1780,7 @@ msgid "To"
msgstr "Para"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "Para registrar, visite ~s"
#: mod_configure.erl:666
@@ -1798,10 +1793,9 @@ msgid "Token TTL"
msgstr "Token TTL"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"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 às ~s UTC"
@@ -2016,19 +2010,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "Valor 'set' não permitido para atributo 'type'"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "Value de '~s' deveria ser um booleano"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "Valor de '~s' deveria ser data e hora"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "Valor de '~s' deveria ser um inteiro"
#: ejabberd_web_admin.erl:433
@@ -2132,10 +2123,9 @@ msgid ""
msgstr "Sua fila de mensagens offline esta cheia. Sua mensagem foi descartada"
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"Suas mensagens para ~s estão bloqueadas. Para desbloqueá-las, visite: ~s"
+3 -5
View File
@@ -300,7 +300,7 @@ msgstr "Configuração"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Configuração para "
#: ejabberd_web_admin.erl:937
@@ -585,9 +585,8 @@ msgid "Given Name"
msgstr "Segundo nome"
#: mod_shared_roster.erl:879
#, fuzzy
msgid "Group "
msgstr "Grupos"
msgstr ""
#: mod_roster.erl:956
msgid "Groups"
@@ -969,8 +968,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "A alcunha ~s não existe na sala"
#: mod_muc_room.erl:3396
+16 -27
View File
@@ -289,8 +289,7 @@ msgid "Configuration"
msgstr "Конфигурация"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Конфигурация комнаты ~s"
#: ejabberd_web_admin.erl:937
@@ -491,8 +490,7 @@ msgid "Failed to parse HTTP response"
msgstr "Ошибка разбора HTTP ответа"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "Ошибка обработки опции '~s'"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -559,8 +557,8 @@ msgid "Given Name"
msgstr "Имя"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Группа "
msgid "Group"
msgstr "Группа"
#: mod_roster.erl:956
msgid "Groups"
@@ -685,10 +683,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "Рассылка приглашений отключена в этой конференции"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Запрещено посылать сообщения об ошибках в эту комнату. Участник (~s) послал "
"сообщение об ошибке (~s) и был выкинут из комнаты"
@@ -924,8 +921,7 @@ msgid "Nickname can't be empty"
msgstr "Псевдоним не может быть пустым значением"
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Псевдоним ~s в комнате отсутствует"
#: mod_muc_room.erl:3396
@@ -1726,8 +1722,7 @@ msgid "This room is not anonymous"
msgstr "Эта комната не анонимная"
#: mod_multicast.erl:498
#, fuzzy
msgid "This service can not process the address: ~ts"
msgid "This service can not process the address: ~s"
msgstr "Сервер не может обработать адрес: ~s"
#: mod_muc_log.erl:470
@@ -1751,8 +1746,7 @@ msgid "To"
msgstr "Кому"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "Для регистрации посетите ~s"
#: mod_configure.erl:666
@@ -1765,10 +1759,9 @@ msgid "Token TTL"
msgstr "Токен TTL"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr ""
"Слишком много (~p) неудачных попыток аутентификации с этого IP-адреса (~s). "
"Адрес будет разблокирован в ~s UTC"
@@ -1977,19 +1970,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "Значение 'set' атрибута 'type' недопустимо"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "Значение '~s' должно быть булевым"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "Значение '~s' должно быть датой"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "Значение '~s' должно быть целочисленным"
#: ejabberd_web_admin.erl:433
@@ -2089,10 +2079,9 @@ msgstr ""
"было сохранено."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"Ваши запросы на добавление в контакт-лист, а также сообщения к ~s "
"блокируются. Для снятия блокировки перейдите по ссылке ~s"
+6 -9
View File
@@ -291,8 +291,7 @@ msgid "Configuration"
msgstr "Konfigurácia"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Konfigurácia miestnosti ~s"
#: ejabberd_web_admin.erl:937
@@ -567,8 +566,8 @@ msgid "Given Name"
msgstr "Prostredné meno: "
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Skupina "
msgid "Group"
msgstr "Skupina"
#: mod_roster.erl:956
msgid "Groups"
@@ -936,8 +935,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Prezývka ~s v miestnosti neexistuje"
#: mod_muc_room.erl:3396
@@ -2113,10 +2111,9 @@ msgid ""
msgstr "Fronta offline správ tohoto kontaktu je plná. Správa bola zahodená."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "Správa určená pre ~s bola zablokovaná. Oblokovať ju môžete na ~s"
#: mod_disco.erl:438
+6 -9
View File
@@ -295,8 +295,7 @@ msgid "Configuration"
msgstr "Konfiguration"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Konfiguration för ~s"
#: ejabberd_web_admin.erl:937
@@ -570,8 +569,8 @@ msgid "Given Name"
msgstr "Mellannamn"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Grupp "
msgid "Group"
msgstr "Grupp"
#: mod_roster.erl:956
msgid "Groups"
@@ -942,8 +941,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Smeknamnet ~s existerar inte i det här rummet"
#: mod_muc_room.erl:3396
@@ -2121,10 +2119,9 @@ msgid ""
msgstr "Din kontaktkö for offlinekontakter ar full"
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"Dina meddelanden till ~s är blockerade. För att avblockera dem, gå till ~s"
+2 -2
View File
@@ -569,8 +569,8 @@ msgid "Given Name"
msgstr "ชื่อกลาง"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "กลุ่"
msgid "Group"
msgstr "กลุ่"
#: mod_roster.erl:956
msgid "Groups"
+5 -8
View File
@@ -294,8 +294,7 @@ msgid "Configuration"
msgstr "Ayarlar"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "~s odasının ayarları"
#: ejabberd_web_admin.erl:937
@@ -573,7 +572,7 @@ msgstr "Ortanca İsim"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Group "
msgstr ""
#: mod_roster.erl:956
msgid "Groups"
@@ -943,8 +942,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "~s takma ismi odada yok"
#: mod_muc_room.erl:3396
@@ -2128,10 +2126,9 @@ msgid ""
msgstr "Çevirim-dışı mesaj kuyruğunuz dolu. Mesajını dikkate alınmadı."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
"~s kullanıcısına mesajlarınız engelleniyor. Durumu düzeltmek için ~s "
"adresini ziyaret ediniz."
+10 -15
View File
@@ -295,8 +295,7 @@ msgid "Configuration"
msgstr "Конфігурація"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Конфігурація кімнати ~s"
#: ejabberd_web_admin.erl:937
@@ -568,8 +567,8 @@ msgid "Given Name"
msgstr "По-батькові"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Група "
msgid "Group"
msgstr "Група"
#: mod_roster.erl:956
msgid "Groups"
@@ -699,10 +698,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "Голосові запити відключені в цій конференції"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"Не дозволяється відправляти помилкові повідомлення в кімнату. Учасник (~s) "
"відправив помилкове повідомлення (~s), та був виганий з кімнати"
@@ -940,8 +938,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "Псевдонім ~s в кімнаті відсутній"
#: mod_muc_room.erl:3396
@@ -1794,10 +1791,9 @@ msgid "Token TTL"
msgstr ""
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr ""
"Забагато (~p) помилок авторизації з цієї IP адреси (~s). Адресу буде "
"розблоковано о ~s UTC"
@@ -2126,10 +2122,9 @@ msgstr ""
"збережено."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "Ваші повідомлення до ~s блокуються. Для розблокування відвідайте ~s"
#: mod_disco.erl:438
+5 -7
View File
@@ -571,8 +571,8 @@ msgid "Given Name"
msgstr "Họ Đệm"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Nhóm "
msgid "Group"
msgstr "Nhóm"
#: mod_roster.erl:956
msgid "Groups"
@@ -946,8 +946,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
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:3396
@@ -2140,10 +2139,9 @@ msgid ""
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ỏ."
#: ejabberd_captcha.erl:97
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr ""
#: mod_disco.erl:438
+10 -15
View File
@@ -293,8 +293,7 @@ msgid "Configuration"
msgstr "Apontiaedjes"
#: mod_muc_room.erl:3489
#, fuzzy
msgid "Configuration of room ~ts"
msgid "Configuration of room ~s"
msgstr "Apontiaedje del såle ~s"
#: ejabberd_web_admin.erl:937
@@ -571,8 +570,8 @@ msgid "Given Name"
msgstr "No do mitan"
#: mod_shared_roster.erl:879
msgid "Group "
msgstr "Groupe "
msgid "Group"
msgstr "Groupe"
#: mod_roster.erl:956
msgid "Groups"
@@ -702,10 +701,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "Les dmandes di vwès sont dismetowes e cisse conferince ci"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"On n' pout nén evoyî des messaedjes d' aroke sol såle. Li pårticipan (~s) a-"
"st evoyî on messaedje d' aroke (~s) ey a stî tapé foû."
@@ -943,8 +941,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
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:3396
@@ -1798,10 +1795,9 @@ msgid "Token TTL"
msgstr ""
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr ""
"I gn a-st avou pår trop (~p) d' otintifiaedjes k' ont fwait berwete vinant "
"di ciste adresse IP la (~s). L' adresse serè disblokêye a ~s UTC"
@@ -2129,10 +2125,9 @@ msgstr ""
"messaedje a stî tapé å diale."
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "Vos messaedjes po ~s sont blokés. Po les disbloker, alez vey ~s"
#: mod_disco.erl:438
+13 -22
View File
@@ -491,8 +491,7 @@ msgid "Failed to parse HTTP response"
msgstr "HTTP响应解析失败"
#: mod_muc_room.erl:3632
#, fuzzy
msgid "Failed to process option '~ts'"
msgid "Failed to process option '~s'"
msgstr "选项'~s'处理失败"
#: mod_vcard_mnesia.erl:103 mod_vcard_mnesia.erl:117 mod_vcard_sql.erl:160
@@ -561,7 +560,7 @@ msgid "Given Name"
msgstr "中间名"
#: mod_shared_roster.erl:879
msgid "Group "
msgid "Group"
msgstr "组"
#: mod_roster.erl:956
@@ -690,10 +689,9 @@ msgid "Invitations are not allowed in this conference"
msgstr "此会议不允许邀请"
#: mod_muc_room.erl:373 mod_muc_room.erl:519 mod_muc_room.erl:1293
#, fuzzy
msgid ""
"It is not allowed to send error messages to the room. The participant (~ts) "
"has sent an error message (~ts) and got kicked from the room"
"It is not allowed to send error messages to the room. The participant (~s) "
"has sent an error message (~s) and got kicked from the room"
msgstr ""
"不允许将错误消息发送到该房间. 参与者(~s)已发送过一条消息(~s)并已被踢出房间"
@@ -928,8 +926,7 @@ msgid "Nickname can't be empty"
msgstr ""
#: mod_muc_room.erl:2994
#, fuzzy
msgid "Nickname ~ts does not exist in the room"
msgid "Nickname ~s does not exist in the room"
msgstr "昵称~s不在该房间"
#: mod_muc_room.erl:3396
@@ -1754,8 +1751,7 @@ msgid "To"
msgstr "到"
#: mod_register.erl:226
#, fuzzy
msgid "To register, visit ~ts"
msgid "To register, visit ~s"
msgstr "要注册,请访问 ~s"
#: mod_configure.erl:666
@@ -1768,10 +1764,9 @@ msgid "Token TTL"
msgstr "TTL令牌"
#: mod_fail2ban.erl:219
#, fuzzy
msgid ""
"Too many (~p) failed authentications from this IP address (~ts). The address "
"will be unblocked at ~ts UTC"
"Too many (~p) failed authentications from this IP address (~s). The address "
"will be unblocked at ~s UTC"
msgstr "来自IP地址(~p)的(~s)失败认证太多. 该地址将在UTC时间~s被禁用."
#: mod_muc_room.erl:2768 mod_muc_room.erl:3402
@@ -1981,19 +1976,16 @@ msgid "Value 'set' of 'type' attribute is not allowed"
msgstr "不允许 'type' 属性的 'set' 值"
#: pubsub_subscription.erl:237 pubsub_subscription_sql.erl:202
#, fuzzy
msgid "Value of '~ts' should be boolean"
msgid "Value of '~s' should be boolean"
msgstr "'~s' 的值应为布尔型"
#: pubsub_subscription.erl:215 pubsub_subscription_sql.erl:180
#, fuzzy
msgid "Value of '~ts' should be datetime string"
msgid "Value of '~s' should be datetime string"
msgstr "'~s' 的值应为日期时间字符串"
#: pubsub_subscription.erl:209 pubsub_subscription.erl:227
#: pubsub_subscription_sql.erl:174 pubsub_subscription_sql.erl:192
#, fuzzy
msgid "Value of '~ts' should be integer"
msgid "Value of '~s' should be integer"
msgstr "'~s' 的值应为整数"
#: ejabberd_web_admin.erl:433
@@ -2093,10 +2085,9 @@ msgid ""
msgstr "您的联系人离线消息队列已满. 消息已被丢弃"
#: ejabberd_captcha.erl:97
#, fuzzy
msgid ""
"Your subscription request and/or messages to ~ts have been blocked. To "
"unblock your subscription request, visit ~ts"
"Your subscription request and/or messages to ~s have been blocked. To "
"unblock your subscription request, visit ~s"
msgstr "您发送给~s的消息已被阻止. 要解除阻止, 请访问 ~s"
#: mod_disco.erl:438
+85 -79
View File
@@ -18,67 +18,70 @@
%%%
%%%----------------------------------------------------------------------
{deps, [{lager, ".*", {git, "https://github.com/erlang-lager/lager", "3.6.10"}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.18"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.22"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.4"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.19"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.39"}}},
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.4.5"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.23"}}},
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.3"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.0.1"}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.6"}}},
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.5"}}},
{deps, [{base64url, ".*", {git, "https://github.com/dvv/base64url.git", {tag, "v1.0"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.25"}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.17"}}},
{if_var_true, elixir,
{elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.4.4"}}}},
{if_var_true, pam,
{epam, ".*", {git, "https://github.com/processone/epam", {tag, "1.0.9"}}}},
{if_var_true, redis,
{eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.0.8"}}}},
{if_var_true, sip,
{esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.37"}}}},
{if_var_true, zlib,
{ezlib, ".*", {git, "https://github.com/processone/ezlib", {tag, "1.0.8"}}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.8"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.43"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.27"}}},
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.0.5"}}},
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.9.0"}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.14"}}},
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.7"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.4"}}},
{base64url, ".*", {git, "https://github.com/dvv/base64url.git", {tag, "v1.0"}}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.31"}}}},
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.32"}}}},
{if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql",
{tag, "1.0.13"}}}},
{if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql",
{tag, "1.1.9"}}}},
{if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3",
{tag, "1.1.6"}}}},
{if_var_true, pam, {epam, ".*", {git, "https://github.com/processone/epam",
{tag, "1.0.7"}}}},
{if_var_true, zlib, {ezlib, ".*", {git, "https://github.com/processone/ezlib",
{tag, "1.0.7"}}}},
%% Elixir support, needed to run tests
{if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir",
{tag, {if_version_above, "17", "v1.4.4", "v1.1.1"}}}}},
%% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin
{if_not_rebar3, {if_var_true, elixir, {rebar_elixir_plugin, ".*",
{git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}},
{if_var_true, tools, {luerl, ".*", {git, "https://github.com/rvirding/luerl",
{tag, "v0.3"}}}},
{if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis",
{tag, "v1.0.8"}}}}]}.
{lager, ".*", {git, "https://github.com/erlang-lager/lager", "3.6.10"}},
{if_var_true, tools,
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "v0.3"}}}},
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.10"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.8"}}},
{if_var_true, mysql,
{p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.16"}}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.7"}}},
{if_var_true, pgsql,
{p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.10"}}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.20"}}},
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.6"}}},
{if_not_rebar3, %% Needed because modules are not fully migrated to new structure and mix
{if_var_true, elixir,
{rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}},
{if_var_true, sqlite,
{sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.8"}}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.22"}}},
{if_var_true, stun,
{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.37"}}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.4.9"}}},
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.7"}}}
]}.
{if_var_true, latest_deps,
{floating_deps, [cache_tab,
fast_tls,
stringprep,
fast_xml,
esip,
stun,
fast_yaml,
xmpp,
p1_utils,
p1_mysql,
p1_pgsql,
p1_oauth2,
epam,
ezlib,
eimp,
epam,
esip,
ezlib,
fast_tls,
fast_xml,
fast_yaml,
mqtree,
p1_acme,
p1_mysql,
p1_oauth2,
p1_pgsql,
p1_utils,
pkix,
yconf,
p1_acme]}}.
sqlite3,
stringprep,
stun,
xmpp,
yconf]}}.
{erl_first_files, ["src/ejabberd_sql_pt.erl", "src/ejabberd_config.erl",
"src/gen_mod.erl", "src/mod_muc_room.erl",
@@ -87,20 +90,23 @@
{erl_opts, [nowarn_deprecated_function,
{i, "include"},
{i, "deps/fast_xml/include"},
{i, "deps/xmpp/include"},
{i, "deps/p1_utils/include"},
{i, "deps/xmpp/include"},
{if_version_above, "20", {d, 'DEPRECATED_GET_STACKTRACE'}},
{if_version_below, "21", {d, 'USE_OLD_HTTP_URI'}},
{if_version_below, "22", {d, 'LAGER'}},
{if_version_below, "23", {d, 'USE_OLD_CRYPTO_HMAC'}},
{if_version_below, "23", {d, 'USE_OLD_PG2'}},
{if_var_match, db_type, mssql, {d, 'mssql'}},
{if_var_false, debug, no_debug_info},
{if_var_true, debug, debug_info},
{if_var_true, elixir, {d, 'ELIXIR_ENABLED'}},
{if_var_true, hipe, native},
{if_var_true, new_sql_schema, {d, 'NEW_SQL_SCHEMA'}},
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}},
{if_var_true, sip, {d, 'SIP'}},
{if_var_true, stun, {d, 'STUN'}},
{if_version_above, "20", {d, 'DEPRECATED_GET_STACKTRACE'}},
{if_version_below, "22", {d, 'LAGER'}},
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}},
{if_var_match, db_type, mssql, {d, 'mssql'}},
{if_var_true, elixir, {d, 'ELIXIR_ENABLED'}},
{if_var_true, new_sql_schema, {d, 'NEW_SQL_SCHEMA'}},
{if_var_true, hipe, native},
{if_have_fun, {erl_error, format_exception, 6}, {d, 'HAVE_ERL_ERROR'}},
{if_have_fun, {erl_error, format_exception, 6}, {d, 'HAVE_ERL_ERROR'}},
{src_dirs, [src,
{if_var_true, tools, tools},
{if_var_true, elixir, include}]}]}.
@@ -130,20 +136,20 @@
{xref_exclusions, [
"(\"gen_transport\":_/_)",
"(\"eprof\":_/_)",
{if_var_false, mysql, "(\".*mysql.*\":_/_)"},
{if_var_false, pgsql, "(\".*pgsql.*\":_/_)"},
{if_var_false, pam, "(\"epam\":_/_)"},
{if_var_false, zlib, "(\"ezlib\":_/_)"},
{if_var_false, http, "(\"lhttpc\":_/_)"},
{if_var_false, odbc, "(\"odbc\":_/_)"},
{if_var_false, sqlite, "(\"sqlite3\":_/_)"},
{if_var_false, elixir, "(\"Elixir.*\":_/_)"},
{if_var_false, redis, "(\"eredis\":_/_)"}]}.
{if_var_false, http, "(\"lhttpc\":_/_)"},
{if_var_false, mysql, "(\".*mysql.*\":_/_)"},
{if_var_false, odbc, "(\"odbc\":_/_)"},
{if_var_false, pam, "(\"epam\":_/_)"},
{if_var_false, pgsql, "(\".*pgsql.*\":_/_)"},
{if_var_false, redis, "(\"eredis\":_/_)"},
{if_var_false, sqlite, "(\"sqlite3\":_/_)"},
{if_var_false, zlib, "(\"ezlib\":_/_)"}]}.
{eunit_compile_opts, [{i, "tools"},
{i, "include"},
{i, "deps/p1_utils/include"},
{i, "deps/fast_xml/include"},
{i, "deps/p1_utils/include"},
{i, "deps/xmpp/include"}]}.
{cover_enabled, true}.
@@ -153,14 +159,14 @@
{overrides, [
{del, [{erl_opts, [warnings_as_errors]}]}]}.
{post_hook_configure, [{"fast_tls", []},
{"stringprep", []},
{"fast_yaml", []},
{"eimp", []},
{if_var_true, sip, {"esip", []}},
{"fast_xml", [{if_var_true, full_xml, "--enable-full-xml"}]},
{post_hook_configure, [{"eimp", []},
{if_var_true, pam, {"epam", []}},
{if_var_true, zlib, {"ezlib", []}}]}.
{if_var_true, sip, {"esip", []}},
{if_var_true, zlib, {"ezlib", []}},
{"fast_tls", []},
{"fast_xml", [{if_var_true, full_xml, "--enable-full-xml"}]},
{"fast_yaml", []},
{"stringprep", []}]}.
%% Local Variables:
%% mode: erlang
+4 -2
View File
@@ -304,12 +304,14 @@ fun(Hooks) ->
end,
ProcessErlOpt = fun(Vals) ->
lists:map(
R = lists:map(
fun({i, Path}) ->
{i, ResolveDepPath(Path)};
(ErlOpt) ->
ErlOpt
end, Vals)
end, Vals),
M = lists:filter(fun({d, M}) -> true; (_) -> false end, R),
[{d, 'ALL_DEFS', M} | R]
end,
ProcssXrefExclusions = fun(Items) ->
+1 -1
View File
@@ -209,7 +209,7 @@ WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW
CREATE TABLE [dbo].[pubsub_item] (
[nodeid] [bigint] NULL,
[itemid] [varchar] (255) NOT NULL,
[publisher] [text] NOT NULL,
[publisher] [varchar] (250) NOT NULL,
[creation] [varchar] (32) NOT NULL,
[modification] [varchar] (32) NOT NULL,
[payload] [text] NOT NULL DEFAULT ''
+4 -4
View File
@@ -107,8 +107,8 @@ match_acl(_Host, {shared_group, {G, H}}, #{usr := {U, S, _}}) ->
end;
match_acl(Host, {shared_group, G}, Map) ->
match_acl(Host, {shared_group, {G, Host}}, Map);
match_acl(_Host, {user_regexp, {UR, S}}, #{usr := {U, S, _}}) ->
match_regexp(U, UR);
match_acl(_Host, {user_regexp, {UR, S1}}, #{usr := {U, S2, _}}) ->
S1 == S2 andalso match_regexp(U, UR);
match_acl(_Host, {user_regexp, UR}, #{usr := {U, S, _}}) ->
ejabberd_router:is_my_host(S) andalso match_regexp(U, UR);
match_acl(_Host, {server_regexp, SR}, #{usr := {_, S, _}}) ->
@@ -117,8 +117,8 @@ match_acl(_Host, {resource_regexp, RR}, #{usr := {_, _, R}}) ->
match_regexp(R, RR);
match_acl(_Host, {node_regexp, {UR, SR}}, #{usr := {U, S, _}}) ->
match_regexp(U, UR) andalso match_regexp(S, SR);
match_acl(_Host, {user_glob, {UR, S}}, #{usr := {U, S, _}}) ->
match_regexp(U, UR);
match_acl(_Host, {user_glob, {UR, S1}}, #{usr := {U, S2, _}}) ->
S1 == S2 andalso match_regexp(U, UR);
match_acl(_Host, {user_glob, UR}, #{usr := {U, S, _}}) ->
ejabberd_router:is_my_host(S) andalso match_regexp(U, UR);
match_acl(_Host, {server_glob, SR}, #{usr := {_, S, _}}) ->
+9 -3
View File
@@ -151,7 +151,7 @@ get_commands_spec() ->
module = ?MODULE, function = set_loglevel,
args_desc = ["Desired logging level: none | emergency | alert | critical "
"| error | warning | notice | info | debug"],
args_example = [debug],
args_example = ["debug"],
args = [{loglevel, string}],
result = {res, rescode}},
@@ -208,6 +208,9 @@ get_commands_spec() ->
#ejabberd_commands{name = join_cluster, tags = [cluster],
desc = "Join this node into the cluster handled by Node",
longdesc = "This command works only with ejabberdctl, "
"not mod_http_api or other code that runs inside the "
"same ejabberd node that will be joined.",
module = ?MODULE, function = join_cluster,
args_desc = ["Nodename of the node to join"],
args_example = [<<"ejabberd1@machine7">>],
@@ -215,8 +218,11 @@ get_commands_spec() ->
result = {res, rescode}},
#ejabberd_commands{name = leave_cluster, tags = [cluster],
desc = "Remove and shutdown Node from the running cluster",
longdesc = "This command can be run from any running node of the cluster, "
"even the node to be removed.",
longdesc = "This command can be run from any running "
"node of the cluster, even the node to be removed. "
"In the removed node, this command works only when "
"using ejabberdctl, not mod_http_api or other code that "
"runs inside the same ejabberd node that will leave.",
module = ?MODULE, function = leave_cluster,
args_desc = ["Nodename of the node to kick from the cluster"],
args_example = [<<"ejabberd1@machine8">>],
+6 -1
View File
@@ -37,7 +37,8 @@
-export([start/1, stop/1, start_link/1, set_password/3,
check_password/4, user_exists/2,
get_users/2, count_users/2,
store_type/1, plain_password_required/1]).
store_type/1, plain_password_required/1,
reload/1]).
-include("logger.hrl").
@@ -109,6 +110,10 @@ init(Host) ->
State#state.password, State#state.tls_options),
{ok, State}.
reload(Host) ->
stop(Host),
start(Host).
plain_password_required(_) -> true.
store_type(_) -> external.
+59 -42
View File
@@ -43,7 +43,7 @@
process_closed/2, process_terminated/2, process_info/2]).
%% API
-export([get_presence/1, set_presence/2, resend_presence/1, resend_presence/2,
open_session/1, call/3, cast/2, send/2, close/1, close/2, stop/1,
open_session/1, call/3, cast/2, send/2, close/1, close/2, stop_async/1,
reply/2, copy_state/2, set_timeout/2, route/2, format_reason/2,
host_up/1, host_down/1, send_ws_ping/1, bounce_message_queue/2]).
@@ -110,10 +110,9 @@ close(Ref) ->
close(Ref, Reason) ->
xmpp_stream_in:close(Ref, Reason).
-spec stop(pid()) -> ok;
(state()) -> no_return().
stop(Ref) ->
xmpp_stream_in:stop(Ref).
-spec stop_async(pid()) -> ok.
stop_async(Pid) ->
xmpp_stream_in:stop_async(Pid).
-spec send(pid(), xmpp_element()) -> ok;
(state(), xmpp_element()) -> state().
@@ -181,10 +180,9 @@ host_down(Host) ->
%% Copies content of one c2s state to another.
%% This is needed for session migration from one pid to another.
-spec copy_state(state(), state()) -> state().
copy_state(#{owner := Owner} = NewState,
#{jid := JID, resource := Resource, sid := {Time, _},
auth_module := AuthModule, lserver := LServer,
pres_a := PresA} = OldState) ->
copy_state(NewState,
#{jid := JID, resource := Resource, auth_module := AuthModule,
lserver := LServer, pres_a := PresA} = OldState) ->
State1 = case OldState of
#{pres_last := Pres, pres_timestamp := PresTS} ->
NewState#{pres_last => Pres, pres_timestamp => PresTS};
@@ -194,7 +192,6 @@ copy_state(#{owner := Owner} = NewState,
Conn = get_conn_type(State1),
State2 = State1#{jid => JID, resource => Resource,
conn => Conn,
sid => {Time, Owner},
auth_module => AuthModule,
pres_a => PresA},
ejabberd_hooks:run_fold(c2s_copy_session, LServer, State2, [OldState]).
@@ -285,7 +282,8 @@ process_auth_result(#{sasl_mech := Mech,
State.
process_closed(State, Reason) ->
stop(State#{stop_reason => Reason}).
stop_async(self()),
State#{stop_reason => Reason}.
process_terminated(#{sid := SID, socket := Socket,
jid := JID, user := U, server := S, resource := R} = State,
@@ -293,17 +291,17 @@ process_terminated(#{sid := SID, socket := Socket,
Status = format_reason(State, Reason),
?INFO_MSG("(~ts) Closing c2s session for ~ts: ~ts",
[xmpp_socket:pp(Socket), jid:encode(JID), Status]),
Pres = #presence{type = unavailable,
from = JID,
to = jid:remove_resource(JID)},
State1 = case maps:is_key(pres_last, State) of
true ->
Pres = #presence{type = unavailable,
from = JID,
to = jid:remove_resource(JID)},
ejabberd_sm:close_session_unset_presence(SID, U, S, R,
Status),
broadcast_presence_unavailable(State, Pres);
broadcast_presence_unavailable(State, Pres, true);
false ->
ejabberd_sm:close_session(SID, U, S, R),
State
broadcast_presence_unavailable(State, Pres, false)
end,
bounce_message_queue(SID, JID),
State1;
@@ -386,7 +384,7 @@ sasl_mechanisms(Mechs, #{lserver := LServer} = State) ->
(<<"DIGEST-MD5">>) -> Type == plain;
(<<"SCRAM-SHA-1">>) -> Type /= external;
(<<"PLAIN">>) -> true;
(<<"X-OAUTH2">>) -> true;
(<<"X-OAUTH2">>) -> [ejabberd_auth_anonymous] /= ejabberd_auth:auth_modules(LServer);
(<<"EXTERNAL">>) -> maps:get(tls_verify, State, false);
(_) -> false
end, Mechs -- Mechs1).
@@ -491,7 +489,11 @@ handle_authenticated_packet(Pkt, #{lserver := LServer, jid := JID,
#iq{type = set, sub_els = [_]} ->
try xmpp:try_subtag(Pkt2, #xmpp_session{}) of
#xmpp_session{} ->
send(State2, xmpp:make_iq_result(Pkt2));
% It seems that some client are expecting to have response
% to session request be sent from server jid, let's make
% sure it is that.
Pkt3 = xmpp:set_to(Pkt2, jid:make(<<>>, LServer, <<>>)),
send(State2, xmpp:make_iq_result(Pkt3));
_ ->
check_privacy_then_route(State2, Pkt2)
catch _:{xmpp_codec, Why} ->
@@ -730,7 +732,7 @@ process_self_presence(#{lserver := LServer, sid := SID,
_ = ejabberd_sm:unset_presence(SID, U, S, R, Status),
{Pres1, State1} = ejabberd_hooks:run_fold(
c2s_self_presence, LServer, {Pres, State}, []),
State2 = broadcast_presence_unavailable(State1, Pres1),
State2 = broadcast_presence_unavailable(State1, Pres1, true),
maps:remove(pres_last, maps:remove(pres_timestamp, State2));
process_self_presence(#{lserver := LServer} = State,
#presence{type = available} = Pres) ->
@@ -751,28 +753,39 @@ update_priority(#{sid := SID, user := U, server := S, resource := R},
Priority = get_priority_from_presence(Pres),
ejabberd_sm:set_presence(SID, U, S, R, Priority, Pres).
-spec broadcast_presence_unavailable(state(), presence()) -> state().
broadcast_presence_unavailable(#{jid := JID, pres_a := PresA} = State, Pres) ->
-spec broadcast_presence_unavailable(state(), presence(), boolean()) -> state().
broadcast_presence_unavailable(#{jid := JID, pres_a := PresA} = State, Pres,
BroadcastToRoster) ->
#jid{luser = LUser, lserver = LServer} = JID,
BareJID = jid:remove_resource(JID),
Items1 = ejabberd_hooks:run_fold(roster_get, LServer,
[], [{LUser, LServer}]),
BareJID = jid:tolower(jid:remove_resource(JID)),
Items1 = case BroadcastToRoster of
true ->
Roster = ejabberd_hooks:run_fold(roster_get, LServer,
[], [{LUser, LServer}]),
lists:foldl(
fun(#roster{jid = LJID, subscription = Sub}, Acc)
when Sub == both; Sub == from ->
maps:put(LJID, 1, Acc);
(_, Acc) ->
Acc
end, #{BareJID => 1}, Roster);
_ ->
#{BareJID => 1}
end,
Items2 = ?SETS:fold(
fun(LJID, Items) ->
[#roster{jid = LJID, subscription = from}|Items]
end, Items1, PresA),
JIDs = lists:foldl(
fun(#roster{jid = LJID, subscription = Sub}, Tos)
when Sub == both orelse Sub == from ->
To = jid:make(LJID),
P = xmpp:set_to(Pres, jid:make(LJID)),
case privacy_check_packet(State, P, out) of
allow -> [To|Tos];
deny -> Tos
end;
(_, Tos) ->
Tos
end, [BareJID], Items2),
fun(LJID, Acc) ->
maps:put(LJID, 1, Acc)
end, Items1, PresA),
JIDs = lists:filtermap(
fun(LJid) ->
To = jid:make(LJid),
P = xmpp:set_to(Pres, To),
case privacy_check_packet(State, P, out) of
allow -> {true, To};
deny -> false
end
end, maps:keys(Items2)),
route_multiple(State, JIDs, Pres),
State#{pres_a => ?SETS:new()}.
@@ -902,7 +915,7 @@ bounce_message_queue({_, Pid} = SID, JID) ->
receive {route, Pkt} ->
ejabberd_router:route(Pkt),
bounce_message_queue(SID, JID)
after 0 ->
after 100 ->
ok
end
end.
@@ -937,7 +950,11 @@ fix_from_to(Pkt, #{jid := JID}) when ?is_stanza(Pkt) ->
{U, S, _} -> jid:replace_resource(JID, From#jid.resource);
_ -> From
end,
xmpp:set_from_to(Pkt, From1, JID)
To1 = case xmpp:get_to(Pkt) of
#jid{lresource = <<>>} = To2 -> To2;
_ -> JID
end,
xmpp:set_from_to(Pkt, From1, To1)
end;
fix_from_to(Pkt, _State) ->
Pkt.
@@ -991,4 +1008,4 @@ listen_options() ->
{tls_verify, false},
{zlib, false},
{max_stanza_size, infinity},
{max_fsm_queue, 5000}].
{max_fsm_queue, 10000}].
+1 -1
View File
@@ -1,5 +1,5 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Created : 5 Jul 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
-201
View File
@@ -23,190 +23,6 @@
%%%
%%%----------------------------------------------------------------------
%%% @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':
%%%
%%% <pre>#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}}</pre>
%%%
%%%
%%% === 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:
%%%
%%% <pre>calc_power(Base, Exponent) ->
%%% PowFloat = math:pow(Base, Exponent),
%%% round(PowFloat).</pre>
%%%
%%% Since this function will be called by ejabberd_commands, it must
%%% be exported.
%%% Add to your module:
%%% <pre>-export([calc_power/2]).</pre>
%%%
%%% 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:
%%%
%%% <pre>commands() ->
%%% [
%%%
%%% ].</pre>
%%%
%%% You need to include this header file in order to use the record:
%%%
%%% <pre>-include("ejabberd_commands.hrl").</pre>
%%%
%%% When your module is initialized or started, register your commands:
%%%
%%% <pre>ejabberd_commands:register_commands(commands()),</pre>
%%%
%%% And when your module is stopped, unregister your commands:
%%%
%%% <pre>ejabberd_commands:unregister_commands(commands()),</pre>
%%%
%%% That's all! Now when your module is started, the command will be
%%% registered and any frontend can access it. For example:
%%%
%%% <pre>$ 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
%%% </pre>
%%%
%%%
%%% == 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 caught. 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').
@@ -312,11 +128,6 @@ code_change(_OldVsn, State, _Extra) ->
-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.
%% A registered command is not directly available to be called through
%% ejabberd ReST API. It need to be exposed to be available through API.
register_commands(Commands) ->
lists:foreach(
fun(Command) ->
@@ -330,7 +141,6 @@ register_commands(Commands) ->
-spec unregister_commands([ejabberd_commands()]) -> ok.
%% @doc Unregister ejabberd commands.
unregister_commands(Commands) ->
lists:foreach(
fun(Command) ->
@@ -341,14 +151,11 @@ unregister_commands(Commands) ->
-spec list_commands() -> [{atom(), [aterm()], string()}].
%% @doc Get a list of all the available commands, arguments and description.
list_commands() ->
list_commands(?DEFAULT_VERSION).
-spec list_commands(integer()) -> [{atom(), [aterm()], string()}].
%% @doc Get a list of all the available commands, arguments and
%% description in a given API version.
list_commands(Version) ->
Commands = get_commands_definition(Version),
[{Name, Args, Desc} || #ejabberd_commands{name = Name,
@@ -357,7 +164,6 @@ list_commands(Version) ->
-spec get_command_format(atom()) -> {[aterm()], [{atom(),atom()}], rterm()}.
%% @doc Get the format of arguments and result of a command.
get_command_format(Name) ->
get_command_format(Name, noauth, ?DEFAULT_VERSION).
get_command_format(Name, Version) when is_integer(Version) ->
@@ -383,13 +189,11 @@ get_command_format(Name, Auth, Version) ->
-spec get_command_definition(atom()) -> ejabberd_commands().
%% @doc Get the definition record of a command.
get_command_definition(Name) ->
get_command_definition(Name, ?DEFAULT_VERSION).
-spec get_command_definition(atom(), integer()) -> ejabberd_commands().
%% @doc Get the definition record of a command in a given API version.
get_command_definition(Name, Version) ->
case lists:reverse(
lists:sort(
@@ -409,7 +213,6 @@ get_commands_definition() ->
-spec get_commands_definition(integer()) -> [ejabberd_commands()].
% @doc Returns all commands for a given API version
get_commands_definition(Version) ->
L = lists:reverse(
lists:sort(
@@ -450,15 +253,11 @@ do_execute_command(Command, Arguments) ->
-spec get_tags_commands() -> [{string(), [string()]}].
%% @spec () -> [{Tag::string(), [CommandName::string()]}]
%% @doc Get all the tags and associated commands.
get_tags_commands() ->
get_tags_commands(?DEFAULT_VERSION).
-spec get_tags_commands(integer()) -> [{string(), [string()]}].
%% @spec (integer) -> [{Tag::string(), [CommandName::string()]}]
%% @doc Get all the tags and associated commands in a given API version
get_tags_commands(Version) ->
CommandTags = [{Name, Tags} ||
#ejabberd_commands{name = Name, tags = Tags}
+3 -2
View File
@@ -80,7 +80,7 @@ md_tag(p, V) ->
md_tag(h1, V) ->
[<<"\n\n## ">>, V, <<"\n">>];
md_tag(h2, V) ->
[<<"\n\n### ">>, V, <<"\n">>];
[<<"\n__">>, V, <<"__\n\n">>];
md_tag(strong, V) ->
[<<"*">>, V, <<"*">>];
md_tag(_, V) ->
@@ -460,7 +460,8 @@ generate_md_output(File, RegExp, Languages) ->
Cmds4 = [maybe_add_policy_arguments(Cmd) || Cmd <- Cmds3],
Langs = binary:split(Languages, <<",">>, [global]),
Header = <<"---\ntitle: Administration API reference\ntoc: true\nmenu: Administration API\norder: 40\n"
"// Autogenerated with 'ejabberdctl gen_markdown_doc_for_commands'\n---">>,
"// Autogenerated with 'ejabberdctl gen_markdown_doc_for_commands'\n---\n\n"
"This section describes API of ejabberd version ", (ejabberd_option:version())/binary>>,
Out = lists:map(fun(C) -> gen_doc(C, false, Langs) end, Cmds4),
{ok, Fh} = file:open(File, [write]),
io:format(Fh, "~ts~ts", [Header, Out]),
+22 -4
View File
@@ -102,8 +102,8 @@ transform(_Host, certfiles, CertFiles1, Acc) ->
transform(_Host, acme, ACME, Acc) ->
ACME1 = lists:map(
fun({ca_url, URL} = Opt) ->
case http_uri:parse(binary_to_list(URL)) of
{ok, {_, _, "acme-v01.api.letsencrypt.org", _, _, _}} ->
case misc:uri_parse(URL) of
{ok, _, "acme-v01.api.letsencrypt.org", _, _} ->
NewURL = ejabberd_acme:default_directory_url(),
?WARNING_MSG("ACME directory URL ~ts defined in "
"option acme->ca_url is deprecated "
@@ -245,8 +245,9 @@ filter(_, _, _, _) ->
%%%===================================================================
transform_listener(Opts, Acc) ->
Opts1 = transform_request_handlers(Opts),
Opts2 = remove_inet_options(Opts1),
collect_listener_certfiles(Opts2, Acc).
Opts2 = transform_turn_ip(Opts1),
Opts3 = remove_inet_options(Opts2),
collect_listener_certfiles(Opts3, Acc).
transform_request_handlers(Opts) ->
case lists:keyfind(module, 1, Opts) of
@@ -258,6 +259,14 @@ transform_request_handlers(Opts) ->
Opts
end.
transform_turn_ip(Opts) ->
case lists:keyfind(module, 1, Opts) of
{_, ejabberd_stun} ->
replace_turn_ip(Opts);
_ ->
Opts
end.
replace_request_handlers(Opts) ->
Handlers = proplists:get_value(request_handlers, Opts, []),
Handlers1 =
@@ -322,6 +331,15 @@ remove_xmlrpc_access_commands(Opts) ->
true
end, Opts).
replace_turn_ip(Opts) ->
lists:filtermap(
fun({turn_ip, Val}) ->
warn_replaced_option(turn_ip, turn_ipv4_address),
{true, {turn_ipv4_address, Val}};
(_) ->
true
end, Opts).
remove_inet_options(Opts) ->
lists:filter(
fun({Opt, _}) when Opt == inet; Opt == inet6 ->
+10 -66
View File
@@ -23,33 +23,14 @@
%%%
%%%----------------------------------------------------------------------
%%% @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(gen_server).
-author('alexey@process-one.net').
-export([start/0, start_link/0, process/1, process2/2,
register_commands/3, unregister_commands/3]).
-export([start/0, start_link/0, process/1, process2/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
@@ -111,8 +92,6 @@ start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
ets:new(ejabberd_ctl_cmds, [named_table, set, public]),
ets:new(ejabberd_ctl_host_cmds, [named_table, set, public]),
{ok, #state{}}.
handle_call(Request, From, State) ->
@@ -133,30 +112,10 @@ terminate(_Reason, _State) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%-----------------------------
%% ejabberdctl Command management
%%-----------------------------
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().
process(Args) ->
process(Args, ?DEFAULT_VERSION).
@@ -295,7 +254,7 @@ process2(Args, AccessCommands, Auth, Version) ->
%% Command calling
%%-----------------------------
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()}
%% @spec (Args::[string()], Auth, AccessCommands, Version) -> string() | integer() | {string(), integer()}
try_run_ctp(Args, Auth, AccessCommands, Version) ->
try ejabberd_hooks:run_fold(ejabberd_ctl_process, false, [Args]) of
false when Args /= [] ->
@@ -316,7 +275,7 @@ try_run_ctp(Args, Auth, AccessCommands, Version) ->
{io_lib:format("Error in ejabberd ctl process: '~p' ~p", [Error, Why]), ?STATUS_USAGE}
end.
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()}
%% @spec (Args::[string()], Auth, AccessCommands, Version) -> string() | integer() | {string(), integer()}
try_call_command(Args, Auth, AccessCommands, Version) ->
try call_command(Args, Auth, AccessCommands, Version) of
{Reason, wrong_command_arguments} ->
@@ -340,7 +299,7 @@ try_call_command(Args, Auth, AccessCommands, Version) ->
?STATUS_ERROR}
end.
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} | {error, ErrorType}
%% @spec (Args::[string()], Auth, AccessCommands, Version) -> string() | integer() | {string(), integer()} | {error, ErrorType}
call_command([CmdString | Args], Auth, _AccessCommands, Version) ->
CmdStringU = ejabberd_regexp:greplace(
list_to_binary(CmdString), <<"-">>, <<"_">>),
@@ -472,7 +431,9 @@ make_status(ok) -> ?STATUS_SUCCESS;
make_status(true) -> ?STATUS_SUCCESS;
make_status(Code) when is_integer(Code), Code > 255 -> ?STATUS_ERROR;
make_status(Code) when is_integer(Code), Code > 0 -> Code;
make_status(_Error) -> ?STATUS_ERROR.
make_status(Error) ->
io:format("Error: ~p~n", [Error]),
?STATUS_ERROR.
get_list_commands(Version) ->
try ejabberd_commands:list_commands(Version) of
@@ -507,13 +468,6 @@ is_supported_args(Args) ->
end,
Args).
get_list_ctls() ->
case catch ets:tab2list(ejabberd_ctl_cmds) of
{'EXIT', _} -> [];
Cs -> [{NameArgs, [], Desc} || {NameArgs, Desc} <- Cs]
end.
%%-----------------------------
%% Print help
%%-----------------------------
@@ -539,8 +493,7 @@ print_usage(HelpMode, MaxC, ShCode, Version) ->
{"restart", [], "Restart ejabberd"},
{"help", ["[--tags [tag] | com?*]"], "Show help (try: ejabberdctl help help)"},
{"mnesia", ["[info]"], "show information of Mnesia system"}] ++
get_list_commands(Version) ++
get_list_ctls(),
get_list_commands(Version),
print(
["Usage: ", ?B("ejabberdctl"), " [--no-timeout] [--node ", ?U("nodename"), "] [--version ", ?U("api_version"), "] ",
@@ -742,7 +695,7 @@ print_usage_help(MaxC, ShCode) ->
%% Print usage command
%%-----------------------------
%% @spec (CmdSubString::string(), MaxC::integer(), ShCode::boolean()) -> ok
%% @spec (CmdSubString::string(), MaxC::integer(), ShCode::boolean(), Version) -> ok
print_usage_commands2(CmdSubString, MaxC, ShCode, Version) ->
%% Get which command names match this substring
AllCommandsNames = [atom_to_list(Name) || {Name, _, _} <- ejabberd_commands:list_commands(Version)],
@@ -785,7 +738,7 @@ filter_commands_regexp(All, Glob) ->
end,
All).
%% @spec (Cmd::string(), MaxC::integer(), ShCode::boolean()) -> ok
%% @spec (Cmd::string(), MaxC::integer(), ShCode::boolean(), Version) -> ok
print_usage_command(Cmd, MaxC, ShCode, Version) ->
Name = list_to_atom(Cmd),
C = ejabberd_commands:get_command_definition(Name, Version),
@@ -872,12 +825,3 @@ disable_logging() ->
disable_logging() ->
logger:set_primary_config(level, none).
-endif.
%%-----------------------------
%% Command management
%%-----------------------------
%%+++
%% Struct(Integer res) create_account(Struct(String user, String server, String password))
%%format_usage_xmlrpc(ArgsDef, ResultDef) ->
%% ["aaaa bbb ccc"].
+4 -3
View File
@@ -69,10 +69,11 @@ man(Lang) ->
catch _:undef -> []
end
end, ejabberd_config:callback_modules(all)),
Version = binary_to_list(ejabberd_option:version()),
Options =
["TOP LEVEL OPTIONS",
"-----------------",
tr(Lang, ?T("This section describes top level options of ejabberd.")),
"This section describes top level options of ejabberd "++Version,
io_lib:nl()] ++
lists:flatmap(
fun(Opt) ->
@@ -92,7 +93,7 @@ man(Lang) ->
"MODULES",
"-------",
"[[modules]]",
tr(Lang, ?T("This section describes options of all ejabberd modules.")),
"This section describes options of all modules in ejabberd "++Version,
io_lib:nl()] ++
lists:flatmap(
fun({M, Descr, DocOpts, Backends, Example}) ->
@@ -111,7 +112,7 @@ man(Lang) ->
"LISTENERS",
"-------",
"[[listeners]]",
tr(Lang, ?T("This section describes options of all ejabberd listeners.")),
"This section describes options of all listeners in ejabberd "++Version,
io_lib:nl(),
"TODO"],
AsciiData =
+18 -7
View File
@@ -193,7 +193,13 @@ receive_headers(#state{trail = Trail} = State) ->
Socket = State#state.socket,
Data = SockMod:recv(Socket, 0, 300000),
case Data of
{error, _} -> ok;
{error, closed} when State#state.request_method == undefined ->
% socket closed without receiving anything in it
ok;
{error, Error} ->
?DEBUG("Error when retrieving http headers ~p: ~p",
[State#state.sockmod, Error]),
ok;
{ok, D} ->
parse_headers(State#state{trail = <<Trail/binary, D/binary>>})
end.
@@ -386,7 +392,7 @@ extract_path_query(#state{request_method = Method,
{'EXIT', _Reason} -> [];
LQ -> LQ
end,
{State, {LPath, LQuery, <<"">>}}
{State, {LPath, LQuery, <<"">>, Path}}
end;
extract_path_query(#state{request_method = Method,
request_path = {abs_path, Path},
@@ -402,7 +408,7 @@ extract_path_query(#state{request_method = Method,
{LPath, _Query} ->
case Method of
'PUT' ->
{State, {LPath, [], Trail}};
{State, {LPath, [], Trail, Path}};
'POST' ->
case recv_data(State) of
{ok, Data} ->
@@ -410,7 +416,7 @@ extract_path_query(#state{request_method = Method,
{'EXIT', _Reason} -> [];
LQ -> LQ
end,
{State, {LPath, LQuery, Data}};
{State, {LPath, LQuery, Data, Path}};
error ->
{State, false}
end
@@ -451,7 +457,7 @@ process_request(#state{request_method = Method,
case extract_path_query(State) of
{State2, false} ->
{State2, make_bad_request(State)};
{State2, {LPath, LQuery, Data}} ->
{State2, {LPath, LQuery, Data, RawPath}} ->
PeerName = case SockPeer of
none ->
case SockMod of
@@ -471,6 +477,7 @@ process_request(#state{request_method = Method,
IP = analyze_ip_xff(IPHere, XFF),
Request = #request{method = Method,
path = LPath,
raw_path = RawPath,
q = LQuery,
auth = Auth,
length = Length,
@@ -857,9 +864,13 @@ parse_urlencoded(<<>>, Last, Cur, _State) ->
parse_urlencoded(undefined, _, _, _) -> [].
apply_custom_headers(Headers, CustomHeaders) ->
M = maps:merge(maps:from_list(Headers),
{Doctype, Headers2} = case Headers -- [html] of
Headers -> {[], Headers};
Other -> {[html], Other}
end,
M = maps:merge(maps:from_list(Headers2),
maps:from_list(CustomHeaders)),
maps:to_list(M).
Doctype ++ maps:to_list(M).
% The following code is mostly taken from yaws_ssl.erl
+41 -12
View File
@@ -105,10 +105,18 @@ init({_, _, Transport} = EndPoint, Module, AllOpts) ->
-spec init(endpoint(), module(), opts(), [gen_tcp:option()]) -> ok.
init({Port, _, udp} = EndPoint, Module, Opts, SockOpts) ->
case gen_udp:open(Port, [binary,
{Port2, ExtraOpts} = case Port of
<<"unix:", Path/binary>> ->
SO = lists:keydelete(ip, 1, SockOpts),
file:delete(Path),
{0, [{ip, {local, Path}} | SO]};
_ ->
{Port, SockOpts}
end,
case gen_udp:open(Port2, [binary,
{active, false},
{reuseaddr, true} |
SockOpts]) of
ExtraOpts]) of
{ok, Socket} ->
case inet:sockname(Socket) of
{ok, {Addr, Port1}} ->
@@ -174,15 +182,22 @@ init({Port, _, tcp} = EndPoint, Module, Opts, SockOpts) ->
-spec listen_tcp(inet:port_number(), [gen_tcp:option()]) ->
{ok, inet:socket()} | {error, system_limit | inet:posix()}.
listen_tcp(Port, SockOpts) ->
Res = gen_tcp:listen(Port, [binary,
{Port2, ExtraOpts} = case Port of
<<"unix:", Path/binary>> ->
SO = lists:keydelete(ip, 1, SockOpts),
file:delete(Path),
{0, [{ip, {local, Path}} | SO]};
_ ->
{Port, SockOpts}
end,
Res = gen_tcp:listen(Port2, [binary,
{packet, 0},
{active, false},
{reuseaddr, true},
{nodelay, true},
{send_timeout, ?TCP_SEND_TIMEOUT},
{send_timeout_close, true},
{keepalive, true} |
SockOpts]),
{keepalive, true} | ExtraOpts]),
case Res of
{ok, ListenSocket} ->
{ok, ListenSocket};
@@ -226,6 +241,8 @@ accept(ListenSocket, Module, State, Sup, Interval, Proxy, Arity) ->
?ERROR_MSG("(~w) Proxy protocol parsing failed: ~ts",
[ListenSocket, format_error(Err)]),
gen_tcp:close(Socket);
{undefined, undefined} ->
gen_tcp:close(Socket);
{{Addr, Port}, {PAddr, PPort}} = SP ->
%% THIS IS WRONG
State2 = [{sock_peer_name, SP} | State],
@@ -307,7 +324,12 @@ start_connection(Module, Arity, Socket, State, Sup) ->
Module:accept(Pid),
{ok, Pid};
Err ->
exit(Pid, kill),
case Sup of
undefined ->
exit(Pid, kill);
_ ->
supervisor:terminate_child(Sup, Pid)
end,
Err
end;
Err ->
@@ -459,11 +481,16 @@ format_error(Reason) ->
-spec format_endpoint(endpoint()) -> string().
format_endpoint({Port, IP, _Transport}) ->
IPStr = case tuple_size(IP) of
4 -> inet:ntoa(IP);
8 -> "[" ++ inet:ntoa(IP) ++ "]"
end,
IPStr ++ ":" ++ integer_to_list(Port).
case Port of
Unix when is_binary(Unix) ->
<<"unix:", Unix/binary>>;
_ ->
IPStr = case tuple_size(IP) of
4 -> inet:ntoa(IP);
8 -> "[" ++ inet:ntoa(IP) ++ "]"
end,
IPStr ++ ":" ++ integer_to_list(Port)
end.
-spec format_transport(transport(), opts()) -> string().
format_transport(Transport, Opts) ->
@@ -618,7 +645,9 @@ partition(Fun, Opts) ->
-spec listen_opt_type(atom()) -> econf:validator().
listen_opt_type(port) ->
econf:int(0, 65535);
econf:either(
econf:int(0, 65535),
econf:binary("^unix:.*"));
listen_opt_type(module) ->
econf:beam([[{start, 3}, {start, 2}],
[{start_link, 3}, {start_link, 2}],
+13 -7
View File
@@ -47,13 +47,6 @@
-export_type([loglevel/0]).
-spec restart() -> ok.
-spec reopen_log() -> ok.
-spec rotate_log() -> ok.
-spec get() -> loglevel().
-spec set(0..5 | loglevel()) -> ok.
-spec flush() -> ok.
%%%===================================================================
%%% API
%%%===================================================================
@@ -173,14 +166,17 @@ do_start(Level) ->
lager:set_loghwm(Handler, LogRateLimit)
end, gen_event:which_handlers(lager_event)).
-spec restart() -> ok.
restart() ->
Level = ejabberd_option:loglevel(),
application:stop(lager),
start(Level).
-spec reopen_log() -> ok.
reopen_log() ->
ok.
-spec rotate_log() -> ok.
rotate_log() ->
catch lager_crash_log ! rotate,
lists:foreach(
@@ -190,6 +186,7 @@ rotate_log() ->
ok
end, gen_event:which_handlers(lager_event)).
-spec get() -> loglevel().
get() ->
Handlers = get_lager_handlers(),
lists:foldl(fun(lager_console_backend, _Acc) ->
@@ -201,6 +198,7 @@ get() ->
end,
none, Handlers).
-spec set(0..5 | loglevel()) -> ok.
set(N) when is_integer(N), N>=0, N=<5 ->
set(convert_loglevel(N));
set(Level) when ?is_loglevel(Level) ->
@@ -241,6 +239,7 @@ get_lager_version() ->
false -> "0.0.0"
end.
-spec flush() -> ok.
flush() ->
application:stop(lager),
application:stop(sasl).
@@ -261,6 +260,7 @@ start(Level) ->
Config = #{max_no_bytes => LogRotateSize,
max_no_files => LogRotateCount,
filesync_repeat_interval => no_repeat,
file_check => 1000,
sync_mode_qlen => 1000,
drop_mode_qlen => 1000,
flush_qlen => 5000},
@@ -297,6 +297,7 @@ start(Level) ->
Err
end.
-spec restart() -> ok.
restart() ->
ok.
@@ -321,16 +322,20 @@ msg() ->
[{logger_formatter, [[logger_formatter, title], ":", io_lib:nl()], []},
msg, io_lib:nl()].
-spec reopen_log() -> ok.
reopen_log() ->
ok.
-spec rotate_log() -> ok.
rotate_log() ->
ok.
-spec get() -> loglevel().
get() ->
#{level := Level} = logger:get_primary_config(),
Level.
-spec set(0..5 | loglevel()) -> ok.
set(N) when is_integer(N), N>=0, N=<5 ->
set(convert_loglevel(N));
set(Level) when ?is_loglevel(Level) ->
@@ -346,6 +351,7 @@ set(Level) when ?is_loglevel(Level) ->
end
end.
-spec flush() -> ok.
flush() ->
lists:foreach(
fun(#{id := HandlerId, module := logger_std_h}) ->
+118 -28
View File
@@ -36,14 +36,14 @@ doc() ->
{listen,
#{value => "[Options, ...]",
desc =>
?T("The option for listeners configuration. See "
"<<listeners,Listeners>> section of this document "
?T("The option for listeners configuration. See the "
"http://../listen/[Listen Modules] section "
"for details.")}},
{modules,
#{value => "{Module: Options}",
desc =>
?T("The option for modules configuration. See "
"<<modules,Modules>> section of this document "
"http://../modules/[Modules] section "
"for details.")}},
{loglevel,
#{value =>
@@ -60,32 +60,49 @@ doc() ->
#{value => "timeout()",
desc =>
?T("The time of a cached item to keep in cache. "
"Once it's expired, the corresponding item is "
"erased from cache. The default value is 'one hour'.")}},
"Once it's expired, the corresponding item is "
"erased from cache. The default value is 'one hour'. "
"Several modules have a similar option; and some core "
"ejabberd parts support similar options too, see "
"'auth_cache_life_time', 'oauth_cache_life_time', "
"'router_cache_life_time', and 'sm_cache_life_time'.")}},
{cache_missed,
#{value => "true | false",
desc =>
?T("Whether or not to cache missed lookups. When there is "
"an attempt to lookup for a value in a database and "
"this value is not found and the option is set to 'true', "
"this attempt will be cached and no attempts will be "
"performed until the cache expires (see 'cache_life_time'). "
"Usually you don't want to change it. Default is 'true'.")}},
"an attempt to lookup for a value in a database and "
"this value is not found and the option is set to 'true', "
"this attempt will be cached and no attempts will be "
"performed until the cache expires (see 'cache_life_time'). "
"Usually you don't want to change it. Default is 'true'. "
"Several modules have a similar option; and some core "
"ejabberd parts support similar options too, see "
"'auth_cache_missed', 'oauth_cache_missed', "
"'router_cache_missed', and 'sm_cache_missed'.")}},
{cache_size,
#{value => "pos_integer() | infinity",
desc =>
?T("A maximum number of items (not memory!) in cache. "
"The rule of thumb, for all tables except rosters, "
"you should set it to the number of maximum online "
"users you expect. For roster multiply this number "
"by 20 or so. If the cache size reaches this threshold, "
"it's fully cleared, i.e. all items are deleted, and "
"the corresponding warning is logged. You should avoid "
"frequent cache clearance, because this degrades "
"performance. The default value is '1000'.")}},
?T("A maximum number of items (not memory!) in cache. "
"The rule of thumb, for all tables except rosters, "
"you should set it to the number of maximum online "
"users you expect. For roster multiply this number "
"by 20 or so. If the cache size reaches this threshold, "
"it's fully cleared, i.e. all items are deleted, and "
"the corresponding warning is logged. You should avoid "
"frequent cache clearance, because this degrades "
"performance. The default value is '1000'. "
"Several modules have a similar option; and some core "
"ejabberd parts support similar options too, see "
"'auth_cache_size', 'oauth_cache_size', "
"'router_cache_size', and 'sm_cache_size'.")}},
{use_cache,
#{value => "true | false",
desc => ?T("Enable or disable cache. The default is 'true'.")}},
desc =>
?T("Enable or disable cache. The default is 'true'. "
"Several modules have a similar option; and some core "
"ejabberd parts support similar options too, see "
"'auth_use_cache', 'oauth_use_cache', 'router_use_cache', "
"and 'sm_use_cache'.")}},
{default_db,
#{value => "mnesia | sql",
desc =>
@@ -93,7 +110,7 @@ doc() ->
"Modules and other components (e.g. authentication) "
"may have its own value. The default value is 'mnesia'.")}},
{default_ram_db,
#{value => "mnesia | sql | redis",
#{value => "mnesia | redis | sql",
desc =>
?T("Default volatile (in-memory) storage for ejabberd. "
"Modules and other components (e.g. session management) "
@@ -236,7 +253,7 @@ doc() ->
{acme,
#{value => ?T("Options"),
desc =>
?T("ACME configuration. ACME is used to automatically "
?T("http://../basic/#acme[ACME] configuration, to automatically "
"obtain SSL certificates for the domains served by ejabberd, "
"which means that certificate requests and renewals are "
"performed to some CA server (aka \"ACME server\") in a fully "
@@ -300,6 +317,13 @@ doc() ->
"'sasl_anon' means that the SASL Anonymous method will be used. "
"'both' means that SASL Anonymous and login anonymous are both "
"enabled. The default value is 'sasl_anon'.")}},
{api_permissions,
#{value => "[Permission, ...]",
desc =>
?T("Define the permissions for API access. Please consult the "
"ejabberd Docs web -> For Developers -> ejabberd ReST API -> "
"https://docs.ejabberd.im/developer/ejabberd-api/permissions/"
"[API Permissions].")}},
{append_host_config,
#{value => "{Host: Options}",
desc =>
@@ -330,6 +354,13 @@ doc() ->
"considered successful as long as authentication of "
"at least one of the methods succeeds. "
"The default value is '[mnesia]'.")}},
{auth_opts,
#{value => "[Option, ...]",
desc =>
?T("This is used by the contributed module "
"'ejabberd_auth_http' that can be installed from the "
"'ejabberd-contrib' Git repository. Please refer to that "
"module's README file for details.")}},
{auth_password_format,
#{value => "plain | scram",
desc =>
@@ -415,7 +446,8 @@ doc() ->
"any given JID. The option is intended to protect the server "
"from CAPTCHA DoS. The default value is 'infinity'.")}},
{captcha_host,
#{desc => ?T("Deprecated. Use 'captcha_url' instead.")}},
#{value => "String",
desc => ?T("Deprecated. Use 'captcha_url' instead.")}},
{captcha_url,
#{value => ?T("URL"),
desc =>
@@ -453,7 +485,7 @@ doc() ->
desc =>
?T("A list of Erlang nodes to connect on ejabberd startup. "
"This option is mostly intended for ejabberd customization "
"and sofisticated setups. The default value is an empty list.")}},
"and sophisticated setups. The default value is an empty list.")}},
{define_macro,
#{value => "{MacroName: MacroValue}",
desc =>
@@ -516,6 +548,11 @@ doc() ->
#{value => "2..1000",
desc =>
?T("The number of components to balance.")}}]},
{extauth_pool_name,
#{value => ?T("Name"),
desc =>
?T("Define the pool name appendix, so the full pool name will be "
"'extauth_pool_Name'. The default value is the hostname.")}},
{extauth_pool_size,
#{value => ?T("Size"),
desc =>
@@ -527,6 +564,28 @@ doc() ->
desc =>
?T("Indicate in this option the full path to the external "
"authentication script. The script must be executable by ejabberd.")}},
{ext_api_headers,
#{value => "Headers",
desc =>
?T("String of headers (separated with commas ',') that will be "
"provided by ejabberd when sending ReST requests. "
"The default value is an empty string of headers: '\"\"'.")}},
{ext_api_http_pool_size,
#{value => "pos_integer()",
desc =>
?T("Define the size of the HTTP pool, that is, the maximum number "
"of sessions that the ejabberd ReST service will handle "
"simultaneously. The default value is: '100'.")}},
{ext_api_path_oauth,
#{value => "Path",
desc =>
?T("Define the base URI path when performing OAUTH ReST requests. "
"The default value is: '\"/oauth\"'.")}},
{ext_api_url,
#{value => "URL",
desc =>
?T("Define the base URI when performing ReST requests. "
"The default value is: '\"http://localhost/api\"'.")}},
{fqdn,
#{value => ?T("Domain"),
desc =>
@@ -577,6 +636,26 @@ doc() ->
"file 'Filename'. The options that do not match this "
"criteria are not accepted. The default value is to include "
"all options.")}}]},
{jwt_auth_only_rule,
#{value => ?T("AccessName"),
desc =>
?T("This ACL rule defines accounts that can use only this auth "
"method, even if others are also defined in the ejabberd "
"configuration file. In other words: if there are several auth "
"methods enabled for this host (JWT, SQL, ...), users that "
"match this rule can only use JWT. "
"The default value is 'none'.")}},
{jwt_jid_field,
#{value => ?T("FieldName"),
desc =>
?T("By default, the JID is defined in the '\"jid\"' JWT field. "
"This option allows to specify other JWT field name "
"where the JID is defined.")}},
{jwt_key,
#{value => ?T("FilePath"),
desc =>
?T("Path to the file that contains the JWK Key. "
"The default value is 'undefined'.")}},
{language,
#{value => ?T("Language"),
desc =>
@@ -748,7 +827,7 @@ doc() ->
desc =>
{?T("Whether to use 'new' SQL schema. All schemas are located "
"at <https://github.com/processone/ejabberd/tree/~s/sql>. "
"There are two schemas available. The default lecacy schema "
"There are two schemas available. The default legacy schema "
"allows to store one XMPP domain into one ejabberd database. "
"The 'new' schema allows to handle several XMPP domains in a "
"single ejabberd database. Using this 'new' schema is best when "
@@ -780,6 +859,12 @@ doc() ->
desc =>
?T("Same as 'cache_size', but applied to OAuth cache "
"only. If not set, the value from 'cache_size' will be used.")}},
{oauth_client_id_check,
#{value => "allow | db | deny",
desc =>
?T("Define whether the client authentication is always allowed, "
"denied, or it will depend if the client ID is present in the "
"database. The default value is 'allow'.")}},
{oauth_use_cache,
#{value => "true | false",
desc =>
@@ -937,7 +1022,7 @@ doc() ->
?T("Same as 'cache_size', but applied to routing table cache "
"only. If not set, the value from 'cache_size' will be used.")}},
{router_db_type,
#{value => "mnesia | sql | redis",
#{value => "mnesia | redis | sql",
desc =>
?T("Database backend to use for routing information. "
"The default value is picked from 'default_ram_db' option, or "
@@ -1097,7 +1182,7 @@ doc() ->
?T("Same as 'cache_size', but applied to client sessions table cache "
"only. If not set, the value from 'cache_size' will be used.")}},
{sm_db_type,
#{value => "mnesia | sql | redis",
#{value => "mnesia | redis | sql",
desc =>
?T("Database backend to use for client sessions information. "
"The default value is picked from 'default_ram_db' option, or "
@@ -1108,7 +1193,7 @@ doc() ->
?T("Same as 'use_cache', but applied to client sessions table cache "
"only. If not set, the value from 'use_cache' will be used.")}},
{sql_type,
#{value => "mysql | pgsql | sqlite | mssql | odbc",
#{value => "mssql | mysql | odbc | pgsql | sqlite",
desc =>
?T("The type of an SQL connection. The default is 'odbc'.")}},
{sql_connect_timeout,
@@ -1144,6 +1229,11 @@ doc() ->
?T("The port where the SQL server is accepting connections. "
"The default is '3306' for MySQL, '5432' for PostgreSQL and "
"'1433' for MSSQL. The option has no effect for SQLite.")}},
{sql_prepared_statements,
#{value => "true | false",
desc =>
?T("This option is 'true' by default, and is useful to disable "
"prepared statements. The option is valid for PostgreSQL.")}},
{sql_query_timeout,
#{value => "timeout()",
desc =>
+1 -1
View File
@@ -1,5 +1,5 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Created : 4 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
+1 -1
View File
@@ -1,5 +1,5 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Created : 6 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
+6 -45
View File
@@ -1,7 +1,7 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_regexp.erl
%%% Author : Badlop
%%% Purpose : Frontend to Re and Regexp OTP modules
%%% Purpose : Frontend to Re OTP module
%%% Created : 8 Dec 2011 by Badlop
%%%
%%%
@@ -25,66 +25,27 @@
-module(ejabberd_regexp).
-export([exec/2, run/2, split/2, replace/3, greplace/3, sh_to_awk/1]).
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.
-export([run/2, split/2, replace/3, greplace/3, sh_to_awk/1]).
-spec run(binary(), binary()) -> match | nomatch | {error, any()}.
run(String, Regexp) ->
case exec({re, run, [String, Regexp, [{capture, none}, unicode]]},
{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.
re:run(String, Regexp, [{capture, none}, unicode]).
-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.
re:split(String, Regexp, [{return, binary}]).
-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.
re:replace(String, Regexp, New, [{return, binary}]).
-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.
re:replace(String, Regexp, New, [global, {return, binary}]).
%% This code was copied and adapted from xmerl_regexp.erl
+1 -1
View File
@@ -1,5 +1,5 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
+1 -1
View File
@@ -1,5 +1,5 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
+5 -5
View File
@@ -319,7 +319,7 @@ host_down(Host) ->
case ejabberd_router:host_of_route(From) of
Host ->
ejabberd_s2s_out:send(Pid, Err),
ejabberd_s2s_out:stop(Pid);
ejabberd_s2s_out:stop_async(Pid);
_ ->
ok
end;
@@ -473,14 +473,14 @@ new_connection(MyServer, Server, From, FromTo,
if Pid1 == Pid ->
ejabberd_s2s_out:connect(Pid);
true ->
ejabberd_s2s_out:stop(Pid)
ejabberd_s2s_out:stop_async(Pid)
end,
[Pid1];
{aborted, Reason} ->
?ERROR_MSG("Failed to register s2s connection ~ts -> ~ts: "
"Mnesia failure: ~p",
[MyServer, Server, Reason]),
ejabberd_s2s_out:stop(Pid),
ejabberd_s2s_out:stop_async(Pid),
[]
end.
@@ -553,13 +553,13 @@ stop_s2s_connections(Err) ->
lists:foreach(
fun({_Id, Pid, _Type, _Module}) ->
ejabberd_s2s_in:send(Pid, Err),
ejabberd_s2s_in:stop(Pid),
ejabberd_s2s_in:stop_async(Pid),
supervisor:terminate_child(ejabberd_s2s_in_sup, Pid)
end, supervisor:which_children(ejabberd_s2s_in_sup)),
lists:foreach(
fun({_Id, Pid, _Type, _Module}) ->
ejabberd_s2s_out:send(Pid, Err),
ejabberd_s2s_out:stop(Pid),
ejabberd_s2s_out:stop_async(Pid),
supervisor:terminate_child(ejabberd_s2s_out_sup, Pid)
end, supervisor:which_children(ejabberd_s2s_out_sup)),
_ = mnesia:clear_table(s2s),
+7 -5
View File
@@ -38,7 +38,7 @@
-export([handle_unexpected_info/2, handle_unexpected_cast/2,
reject_unauthenticated_packet/2, process_closed/2]).
%% API
-export([stop/1, close/1, close/2, send/2, update_state/2, establish/1,
-export([stop_async/1, close/1, close/2, send/2, update_state/2, establish/1,
host_up/1, host_down/1]).
-include("xmpp.hrl").
@@ -64,8 +64,9 @@ close(Ref) ->
close(Ref, Reason) ->
xmpp_stream_in:close(Ref, Reason).
stop(Ref) ->
xmpp_stream_in:stop(Ref).
-spec stop_async(pid()) -> ok.
stop_async(Pid) ->
xmpp_stream_in:stop_async(Pid).
accept(Ref) ->
xmpp_stream_in:accept(Ref).
@@ -130,7 +131,8 @@ process_closed(#{server := LServer} = State, Reason) ->
end,
?INFO_MSG("Closing inbound s2s connection ~ts -> ~ts: ~ts",
[RServer, LServer, xmpp_stream_out:format_error(Reason)]),
stop(State).
stop_async(self()),
State.
%%%===================================================================
%%% xmpp_stream_in callbacks
@@ -349,4 +351,4 @@ listen_options() ->
{tls, false},
{tls_compression, false},
{max_stanza_size, infinity},
{max_fsm_queue, 5000}].
{max_fsm_queue, 10000}].
+9 -7
View File
@@ -36,7 +36,7 @@
-export([process_auth_result/2, process_closed/2, handle_unexpected_info/2,
handle_unexpected_cast/2, process_downgraded/2]).
%% API
-export([start/3, start_link/3, connect/1, close/1, close/2, stop/1, send/2,
-export([start/3, start_link/3, connect/1, close/1, close/2, stop_async/1, send/2,
route/2, establish/1, update_state/2, host_up/1, host_down/1]).
-include("xmpp.hrl").
@@ -79,10 +79,9 @@ close(Ref) ->
close(Ref, Reason) ->
xmpp_stream_out:close(Ref, Reason).
-spec stop(pid()) -> ok;
(state()) -> no_return().
stop(Ref) ->
xmpp_stream_out:stop(Ref).
-spec stop_async(pid()) -> ok.
stop_async(Pid) ->
xmpp_stream_out:stop_async(Pid).
-spec send(pid(), xmpp_element()) -> ok;
(state(), xmpp_element()) -> state().
@@ -150,7 +149,8 @@ process_closed(#{server := LServer, remote_server := RServer,
Reason) ->
?INFO_MSG("Closing outbound s2s connection ~ts -> ~ts: ~ts",
[LServer, RServer, format_error(Reason)]),
stop(State);
stop_async(self()),
State;
process_closed(#{server := LServer, remote_server := RServer} = State,
Reason) ->
Delay = get_delay(),
@@ -248,7 +248,9 @@ handle_send(El, Pkt, #{server_host := ServerHost} = State) ->
handle_timeout(#{on_route := Action, lang := Lang} = State) ->
case Action of
bounce -> stop(State);
bounce ->
stop_async(self()),
State;
_ ->
Txt = ?T("Idle connection"),
send(State, xmpp:serr_connection_timeout(Txt, Lang))
+6 -7
View File
@@ -33,7 +33,7 @@
-export([handle_stream_start/2, handle_auth_success/4, handle_auth_failure/4,
handle_authenticated_packet/2, get_password_fun/1, tls_options/1]).
%% API
-export([send/2, close/1, close/2, stop/1]).
-export([send/2, close/1, close/2, stop_async/1]).
-include("xmpp.hrl").
-include("logger.hrl").
@@ -59,7 +59,7 @@ stop() ->
lists:foreach(
fun({_Id, Pid, _Type, _Module}) ->
send(Pid, Err),
stop(Pid),
stop_async(Pid),
supervisor:terminate_child(ejabberd_service_sup, Pid)
end, supervisor:which_children(ejabberd_service_sup)),
_ = supervisor:terminate_child(ejabberd_sup, ejabberd_service_sup),
@@ -83,10 +83,9 @@ close(Ref) ->
close(Ref, Reason) ->
xmpp_stream_in:close(Ref, Reason).
-spec stop(pid()) -> ok;
(state()) -> no_return().
stop(Ref) ->
xmpp_stream_in:stop(Ref).
-spec stop_async(pid()) -> ok.
stop_async(Pid) ->
xmpp_stream_in:stop_async(Pid).
%%%===================================================================
%%% xmpp_stream_in callbacks
@@ -303,7 +302,7 @@ listen_options() ->
{tls, false},
{tls_compression, false},
{max_stanza_size, infinity},
{max_fsm_queue, 5000},
{max_fsm_queue, 10000},
{password, undefined},
{hosts, []},
{check_from, true},
+1 -1
View File
@@ -538,7 +538,7 @@ host_down(Host) ->
lists:foreach(
fun(#session{sid = {_, Pid}}) when node(Pid) == node() ->
ejabberd_c2s:send(Pid, Err),
ejabberd_c2s:stop(Pid);
ejabberd_c2s:stop_async(Pid);
(_) ->
ok
end, get_sessions(Mod, Host)),
+29 -55
View File
@@ -51,10 +51,8 @@
sqlite_file/1,
encode_term/1,
decode_term/1,
odbc_config/0,
freetds_config/0,
odbcinst_config/0,
init_mssql/1,
init_mssql/0,
keep_alive/2,
to_list/2,
to_array/2]).
@@ -253,7 +251,7 @@ to_list(EscapeFun, Val) ->
to_array(EscapeFun, Val) ->
Escaped = lists:join(<<",">>, lists:map(EscapeFun, Val)),
[<<"{">>, Escaped, <<"}">>].
lists:flatten([<<"{">>, Escaped, <<"}">>]).
to_string_literal(odbc, S) ->
<<"'", (escape(S))/binary, "'">>;
@@ -736,11 +734,11 @@ pgsql_sql_query_format(SQLQuery) ->
pgsql_escape() ->
#sql_escape{string = fun(X) -> <<"E'", (escape(X))/binary, "'">> end,
integer = fun(X) -> misc:i2l(X) end,
boolean = fun(true) -> <<"1">>;
(false) -> <<"0">>
boolean = fun(true) -> <<"'t'">>;
(false) -> <<"'f'">>
end,
in_array_string = fun(X) -> <<"E'", (escape(X))/binary, "'">> end,
like_escape = fun() -> <<"">> end
like_escape = fun() -> <<"ESCAPE E'\\\\'">> end
}.
sqlite_sql_query(SQLQuery) ->
@@ -776,11 +774,13 @@ pgsql_prepare(SQLQuery, State) ->
like_escape = fun() -> escape end},
{RArgs, _} =
lists:foldl(
fun(arg, {Acc, I}) ->
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1};
(escape, {Acc, I}) ->
{[<<"">> | Acc], I}
end, {[], 1}, (SQLQuery#sql_query.args)(Escape)),
fun(arg, {Acc, I}) ->
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1};
(escape, {Acc, I}) ->
{[<<"ESCAPE E'\\\\'">> | Acc], I};
(List, {Acc, I}) when is_list(List) ->
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1}
end, {[], 1}, (SQLQuery#sql_query.args)(Escape)),
Args = lists:reverse(RArgs),
%N = length((SQLQuery#sql_query.args)(Escape)),
%Args = [<<$$, (integer_to_binary(I))/binary>> || I <- lists:seq(1, N)],
@@ -1001,12 +1001,18 @@ pgsql_execute_to_odbc(_) -> {updated, undefined}.
%% part of init/1
%% Open a database connection to MySQL
mysql_connect(Server, Port, DB, Username, Password, ConnectTimeout, _, _) ->
mysql_connect(Server, Port, DB, Username, Password, ConnectTimeout, Transport, _) ->
SSLOpts = case Transport of
ssl ->
[ssl_required];
_ ->
[]
end,
case p1_mysql_conn:start(binary_to_list(Server), Port,
binary_to_list(Username),
binary_to_list(Password),
binary_to_list(DB),
ConnectTimeout, fun log/3)
ConnectTimeout, fun log/3, SSLOpts)
of
{ok, Ref} ->
p1_mysql_conn:fetch(
@@ -1101,8 +1107,9 @@ db_opts(Host) ->
SSLOpts = get_ssl_opts(Transport, Host),
case Type of
mssql ->
[mssql, <<"DSN=", Host/binary, ";UID=", User/binary,
";PWD=", Pass/binary>>, Timeout];
[mssql, <<"DRIVER=FreeTDS;SERVER=", Server/binary, ";UID=", User/binary,
";DATABASE=", DB/binary ,";PWD=", Pass/binary,
";PORT=", (integer_to_binary(Port))/binary ,";CLIENT_CHARSET=UTF-8;">>, Timeout];
_ ->
[Type, Server, Port, DB, User, Pass, Timeout, Transport, SSLOpts]
end
@@ -1112,6 +1119,8 @@ warn_if_ssl_unsupported(tcp, _) ->
ok;
warn_if_ssl_unsupported(ssl, pgsql) ->
ok;
warn_if_ssl_unsupported(ssl, mysql) ->
ok;
warn_if_ssl_unsupported(ssl, Type) ->
?WARNING_MSG("SSL connection is not supported for ~ts", [Type]).
@@ -1142,44 +1151,15 @@ get_ssl_opts(ssl, Host) ->
get_ssl_opts(tcp, _) ->
[].
init_mssql(Host) ->
Server = ejabberd_option:sql_server(Host),
Port = ejabberd_option:sql_port(Host),
DB = case ejabberd_option:sql_database(Host) of
undefined -> <<"ejabberd">>;
D -> D
end,
FreeTDS = io_lib:fwrite("[~ts]~n"
"\thost = ~ts~n"
"\tport = ~p~n"
"\tclient charset = UTF-8~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("[~ts]~n"
"Description = MS SQL~n"
"Driver = freetds~n"
"Servername = ~ts~n"
"Database = ~ts~n"
"Port = ~p~n",
[Host, Host, DB, Port]),
?DEBUG("~ts:~n~ts", [freetds_config(), FreeTDS]),
init_mssql() ->
ODBCINST = io_lib:fwrite("[FreeTDS]~n"
"Driver = libtdsodbc.so~n", []),
?DEBUG("~ts:~n~ts", [odbcinst_config(), ODBCINST]),
?DEBUG("~ts:~n~ts", [odbc_config(), ODBCINI]),
case filelib:ensure_dir(freetds_config()) of
case filelib:ensure_dir(odbcinst_config()) of
ok ->
try
ok = write_file_if_new(freetds_config(), FreeTDS),
ok = write_file_if_new(odbcinst_config(), ODBCINST),
ok = write_file_if_new(odbc_config(), ODBCINI),
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 ~ts: ~ts",
@@ -1204,12 +1184,6 @@ tmp_dir() ->
_ -> filename:join(["/tmp", "ejabberd"])
end.
odbc_config() ->
filename:join(tmp_dir(), "odbc.ini").
freetds_config() ->
filename:join(tmp_dir(), "freetds.conf").
odbcinst_config() ->
filename:join(tmp_dir(), "odbcinst.ini").
+5 -1
View File
@@ -648,7 +648,11 @@ make_sql_upsert_insert(Table, ParseRes) ->
]),
State.
make_sql_upsert_pgsql901(Table, ParseRes) ->
make_sql_upsert_pgsql901(Table, ParseRes0) ->
ParseRes = lists:map(
fun({"family", A2, A3}) -> {"\"family\"", A2, A3};
(Other) -> Other
end, ParseRes0),
Update = make_sql_upsert_update(Table, ParseRes),
Vals =
lists:map(
+1 -3
View File
@@ -84,8 +84,6 @@ stop() ->
ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 20).
init([]) ->
file:delete(ejabberd_sql:freetds_config()),
file:delete(ejabberd_sql:odbc_config()),
file:delete(ejabberd_sql:odbcinst_config()),
ejabberd_hooks:add(host_up, ?MODULE, start, 20),
ejabberd_hooks:add(host_down, ?MODULE, stop, 90),
@@ -98,7 +96,7 @@ init([Host]) ->
sqlite ->
check_sqlite_db(Host);
mssql ->
ejabberd_sql:init_mssql(Host);
ejabberd_sql:init_mssql();
_ ->
ok
end,
+87 -22
View File
@@ -46,19 +46,26 @@ start_link(_, _, _) ->
fail().
-else.
-export([tcp_init/2, udp_init/2, udp_recv/5, start/3,
start_link/3, accept/1, listen_opt_type/1, listen_options/0]).
start_link/3, accept/1, listen_opt_type/1, listen_options/0,
get_password/2]).
-include("logger.hrl").
-ifndef(LAGER).
-export([stun_filter/2]).
-define(STUN_MAX_LOG_LEVEL, notice). % Drop STUN/TURN info/debug messages.
-endif.
%%%===================================================================
%%% API
%%%===================================================================
tcp_init(Socket, Opts) ->
init_logger(),
ejabberd:start_app(stun),
stun:tcp_init(Socket, prepare_turn_opts(Opts)).
-dialyzer({nowarn_function, udp_init/2}).
udp_init(Socket, Opts) ->
init_logger(),
ejabberd:start_app(stun),
stun:udp_init(Socket, prepare_turn_opts(Opts)).
@@ -74,6 +81,21 @@ start_link(_SockMod, Socket, Opts) ->
accept(_Pid) ->
ok.
get_password(User, Realm) ->
case ejabberd_hooks:run_fold(stun_get_password, <<>>, [User, Realm]) of
Password when byte_size(Password) > 0 ->
Password;
<<>> ->
case ejabberd_auth:get_password_s(User, Realm) of
Password when is_binary(Password) ->
Password;
_ ->
?INFO_MSG("Cannot use hashed password of ~s@~s for "
"STUN/TURN authentication", [User, Realm]),
<<>>
end
end.
%%%===================================================================
%%% Internal functions
%%%===================================================================
@@ -85,27 +107,36 @@ prepare_turn_opts(Opts, _UseTurn = false) ->
set_certfile(Opts);
prepare_turn_opts(Opts, _UseTurn = true) ->
NumberOfMyHosts = length(ejabberd_option:hosts()),
case proplists:get_value(turn_ip, Opts) of
undefined ->
?WARNING_MSG("Option 'turn_ip' is undefined, "
"most likely the TURN relay won't be working "
"properly", []);
_ ->
ok
end,
AuthFun = fun ejabberd_auth:get_password_s/2,
TurnIP = case proplists:get_value(turn_ipv4_address, Opts) of
undefined ->
MyIP = misc:get_my_ipv4_address(),
case MyIP of
{127, _, _, _} ->
?WARNING_MSG("Option 'turn_ipv4_address' is "
"undefined and the server's hostname "
"doesn't resolve to a public IPv4 "
"address, most likely the TURN relay "
"won't be working properly", []);
_ ->
ok
end,
[{turn_ipv4_address, MyIP}];
_ ->
[]
end,
AuthFun = fun ejabberd_stun:get_password/2,
Shaper = proplists:get_value(shaper, Opts, none),
AuthType = proplists:get_value(auth_type, Opts, user),
Realm = case proplists:get_value(auth_realm, Opts) 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', "
"most likely the TURN relay won't "
"be working properly. Using ~ts as "
"a fallback", [ejabberd_config:get_myname()]);
?INFO_MSG("You have several virtual hosts "
"configured, but option 'auth_realm' is "
"undefined and 'auth_type' is set to "
"'user', so the TURN relay might not be "
"working properly. Using ~ts as a "
"fallback",
[ejabberd_config:get_myname()]);
true ->
ok
end,
@@ -114,8 +145,8 @@ prepare_turn_opts(Opts, _UseTurn = true) ->
[]
end,
MaxRate = ejabberd_shaper:get_max_rate(Shaper),
Opts1 = Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} |
lists:keydelete(shaper, 1, Opts)],
Opts1 = TurnIP ++ Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} |
lists:keydelete(shaper, 1, Opts)],
set_certfile(Opts1).
set_certfile(Opts) ->
@@ -135,9 +166,11 @@ set_certfile(Opts) ->
listen_opt_type(use_turn) ->
econf:bool();
listen_opt_type(ip) ->
econf:ip();
listen_opt_type(turn_ipv4_address) ->
econf:ipv4();
listen_opt_type(turn_ip) ->
econf:ipv4();
listen_opt_type(turn_ipv6_address) ->
econf:ipv6();
listen_opt_type(auth_type) ->
econf:enum([anonymous, user]);
listen_opt_type(auth_realm) ->
@@ -150,6 +183,8 @@ listen_opt_type(turn_max_allocations) ->
econf:pos_int(infinity);
listen_opt_type(turn_max_permissions) ->
econf:pos_int(infinity);
listen_opt_type(turn_blacklist) ->
econf:list_or_single(econf:ip_mask());
listen_opt_type(server_name) ->
econf:binary();
listen_opt_type(certfile) ->
@@ -158,7 +193,8 @@ listen_opt_type(certfile) ->
listen_options() ->
[{shaper, none},
{use_turn, false},
{turn_ip, undefined},
{turn_ipv4_address, undefined},
{turn_ipv6_address, undefined},
{auth_type, user},
{auth_realm, undefined},
{tls, false},
@@ -167,5 +203,34 @@ listen_options() ->
{turn_max_port, 65535},
{turn_max_allocations, 10},
{turn_max_permissions, 10},
{turn_blacklist, [<<"2001::/32">>, <<"2002::/16">>]}, % Teredo, 6to4.
{server_name, <<"ejabberd">>}].
-spec init_logger() -> ok.
-ifdef(LAGER).
init_logger() ->
ok.
-else.
init_logger() ->
case logger:add_primary_filter(stun, {fun ?MODULE:stun_filter/2,
?STUN_MAX_LOG_LEVEL}) of
ok ->
ok;
{error, {already_exist, _}} ->
ok
end.
-spec stun_filter(logger:log_event(), logger:level() | term())
-> logger:filter_return().
stun_filter(#{meta := #{domain := [stun | _]}, level := Level}, MaxLevel) ->
case logger:compare_levels(Level, MaxLevel) of
lt ->
stop;
_ ->
ignore
end;
stun_filter(Event, _Extra) ->
Event.
-endif.
-endif.
+23 -8
View File
@@ -150,7 +150,21 @@ url_to_path(URL) -> str:tokens(URL, <<"/">>).
%%%==================================
%%%% process/2
process([<<"server">>, SHost | RPath] = Path,
process(Path, #request{raw_path = RawPath} = Request) ->
Continue = case Path of
[E] ->
binary:match(E, <<".">>) /= nomatch;
_ ->
false
end,
case Continue orelse binary:at(RawPath, size(RawPath) - 1) == $/ of
true ->
process2(Path, Request);
_ ->
{301, [{<<"Location">>, <<RawPath/binary, "/">>}], <<>>}
end.
process2([<<"server">>, SHost | RPath] = Path,
#request{auth = Auth, lang = Lang, host = HostHTTP,
method = Method} =
Request) ->
@@ -185,7 +199,7 @@ process([<<"server">>, SHost | RPath] = Path,
end;
false -> ejabberd_web:error(not_found)
end;
process(RPath,
process2(RPath,
#request{auth = Auth, lang = Lang, host = HostHTTP,
method = Method} =
Request) ->
@@ -269,7 +283,7 @@ get_auth_account2(HostOfRule, AccessRule, User, Server,
make_xhtml(Els, Host, Lang, JID, Level) ->
make_xhtml(Els, Host, cluster, Lang, JID, Level).
%% @spec (Els, Host, Node, Lang, JID) -> {200, [html], xmlelement()}
%% @spec (Els, Host, Node, Lang, JID, Level::integer()) -> {200, [html], xmlelement()}
%% where Host = global | string()
%% Node = cluster | atom()
%% JID = jid()
@@ -326,6 +340,7 @@ make_xhtml(Els, Host, Node, Lang, JID, Level) ->
[?XAE(<<"div">>, [{<<"id">>, <<"copyright">>}],
[?XE(<<"p">>,
[?AC(<<"https://www.ejabberd.im/">>, <<"ejabberd">>),
?C(<<" ">>), ?C(ejabberd_option:version()),
?C(<<" (c) 2002-2020 ">>),
?AC(<<"https://www.process-one.net/">>, <<"ProcessOne, leader in messaging and push solutions">>)]
)])])])]}}.
@@ -430,7 +445,7 @@ process_admin(_Host, #request{path = [<<"additions.js">>]}, _) ->
process_admin(global, #request{path = [<<"vhosts">>], lang = Lang}, AJID) ->
Res = list_vhosts(Lang, AJID),
make_xhtml((?H1GL((translate:translate(Lang, ?T("Virtual Hosts"))),
<<"virtual-hosting">>, ?T("Virtual Hosting")))
<<"basic/#xmpp-domains">>, ?T("XMPP Domains")))
++ Res,
global, Lang, AJID, 1);
process_admin(Host, #request{path = [<<"users">>], q = Query,
@@ -465,7 +480,7 @@ process_admin(Host, #request{path = [<<"last-activity">>],
list_last_activity(Host, Lang, false, Month);
_ -> list_last_activity(Host, Lang, true, Month)
end,
PageH1 = ?H1GL(translate:translate(Lang, ?T("Users Last Activity")), <<"mod-last">>, <<"mod_last">>),
PageH1 = ?H1GL(translate:translate(Lang, ?T("Users Last Activity")), <<"modules/#mod-last">>, <<"mod_last">>),
make_xhtml(PageH1 ++
[?XAE(<<"form">>,
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}],
@@ -496,7 +511,7 @@ process_admin(Host, #request{path = [<<"last-activity">>],
Host, Lang, AJID, 3);
process_admin(Host, #request{path = [<<"stats">>], lang = Lang}, AJID) ->
Res = get_stats(Host, Lang),
PageH1 = ?H1GL(translate:translate(Lang, ?T("Statistics")), <<"mod-stats">>, <<"mod_stats">>),
PageH1 = ?H1GL(translate:translate(Lang, ?T("Statistics")), <<"modules/#mod-stats">>, <<"mod_stats">>),
Level = case Host of
global -> 1;
_ -> 3
@@ -1728,12 +1743,12 @@ pretty_string_int(String) when is_binary(String) ->
%%%==================================
%%%% navigation menu
%% @spec (Host, Node, Lang, JID::jid()) -> [LI]
%% @spec (Host, Node, Lang, JID::jid(), Level::integer()) -> [LI]
make_navigation(Host, Node, Lang, JID, Level) ->
Menu = make_navigation_menu(Host, Node, Lang, JID, Level),
make_menu_items(Lang, Menu).
%% @spec (Host, Node, Lang, JID::jid()) -> Menu
%% @spec (Host, Node, Lang, JID::jid(), Level::integer()) -> Menu
%% where Host = global | string()
%% Node = cluster | string()
%% Lang = string()
+15 -14
View File
@@ -42,8 +42,7 @@
-include("xmpp.hrl").
-record(state,
{access_commands = [] :: list(),
auth = noauth :: noauth | map(),
{auth = noauth :: noauth | map(),
get_auth = true :: boolean(),
ip :: inet:ip_address()}).
@@ -66,10 +65,9 @@ accept(Pid) ->
%% HTTP interface
%% -----------------------------
process(_, #request{method = 'POST', data = Data, opts = Opts, ip = {IP, _}}) ->
AccessCommands = proplists:get_value(access_commands, Opts, []),
process(_, #request{method = 'POST', data = Data, ip = {IP, _}}) ->
GetAuth = true,
State = #state{access_commands = AccessCommands, get_auth = GetAuth, ip = IP},
State = #state{get_auth = GetAuth, ip = IP},
case fxml_stream:parse_element(Data) of
{error, _} ->
{400, [],
@@ -190,8 +188,7 @@ handler(State, {call, Command, []}) ->
handler(State,
{call, Command, [{struct, AttrL}]}) ->
{ArgsF, ArgsR, ResultF} = ejabberd_commands:get_command_format(Command, State#state.auth),
try_do_command(State#state.access_commands,
State#state.auth, Command, AttrL, ArgsF, ArgsR, ResultF);
try_do_command(State#state.auth, Command, AttrL, ArgsF, ArgsR, ResultF);
handler(_State, Payload) ->
build_fault_response(-112, "Unknown call: ~p",
[Payload]).
@@ -200,10 +197,8 @@ handler(_State, Payload) ->
%% Command
%% -----------------------------
try_do_command(AccessCommands, Auth, Command, AttrL,
ArgsF, ArgsR, ResultF) ->
try do_command(AccessCommands, Auth, Command, AttrL,
ArgsF, ArgsR, ResultF)
try_do_command(Auth, Command, AttrL, ArgsF, ArgsR, ResultF) ->
try do_command(Auth, Command, AttrL, ArgsF, ArgsR, ResultF)
of
{command_result, ResultFormatted} ->
{false, {response, [ResultFormatted]}}
@@ -238,11 +233,10 @@ build_fault_response(Code, ParseString, ParseArgs) ->
?WARNING_MSG(FaultString, []),
{false, {response, {fault, Code, list_to_binary(FaultString)}}}.
do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ArgsR,
do_command(Auth, Command, AttrL, ArgsF, ArgsR,
ResultF) ->
ArgsFormatted = format_args(rename_old_args(AttrL, ArgsR), ArgsF),
Auth2 = Auth#{extra_permissions => AccessCommands},
Result = ejabberd_commands:execute_command2(Command, ArgsFormatted, Auth2),
Result = ejabberd_commands:execute_command2(Command, ArgsFormatted, Auth),
ResultFormatted = format_result(Result, ResultF),
{command_result, ResultFormatted}.
@@ -401,4 +395,11 @@ make_status(error) -> 1;
make_status(_) -> 1.
listen_options() ->
?WARNING_MSG("It is deprecated defining ejabberd_xmlrpc as a listen module "
"in the ejabberd configuration. Support for that configuration"
" method may be removed in a future ejabberd release. You are "
"encouraged to define ejabberd_xmlrpc inside request_handlers "
"option of ejabberd_http listen module. See the ejabberd "
"documentation for details: https://docs.ejabberd.im/admin/"
"configuration/listen/#ejabberd-xmlrpc", []),
[].
+21 -3
View File
@@ -33,6 +33,24 @@
-include("logger.hrl").
-ifdef(USE_OLD_PG2).
pg_create(PoolName) -> pg2:create(PoolName).
pg_join(PoolName, Pid) -> pg2:join(PoolName, Pid).
pg_get_closest_pid(Name) -> pg2:get_closest_pid(Name).
-else.
pg_create(_) -> pg:start_link().
pg_join(PoolName, Pid) -> pg:join(PoolName, Pid).
pg_get_closest_pid(Group) ->
case pg:get_local_members(Group) of
[] ->
case pg:get_members(Group) of
[] -> {error, {no_process, Group}};
[Pid | _] -> Pid
end;
[Pid | _] -> Pid
end.
-endif.
%%====================================================================
%% API
%%====================================================================
@@ -48,14 +66,14 @@ modify_passwd(PoolName, DN, Passwd) ->
start_link(Name, Hosts, Backups, Port, Rootdn, Passwd,
Opts) ->
PoolName = make_id(Name),
pg2:create(PoolName),
pg_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);
{ok, Pid} -> pg_join(PoolName, Pid);
Err ->
?ERROR_MSG("Err = ~p", [Err]),
error
@@ -67,7 +85,7 @@ start_link(Name, Hosts, Backups, Port, Rootdn, Passwd,
%% Internal functions
%%====================================================================
do_request(Name, {F, Args}) ->
case pg2:get_closest_pid(make_id(Name)) of
case pg_get_closest_pid(make_id(Name)) of
Pid when is_pid(Pid) ->
case catch apply(eldap, F, [Pid | Args]) of
{'EXIT', {timeout, _}} ->
+1 -1
View File
@@ -570,7 +570,7 @@ compile_result(Results) ->
end.
compile_options() ->
[verbose, report_errors, report_warnings]
[verbose, report_errors, report_warnings, ?ALL_DEFS]
++ [{i, filename:join(app_dir(App), "include")}
|| App <- [fast_xml, xmpp, p1_utils, ejabberd]]
++ [{i, filename:join(mod_dir(Mod), "include")}
+2 -2
View File
@@ -86,7 +86,7 @@ start_link() ->
end.
init([]) ->
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 50),
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 60),
ejabberd_hooks:add(host_up, ?MODULE, start_modules, 40),
ejabberd_hooks:add(host_down, ?MODULE, stop_modules, 70),
ets:new(ejabberd_modules,
@@ -97,7 +97,7 @@ init([]) ->
-spec stop() -> ok.
stop() ->
ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 50),
ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 60),
ejabberd_hooks:delete(host_up, ?MODULE, start_modules, 40),
ejabberd_hooks:delete(host_down, ?MODULE, stop_modules, 70),
stop_modules(),
+49 -27
View File
@@ -37,11 +37,12 @@
now_to_usec/1, usec_to_now/1, encode_pid/1, decode_pid/2,
compile_exprs/2, join_atoms/2, try_read_file/1, get_descr/2,
css_dir/0, img_dir/0, js_dir/0, msgs_dir/0, sql_dir/0, lua_dir/0,
read_css/1, read_img/1, read_js/1, read_lua/1, try_url/1,
read_css/1, read_img/1, read_js/1, read_lua/1,
intersection/2, format_val/1, cancel_timer/1, unique_timestamp/0,
is_mucsub_message/1, best_match/2, pmap/2, peach/2, format_exception/4,
parse_ip_mask/1, match_ip_mask/3, format_hosts_list/1, format_cycle/1,
delete_dir/1]).
get_my_ipv4_address/0, get_my_ipv6_address/0, parse_ip_mask/1,
crypto_hmac/3, crypto_hmac/4, uri_parse/1,
match_ip_mask/3, format_hosts_list/1, format_cycle/1, delete_dir/1]).
%% Deprecated functions
-export([decode_base64/1, encode_base64/1]).
@@ -54,6 +55,34 @@
-type distance_cache() :: #{{string(), string()} => non_neg_integer()}.
-ifdef(USE_OLD_HTTP_URI).
uri_parse(URL) when is_binary(URL) ->
uri_parse(binary_to_list(URL));
uri_parse(URL) ->
{ok, {Scheme, _UserInfo, Host, Port, Path, _Query}} = http_uri:parse(URL),
{ok, Scheme, Host, Port, Path}.
-else.
uri_parse(URL) when is_binary(URL) ->
uri_parse(binary_to_list(URL));
uri_parse(URL) ->
case uri_string:parse(URL) of
#{scheme := Scheme, host := Host, port := Port, path := Path} ->
{ok, Scheme, Host, Port, Path};
#{scheme := "https", host := Host, path := Path} ->
{ok, "https", Host, 443, Path};
#{scheme := "http", host := Host, path := Path} ->
{ok, "http", Host, 80, Path}
end.
-endif.
-ifdef(USE_OLD_CRYPTO_HMAC).
crypto_hmac(Type, Key, Data) -> crypto:hmac(Type, Key, Data).
crypto_hmac(Type, Key, Data, MacL) -> crypto:hmac(Type, Key, Data, MacL).
-else.
crypto_hmac(Type, Key, Data) -> crypto:mac(hmac, Type, Key, Data).
crypto_hmac(Type, Key, Data, MacL) -> crypto:macN(hmac, Type, Key, Data, MacL).
-endif.
%%%===================================================================
%%% API
%%%===================================================================
@@ -306,7 +335,7 @@ join_atoms(Atoms, Sep) ->
str:join([io_lib:format("~p", [A]) || A <- lists:sort(Atoms)], Sep).
%% @doc Checks if the file is readable and converts its name to binary.
%% Fails with `badarg` otherwise. The function is intended for usage
%% Fails with `badarg' otherwise. The function is intended for usage
%% in configuration validators only.
-spec try_read_file(file:filename_all()) -> binary().
try_read_file(Path) ->
@@ -319,29 +348,6 @@ try_read_file(Path) ->
erlang:error(badarg)
end.
%% @doc Checks if the URL is valid HTTP(S) URL and converts its name to binary.
%% Fails with `badarg` otherwise. The function is intended for usage
%% in configuration validators only.
-spec try_url(binary() | string()) -> binary().
try_url(URL0) ->
URL = case URL0 of
V when is_binary(V) -> binary_to_list(V);
_ -> URL0
end,
case http_uri:parse(URL) of
{ok, {Scheme, _, _, _, _, _}} when Scheme /= http, Scheme /= https ->
?ERROR_MSG("Unsupported URI scheme: ~ts", [URL]),
erlang:error(badarg);
{ok, {_, _, Host, _, _, _}} when Host == ""; Host == <<"">> ->
?ERROR_MSG("Invalid URL: ~ts", [URL]),
erlang:error(badarg);
{ok, _} ->
iolist_to_binary(URL);
{error, _} ->
?ERROR_MSG("Invalid URL: ~ts", [URL]),
erlang:error(badarg)
end.
-spec css_dir() -> file:filename().
css_dir() ->
get_dir("css").
@@ -509,6 +515,22 @@ format_exception(Level, Class, Reason, Stacktrace) ->
end).
-endif.
-spec get_my_ipv4_address() -> inet:ip4_address().
get_my_ipv4_address() ->
{ok, MyHostName} = inet:gethostname(),
case inet:getaddr(MyHostName, inet) of
{ok, Addr} -> Addr;
{error, _} -> {127, 0, 0, 1}
end.
-spec get_my_ipv6_address() -> inet:ip6_address().
get_my_ipv6_address() ->
{ok, MyHostName} = inet:gethostname(),
case inet:getaddr(MyHostName, inet6) of
{ok, Addr} -> Addr;
{error, _} -> {0, 0, 0, 0, 0, 0, 0, 1}
end.
-spec parse_ip_mask(binary()) -> {ok, {inet:ip4_address(), 0..32}} |
{ok, {inet:ip6_address(), 0..128}} |
error.
+1 -1
View File
@@ -288,5 +288,5 @@ mod_doc() ->
[{report_commands_node,
#{value => "true | false",
desc =>
?T("Provide the Commands item in the Service Disvocery. "
?T("Provide the Commands item in the Service Discovery. "
"Default value: 'false'.")}}]}.
+57 -55
View File
@@ -113,26 +113,26 @@ depends(_Host, _Opts) ->
%%%
get_commands_spec() ->
Vcard1FieldsString = "Some vcard field names in get/set_vcard are:\n"
" FN - Full Name\n"
" NICKNAME - Nickname\n"
" BDAY - Birthday\n"
" TITLE - Work: Position\n"
" ROLE - Work: Role",
Vcard1FieldsString = "Some vcard field names in get/set_vcard are:\n\n"
"* FN - Full Name\n"
"* NICKNAME - Nickname\n"
"* BDAY - Birthday\n"
"* TITLE - Work: Position\n"
"* ROLE - Work: Role\n",
Vcard2FieldsString = "Some vcard field names and subnames in get/set_vcard2 are:\n"
" N FAMILY - Family name\n"
" N GIVEN - Given name\n"
" N MIDDLE - Middle name\n"
" ADR CTRY - Address: Country\n"
" ADR LOCALITY - Address: City\n"
" TEL HOME - Telephone: Home\n"
" TEL CELL - Telephone: Cellphone\n"
" TEL WORK - Telephone: Work\n"
" TEL VOICE - Telephone: Voice\n"
" EMAIL USERID - E-Mail Address\n"
" ORG ORGNAME - Work: Company\n"
" ORG ORGUNIT - Work: Department",
Vcard2FieldsString = "Some vcard field names and subnames in get/set_vcard2 are:\n\n"
"* N FAMILY - Family name\n"
"* N GIVEN - Given name\n"
"* N MIDDLE - Middle name\n"
"* ADR CTRY - Address: Country\n"
"* ADR LOCALITY - Address: City\n"
"* TEL HOME - Telephone: Home\n"
"* TEL CELL - Telephone: Cellphone\n"
"* TEL WORK - Telephone: Work\n"
"* TEL VOICE - Telephone: Voice\n"
"* EMAIL USERID - E-Mail Address\n"
"* ORG ORGNAME - Work: Company\n"
"* ORG ORGUNIT - Work: Department\n",
VcardXEP = "For a full list of vCard fields check XEP-0054: vcard-temp at "
"http://www.xmpp.org/extensions/xep-0054.html",
@@ -435,7 +435,7 @@ get_commands_spec() ->
result = {res, rescode}},
#ejabberd_commands{name = get_vcard, tags = [vcard],
desc = "Get content from a vCard field",
longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
longdesc = Vcard1FieldsString ++ "\n" ++ VcardXEP,
module = ?MODULE, function = get_vcard,
args = [{user, binary}, {host, binary}, {name, binary}],
args_example = [<<"user1">>,<<"myserver.com">>,<<"NICKNAME">>],
@@ -445,7 +445,7 @@ get_commands_spec() ->
result = {content, string}},
#ejabberd_commands{name = get_vcard2, tags = [vcard],
desc = "Get content from a vCard subfield",
longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
longdesc = Vcard2FieldsString ++ "\n" ++ VcardXEP,
module = ?MODULE, function = get_vcard,
args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}],
args_example = [<<"user1">>,<<"myserver.com">>,<<"N">>, <<"FAMILY">>],
@@ -455,14 +455,14 @@ get_commands_spec() ->
result = {content, string}},
#ejabberd_commands{name = get_vcard2_multi, tags = [vcard],
desc = "Get multiple contents from a vCard field",
longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
longdesc = Vcard2FieldsString ++ "\n" ++ VcardXEP,
module = ?MODULE, function = get_vcard_multi,
args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}],
result = {contents, {list, {value, string}}}},
#ejabberd_commands{name = set_vcard, tags = [vcard],
desc = "Set content in a vCard field",
longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
longdesc = Vcard1FieldsString ++ "\n" ++ VcardXEP,
module = ?MODULE, function = set_vcard,
args = [{user, binary}, {host, binary}, {name, binary}, {content, binary}],
args_example = [<<"user1">>,<<"myserver.com">>, <<"URL">>, <<"www.example.com">>],
@@ -470,7 +470,7 @@ get_commands_spec() ->
result = {res, rescode}},
#ejabberd_commands{name = set_vcard2, tags = [vcard],
desc = "Set content in a vCard subfield",
longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
longdesc = Vcard2FieldsString ++ "\n" ++ VcardXEP,
module = ?MODULE, function = set_vcard,
args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {content, binary}],
args_example = [<<"user1">>,<<"myserver.com">>,<<"TEL">>, <<"NUMBER">>, <<"123456">>],
@@ -478,7 +478,7 @@ get_commands_spec() ->
result = {res, rescode}},
#ejabberd_commands{name = set_vcard2_multi, tags = [vcard],
desc = "Set multiple contents in a vCard subfield",
longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
longdesc = Vcard2FieldsString ++ "\n" ++ VcardXEP,
module = ?MODULE, function = set_vcard,
args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {contents, {list, {value, binary}}}],
result = {res, rescode}},
@@ -1513,6 +1513,9 @@ send_stanza(FromString, ToString, Stanza) ->
catch _:{xmpp_codec, Why} ->
io:format("incorrect stanza: ~ts~n", [xmpp:format_error(Why)]),
{error, Why};
_:{badmatch, {error, {Code, Why}}} when is_integer(Code) ->
io:format("invalid xml: ~p~n", [Why]),
{error, Why};
_:{badmatch, {error, Why}} ->
io:format("invalid xml: ~p~n", [Why]),
{error, Why};
@@ -1596,41 +1599,33 @@ mod_doc() ->
[?T("This module provides additional administrative commands."), "",
?T("Details for some commands:"), "",
?T("- 'ban-acount':"),
?T("This command kicks all the connected sessions of the
account from the server. It also changes their password to
a randomly generated one, so they can't login anymore
unless a server administrator changes their password
again. It is possible to define the reason of the ban. The
new password also includes the reason and the date and time
of the ban. For example, if this command is called:
'ejabberdctl vhost example.org ban-account boby \"Spammed
rooms\"', then the sessions of the local account which JID
is boby@example.org will be kicked, and its password will
be set to something like this:
'BANNED_ACCOUNT--20080425T21:45:07--2176635--Spammed_rooms'"),
?T("- 'pushroster' (and 'pushroster-all'):"),
?T("The roster file must be placed, if using Windows, on
the directory where you installed ejabberd: C:/Program
Files/ejabberd or similar. If you use other Operating
System, place the file on the same directory where the
.beam files are installed. See below an example roster
file."),
?T("This command kicks all the connected sessions of the account "
"from the server. It also changes their password to a randomly "
"generated one, so they can't login anymore unless a server "
"administrator changes their password again. It is possible to "
"define the reason of the ban. The new password also includes "
"the reason and the date and time of the ban. See an example below."),
?T("- 'pushroster': (and 'pushroster-all')"),
?T("The roster file must be placed, if using Windows, on the "
"directory where you installed ejabberd: "
"C:/Program Files/ejabberd or similar. If you use other "
"Operating System, place the file on the same directory where "
"the .beam files are installed. See below an example roster file."),
?T("- 'srg-create':"),
?T("If you want to put a group Name with blankspaces, use
the characters \"\' and \\'\" to define when the Name
starts and ends. For example: 'ejabberdctl srg-create g1
example.org \"\'Group number 1\\'\" this_is_g1 g1'")],
?T("If you want to put a group Name with blankspaces, use the "
"characters \"\' and \'\" to define when the Name starts and "
"ends. See an example below.")],
opts =>
[{module_resource,
#{value => ?T("Resource"),
desc =>
?T("Indicate the resource that the XMPP stanzas must
use in the FROM or TO JIDs. This is only useful in
the 'get_vcard*' and 'set_vcard*' commands. The
default value is 'mod_admin_extra'.")}}],
?T("Indicate the resource that the XMPP stanzas must use "
"in the FROM or TO JIDs. This is only useful in the "
"'get_vcard*' and 'set_vcard*' commands. The default "
"value is 'mod_admin_extra'.")}}],
example =>
[{?T("With this configuration, vCards can only be modified
with mod_admin_extra commands:"),
[{?T("With this configuration, vCards can only be modified with "
"mod_admin_extra commands:"),
["acl:",
" adminextraresource:",
" - resource: \"modadminextraf8x,31ad\"",
@@ -1645,4 +1640,11 @@ mod_doc() ->
{?T("Content of roster file for 'pushroster' command:"),
["[{<<\"bob\">>, <<\"example.org\">>, <<\"workers\">>, <<\"Bob\">>},",
"{<<\"mart\">>, <<\"example.org\">>, <<\"workers\">>, <<\"Mart\">>},",
"{<<\"Rich\">>, <<\"example.org\">>, <<\"bosses\">>, <<\"Rich\">>}]."]}]}.
"{<<\"Rich\">>, <<\"example.org\">>, <<\"bosses\">>, <<\"Rich\">>}]."]},
{?T("With this call, the sessions of the local account which JID is "
"boby@example.org will be kicked, and its password will be set "
"to something like "
"'BANNED_ACCOUNT--20080425T21:45:07--2176635--Spammed_rooms'"),
["ejabberdctl vhost example.org ban-account boby \"Spammed rooms\""]},
{?T("Call to srg-create using double-quotes and single-quotes:"),
["ejabberdctl srg-create g1 example.org \"\'Group number 1\'\" this_is_g1 g1"]}]}.
+9 -5
View File
@@ -925,31 +925,35 @@ mod_doc() ->
"Configured users can perform these actions with an XMPP "
"client either using Ad-hoc Commands or sending messages "
"to specific JIDs."), "",
?T("Note that this module can be resource intensive on large "
"deployments as it may broadcast a lot of messages. This module "
"should be disabled for instances of ejabberd with hundreds of "
"thousands users."), "",
?T("The Ad-hoc Commands are listed in the Server Discovery. "
"For this feature to work, 'mod_adhoc' must be enabled."), "",
?T("The specific JIDs where messages can be sent are listed below. "
"The first JID in each entry will apply only to the specified "
"virtual host example.org, while the JID between brackets "
"will apply to all virtual hosts in ejabberd:"), "",
"example.org/announce/all (example.org/announce/all-hosts/all)::",
"- example.org/announce/all (example.org/announce/all-hosts/all)::",
?T("The message is sent to all registered users. If the user is "
"online and connected to several resources, only the resource "
"with the highest priority will receive the message. "
"If the registered user is not connected, the message will be "
"stored offline in assumption that offline storage (see 'mod_offline') "
"is enabled."),
"example.org/announce/online (example.org/announce/all-hosts/online)::",
"- example.org/announce/online (example.org/announce/all-hosts/online)::",
?T("The message is sent to all connected users. If the user is "
"online and connected to several resources, all resources will "
"receive the message."),
"example.org/announce/motd (example.org/announce/all-hosts/motd)::",
"- example.org/announce/motd (example.org/announce/all-hosts/motd)::",
?T("The message is set as the message of the day (MOTD) and is sent "
"to users when they login. In addition the message is sent to all "
"connected users (similar to announce/online)."),
"example.org/announce/motd/update (example.org/announce/all-hosts/motd/update)::",
"- example.org/announce/motd/update (example.org/announce/all-hosts/motd/update)::",
?T("The message is set as message of the day (MOTD) and is sent to users "
"when they login. The message is not sent to any currently connected user."),
"example.org/announce/motd/delete (example.org/announce/all-hosts/motd/delete)::",
"- example.org/announce/motd/delete (example.org/announce/all-hosts/motd/delete)::",
?T("Any message sent to this JID removes the existing message of the day (MOTD).")],
opts =>
[{access,
+2 -5
View File
@@ -1,5 +1,5 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% Created : 13 Sep 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
@@ -481,12 +481,9 @@ mod_doc() ->
"the list of supported formats is detected at compile time "
"depending on the image libraries installed in the system."),
example =>
[{?T("In this example avatars in WebP format are "
"converted to JPEG, all other formats are "
"converted to PNG:"),
["convert:",
" webp: jpg",
" default: png"]}]}},
" default: png"]}},
{rate_limit,
#{value => ?T("Number"),
desc =>
+33 -1
View File
@@ -213,11 +213,30 @@ mod_doc() ->
[{json,
#{value => "true | false",
desc => ?T("This option has no effect.")}},
{max_concat,
#{value => "pos_integer() | infinity",
desc =>
?T("This option limits the number of stanzas that the server "
"will send in a single bosh request. "
"The default value is 'unlimited'.")}},
{max_inactivity,
#{value => "timeout()",
desc =>
?T("The option defines the maximum inactivity period. "
"The default value is '30' seconds.")}},
{max_pause,
#{value => "pos_integer()",
desc =>
?T("Indicate the maximum length of a temporary session pause "
"(in seconds) that a client can request. "
"The default value is '120'.")}},
{prebind,
#{value => "true | false",
desc =>
?T("If enabled, the client can create the session without "
"going through authentication. Basically, it creates a "
"new session with anonymous authentication. "
"The default value is 'false'.")}},
{queue_type,
#{value => "ram | file",
desc =>
@@ -241,7 +260,20 @@ mod_doc() ->
{cache_life_time,
#{value => "timeout()",
desc =>
?T("Same as top-level 'cache_life_time' option, but applied to this module only.")}}]}.
?T("Same as top-level 'cache_life_time' option, but applied to this module only.")}}],
example =>
["listen:",
" -",
" port: 5222",
" module: ejabberd_c2s",
" -",
" port: 5443",
" module: ejabberd_http",
" request_handlers:",
" /bosh: mod_bosh",
"",
"modules:",
" mod_bosh: {}"]}.
%%%----------------------------------------------------------------------
%%% Cache stuff
+13 -1
View File
@@ -143,7 +143,19 @@ user_send_packet(Acc) ->
-spec user_receive_packet({stanza(), ejabberd_c2s:state()}) -> {stanza(), ejabberd_c2s:state()}.
user_receive_packet({#presence{from = From, type = available} = Pkt,
#{lserver := LServer, jid := To} = State}) ->
IsRemote = not ejabberd_router:is_my_host(From#jid.lserver),
IsRemote = case From#jid.lresource of
% Don't store caps for presences sent by our muc rooms
<<>> ->
try ejabberd_router:host_of_route(From#jid.lserver) of
MaybeMuc ->
not lists:member(From#jid.lserver,
gen_mod:get_module_opt_hosts(MaybeMuc, mod_muc))
catch error:{unregistered_route, _} ->
true
end;
_ ->
not ejabberd_router:is_my_host(From#jid.lserver)
end,
if IsRemote ->
case read_caps(Pkt) of
nothing -> ok;
+2 -2
View File
@@ -27,7 +27,7 @@
-module (mod_carboncopy).
-author ('ecestari@process-one.net').
-protocol({xep, 280, '0.8'}).
-protocol({xep, 280, '0.13.2'}).
-behaviour(gen_mod).
@@ -268,7 +268,7 @@ is_received_muc_invite(Msg, received) ->
#muc_user{invites = [_|_]} ->
true;
_ ->
xmpp:has_subtag(Msg, #x_conference{})
xmpp:has_subtag(Msg, #x_conference{jid = jid:make(<<"">>)})
end.
-spec is_received_muc_pm(jid(), message(), direction()) -> boolean().
+12 -3
View File
@@ -85,13 +85,18 @@ mod_options(_Host) ->
mod_doc() ->
#{desc =>
?T("This module is an implementation of "
[?T("This module is an implementation of "
"https://xmpp.org/extensions/xep-0355.html"
"[XEP-0355: Namespace Delegation]. "
"Only admin mode has been implemented by now. "
"Namespace delegation allows external services to "
"handle IQ using specific namespace. This may be applied "
"for external PEP service."),
"for external PEP service."), "",
?T("WARNING: Security issue: Namespace delegation gives components "
"access to sensitive data, so permission should be granted "
"carefully, only if you trust the component."), "",
?T("NOTE: This module is complementary to 'mod_privilege' but can "
"also be used separately.")],
opts =>
[{namespaces,
#{value => "{Namespace: Options}",
@@ -109,6 +114,10 @@ mod_doc() ->
?T("The option defines which components are allowed "
"for namespace delegation. The default value is 'none'.")}}]}],
example =>
[{?T("Make sure you do not delegate the same namespace to several "
"services at the same time. As in the example provided later, "
"to have the 'sat-pubsub.example.org' component perform "
"correctly disable the 'mod_pubsub' module."),
["access_rules:",
" external_pubsub:",
" allow: external_component",
@@ -126,7 +135,7 @@ mod_doc() ->
" urn:xmpp:mam:1:",
" access: external_mam",
" http://jabber.org/protocol/pubsub:",
" access: external_pubsub"]}.
" access: external_pubsub"]}]}.
depends(_, _) ->
[].
+7 -1
View File
@@ -263,7 +263,13 @@ mod_doc() ->
"record of authentication failures after some time since the "
"first failure or on a successful authentication. "
"It also does not simply block network traffic, but "
"provides the client with a descriptive error message.")],
"provides the client with a descriptive error message."), "",
?T("WARNING: You should not use this module behind a proxy or load "
"balancer. ejabberd will see the failures as coming from the "
"load balancer and, when the threshold of auth failures is "
"reached, will reject all connections coming from the load "
"balancer. You can lock all your user base out of ejabberd "
"when using this module behind a proxy.")],
opts =>
[{access,
#{value => ?T("AccessName"),
+10 -2
View File
@@ -524,5 +524,13 @@ mod_options(_) ->
mod_doc() ->
#{desc =>
?T("This module provides a ReST API to call "
"ejabberd commands using JSON data.")}.
[?T("This module provides a ReST API to call ejabberd commands "
"using JSON data."), "",
?T("To use this module, in addition to adding it to the 'modules' "
"section, you must also add it to 'request_handlers' of some "
"listener."), "",
?T("To use a specific API version N, when defining the URL path "
"in the request_handlers, add a 'vN'. "
"For example: '/api/v2: mod_http_api'"), "",
?T("To run a command, send a POST request to the corresponding "
"URL: 'http://localhost:5280/api/<command_name>'")]}.
+3 -4
View File
@@ -522,12 +522,11 @@ mod_doc() ->
?T("Specify mappings of extension to content type. "
"There are several content types already defined. "
"With this option you can add new definitions "
"or modify existing ones."),
"or modify existing ones. The default values are:"),
example =>
[{?T("The default value is shown in the example below:"),
["content_types:"|
["content_types:"|
[" " ++ binary_to_list(E) ++ ": " ++ binary_to_list(T)
|| {E, T} <- ?DEFAULT_CONTENT_TYPES]]}]}},
|| {E, T} <- ?DEFAULT_CONTENT_TYPES]]}},
{default_content_type,
#{value => ?T("Type"),
desc =>
+3 -3
View File
@@ -711,8 +711,8 @@ get_proc_name(ServerHost, ModuleName) ->
-spec get_proc_name(binary(), atom(), binary()) -> atom().
get_proc_name(ServerHost, ModuleName, PutURL) ->
%% Once we depend on OTP >= 20.0, we can use binaries with http_uri.
{ok, {_Scheme, _UserInfo, Host0, _Port, Path0, _Query}} =
http_uri:parse(binary_to_list(expand_host(PutURL, ServerHost))),
{ok, _Scheme, Host0, _Port, Path0} =
misc:uri_parse(expand_host(PutURL, ServerHost)),
Host = jid:nameprep(iolist_to_binary(Host0)),
Path = str:strip(iolist_to_binary(Path0), right, $/),
ProcPrefix = <<Host/binary, Path/binary>>,
@@ -934,7 +934,7 @@ make_query_string(Slot, Size, #state{external_secret = Key}) when Key /= <<>> ->
UrlPath = str:join(Slot, <<$/>>),
SizeStr = integer_to_binary(Size),
Data = <<UrlPath/binary, " ", SizeStr/binary>>,
HMAC = str:to_hexlist(crypto:hmac(sha256, Key, Data)),
HMAC = str:to_hexlist(misc:crypto_hmac(sha256, Key, Data)),
<<"?v=", HMAC/binary>>;
make_query_string(_Slot, _Size, _State) ->
<<>>.
+5 -1
View File
@@ -130,6 +130,10 @@ mod_doc() ->
"the specified soft quota (see 'access_soft_quota'). "
"The default value is 'hard_upload_quota'.")}}],
example =>
[{?T("Please note that it's not necessary to specify the "
"'access_hard_quota' and 'access_soft_quota' options in order "
"to use the quota feature. You can stick to the default names "
"and just specify access rules such as those in this example:"),
["shaper_rules:",
" ...",
" soft_upload_quota:",
@@ -143,7 +147,7 @@ mod_doc() ->
" mod_http_upload: {}",
" mod_http_upload_quota:",
" max_days: 100",
" ..."]}.
" ..."]}]}.
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
depends(_Host, _Opts) ->
+4 -2
View File
@@ -55,10 +55,11 @@ get_last(LUser, LServer) ->
end.
store_last_info(LUser, LServer, TimeStamp, Status) ->
TS = integer_to_binary(TimeStamp),
case ?SQL_UPSERT(LServer, "last",
["!username=%(LUser)s",
"!server_host=%(LServer)s",
"seconds=%(TimeStamp)d",
"seconds=%(TS)s",
"state=%(Status)s"]) of
ok ->
ok;
@@ -76,11 +77,12 @@ export(_Server) ->
fun(Host, #last_activity{us = {LUser, LServer},
timestamp = TimeStamp, status = Status})
when LServer == Host ->
TS = integer_to_binary(TimeStamp),
[?SQL("delete from last where username=%(LUser)s and %(LServer)H;"),
?SQL_INSERT("last",
["username=%(LUser)s",
"server_host=%(LServer)s",
"seconds=%(TimeStamp)d",
"seconds=%(TS)s",
"state=%(Status)s"])];
(_Host, _R) ->
[]
+15 -2
View File
@@ -1435,7 +1435,12 @@ mod_doc() ->
"Compatible XMPP clients can use it to store their "
"chat history on the server."),
opts =>
[{assume_mam_usage,
[{access_preferences,
#{value => ?T("AccessName"),
desc =>
?T("This access rule defines who is allowed to modify the "
"MAM preferences. The default value is 'all'.")}},
{assume_mam_usage,
#{value => "true | false",
desc =>
?T("This option determines how ejabberd's "
@@ -1499,4 +1504,12 @@ mod_doc() ->
{cache_life_time,
#{value => "timeout()",
desc =>
?T("Same as top-level 'cache_life_time' option, but applied to this module only.")}}]}.
?T("Same as top-level 'cache_life_time' option, but applied to this module only.")}},
{user_mucsub_from_muc_archive,
#{value => "true | false",
desc =>
?T("When this option is disabled, for each individual "
"subscriber a separa mucsub message is stored. With this "
"option enabled, when a user fetches archive virtual "
"mucsub, messages are generated from muc archives. "
"The default value is 'false'.")}}]}.
+1 -1
View File
@@ -105,7 +105,7 @@ store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, TS) ->
jid:tolower(Peer)),
Body = fxml:get_subtag_cdata(Pkt, <<"body">>),
SType = misc:atom_to_binary(Type),
SqlType = ejabberd_option:sql_type(LHost),
SqlType = ejabberd_option:sql_type(LServer),
XML = case mod_mam_opt:compress_xml(LServer) of
true ->
J1 = case Type of
+5 -1
View File
@@ -107,6 +107,10 @@ mod_doc() ->
"yet ready to use in production. It's asserted that "
"the MIX protocol is going to replace the MUC protocol "
"in the future (see 'mod_muc')."), "",
?T("To learn more about how to use that feature, you can refer to "
"our tutorial: https://docs.ejabberd.im/tutorials/mix-010/"
"[Getting started with XEP-0369: Mediated Information "
"eXchange (MIX) v0.1]."), "",
?T("The module depends on 'mod_mam'.")],
opts =>
[{access_create,
@@ -638,7 +642,7 @@ notify_participant_left(Mod, LServer, To, ID) ->
-spec make_id(jid(), binary()) -> binary().
make_id(JID, Key) ->
Data = jid:encode(jid:tolower(jid:remove_resource(JID))),
xmpp_util:hex(crypto:hmac(sha256, Data, Key, 10)).
xmpp_util:hex(misc:crypto_hmac(sha256, Data, Key, 10)).
%%%===================================================================
%%% Error generators
+3 -2
View File
@@ -256,7 +256,7 @@ listen_opt_type(max_payload_size) ->
econf:pos_int(infinity).
listen_options() ->
[{max_fsm_queue, 5000},
[{max_fsm_queue, 10000},
{max_payload_size, infinity},
{tls, false},
{tls_verify, false}].
@@ -267,7 +267,8 @@ listen_options() ->
mod_doc() ->
#{desc =>
?T("This module adds support for the MQTT protocol "
"version '3.1.1' and '5.0'."),
"version '3.1.1' and '5.0'. Remember to configure "
"'mod_mqtt' in 'modules' and 'listen' sections."),
opts =>
[{access_subscribe,
#{value => "{TopicFilter: AccessName}",
+13 -2
View File
@@ -1280,9 +1280,20 @@ mod_options(Host) ->
mod_doc() ->
#{desc =>
?T("This module provides support for https://xmpp.org/extensions/xep-0045.html"
[?T("This module provides support for https://xmpp.org/extensions/xep-0045.html"
"[XEP-0045: Multi-User Chat]. Users can discover existing rooms, "
"join or create them. Occupants of a room can chat in public or have private chats."),
"join or create them. Occupants of a room can chat in public or have private chats."), "",
?T("The MUC service allows any Jabber ID to register a nickname, so "
"nobody else can use that nickname in any room in the MUC "
"service. To register a nickname, open the Service Discovery in "
"your XMPP client and register in the MUC service."), "",
?T("This module supports clustering and load balancing. One module "
"can be started per cluster node. Rooms are distributed at "
"creation time on all available MUC module instances. The "
"multi-user chat module is clustered but the rooms themselves "
"are not clustered nor fault-tolerant: if the node managing a "
"set of rooms goes down, the rooms disappear and they will be "
"recreated on an available node on first connection attempt.")],
opts =>
[{access,
#{value => ?T("AccessName"),
+25 -15
View File
@@ -459,7 +459,7 @@ web_page_main(_, #request{path=[<<"muc">>], lang = Lang} = _Request) ->
Acc + mod_muc:count_online_rooms(Host)
end, 0, find_hosts(global)),
PageTitle = translate:translate(Lang, ?T("Multi-User Chat")),
Res = ?H1GL(PageTitle, <<"mod-muc">>, <<"mod_muc">>) ++
Res = ?H1GL(PageTitle, <<"modules/#mod-muc">>, <<"mod_muc">>) ++
[?XCT(<<"h3">>, ?T("Statistics")),
?XAE(<<"table">>, [],
[?XE(<<"tbody">>, [?TDTD(?T("Total rooms"), OnlineRoomsNumber)
@@ -494,8 +494,8 @@ get_sort_query(Q) ->
end.
get_sort_query2(Q) ->
{value, {_, String}} = lists:keysearch(<<"sort">>, 1, Q),
Integer = binary_to_integer(String),
{value, {_, Binary}} = lists:keysearch(<<"sort">>, 1, Q),
Integer = list_to_integer(string:strip(binary_to_list(Binary), right, $/)),
case Integer >= 0 of
true -> {ok, {normal, Integer}};
false -> {ok, {reverse, abs(Integer)}}
@@ -511,14 +511,14 @@ make_rooms_page(Host, Lang, {Sort_direction, Sort_column}) ->
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 = [?T("Jabber ID"),
?T("# participants"),
?T("Last message"),
?T("Public"),
?T("Persistent"),
?T("Logging"),
?T("Just created"),
?T("Room title")],
{Titles_TR, _} =
lists:mapfoldl(
fun(Title, Num_column) ->
@@ -533,7 +533,7 @@ make_rooms_page(Host, Lang, {Sort_direction, Sort_column}) ->
1,
Titles),
PageTitle = translate:translate(Lang, ?T("Multi-User Chat")),
?H1GL(PageTitle, <<"mod-muc">>, <<"mod_muc">>) ++
?H1GL(PageTitle, <<"modules/#mod-muc">>, <<"mod_muc">>) ++
[?XCT(<<"h2">>, ?T("Chatrooms")),
?XE(<<"table">>,
[?XE(<<"thead">>,
@@ -627,9 +627,10 @@ justcreated_to_binary(J) when is_atom(J) ->
create_room(Name1, Host1, ServerHost) ->
create_room_with_opts(Name1, Host1, ServerHost, []).
create_room_with_opts(Name1, Host1, ServerHost, CustomRoomOpts) ->
create_room_with_opts(Name1, Host1, ServerHost1, CustomRoomOpts) ->
true = (error /= (Name = jid:nodeprep(Name1))),
true = (error /= (Host = jid:nodeprep(Host1))),
true = (error /= (ServerHost = jid:nodeprep(ServerHost1))),
%% Get the default room options from the muc configuration
DefRoomOpts = mod_muc_opt:default_room_options(ServerHost),
@@ -805,7 +806,7 @@ get_rooms(ServiceArg) ->
Hosts = find_services(ServiceArg),
lists:flatmap(
fun(Host) ->
[{RoomName, RoomHost, Host, Pid}
[{RoomName, RoomHost, ejabberd_router:host_of_route(Host), Pid}
|| {RoomName, RoomHost, Pid} <- mod_muc:get_online_rooms(Host)]
end, Hosts).
@@ -988,13 +989,22 @@ send_direct_invitation(FromJid, UserJid, Msg) ->
%% 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(<<"testroom">>, <<"conference.localhost">>, <<"title">>, <<"Test Room">>)'
change_room_option(Name, Service, OptionString, ValueString) ->
case get_room_pid(Name, Service) of
room_not_found ->
room_not_found;
Pid ->
{Option, Value} = format_room_option(OptionString, ValueString),
change_room_option(Pid, Option, Value)
end.
change_room_option(Pid, Option, Value) ->
case {Option,
gen_mod:is_loaded((get_room_state(Pid))#state.server_host, mod_muc_log)} of
{logging, false} ->
mod_muc_log_not_enabled;
_ ->
Config = get_room_config(Pid),
Config2 = change_option(Option, Value, Config),
{ok, _} = mod_muc_room:set_config(Pid, Config2),
+5 -2
View File
@@ -92,7 +92,7 @@ check_access_log(Host, From) ->
-spec get_url(#state{}) -> {ok, binary()} | error.
get_url(#state{room = Room, host = Host, server_host = ServerHost}) ->
case mod_muc_log_opt:url(ServerHost) of
try mod_muc_log_opt:url(ServerHost) of
undefined -> error;
URL ->
case mod_muc_log_opt:dirname(ServerHost) of
@@ -101,6 +101,9 @@ get_url(#state{room = Room, host = Host, server_host = ServerHost}) ->
room_name ->
{ok, <<URL/binary, $/, Room/binary>>}
end
catch
error:{module_not_loaded, _, _} ->
error
end.
depends(_Host, _Opts) ->
@@ -485,7 +488,7 @@ get_dateweek(Date, Lang) ->
11 -> tr(Lang, ?T("November"));
12 -> tr(Lang, ?T("December"))
end,
list_to_binary(
unicode:characters_to_binary(
case Lang of
<<"en">> ->
io_lib:format("~ts, ~ts ~w, ~w", [Weekday, Month, D, Y]);

Some files were not shown because too many files have changed in this diff Show More