Compare commits
213 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ef754939c4 | |||
| ee3a0b8b1a | |||
| 2182cb60ae | |||
| 4da8278e66 | |||
| 629db496b5 | |||
| f79b8e166a | |||
| fae4ab97fd | |||
| da8d04a654 | |||
| ce02fc485f | |||
| 69695ffe27 | |||
| 6fdb467484 | |||
| d8016a6477 | |||
| e43d864184 | |||
| 4d3681aba1 | |||
| d791f6ceaa | |||
| 602a42f5ce | |||
| c98739d5b5 | |||
| 425504454c | |||
| 780031847c | |||
| c3af613db1 | |||
| babd01a87f | |||
| 17b605a32b | |||
| fc813acd7b | |||
| d842d6772d | |||
| 67aaf93157 | |||
| 9154275431 | |||
| c343ef7aad | |||
| 78093735b7 | |||
| ed6a111982 | |||
| a8a5be7a34 | |||
| 5008947e32 | |||
| 0827a5116f | |||
| 85d0e93af5 | |||
| f677436437 | |||
| 05f8992e3e | |||
| 2ed7ce49a2 | |||
| 9087867631 | |||
| f58a0cdbfd | |||
| 91fb02d62e | |||
| d831fd4789 | |||
| 322e642f19 | |||
| 4967acaec9 | |||
| 113e5a322e | |||
| 9c29457ee2 | |||
| 4fe5ee034c | |||
| 78650f827e | |||
| a4fc448a52 | |||
| 01a71dc189 | |||
| 90a200be25 | |||
| 9c92fcc92d | |||
| 6f9f4b3635 | |||
| 968fbc9424 | |||
| 7862c6a7db | |||
| ced72f4a89 | |||
| 85dbadee5c | |||
| cf13abdab6 | |||
| 239d4a5bfb | |||
| 51e96433ea | |||
| 12274a969a | |||
| 79a4dd4a26 | |||
| d9e86600dc | |||
| b8cb1bbdcf | |||
| c180349fc6 | |||
| a6fec278c3 | |||
| 999ede59ce | |||
| 30a7b0ef3b | |||
| 16af90648e | |||
| 7723951c05 | |||
| 1668cde93f | |||
| 418ca34c85 | |||
| 6d8e588b78 | |||
| 9bf2d6ce5b | |||
| 496daf9220 | |||
| 573e06cc0c | |||
| 6d77ace5c9 | |||
| aa78362c7f | |||
| 6151674e64 | |||
| 1ea0dde417 | |||
| 53dea7b6d7 | |||
| c87ba45a86 | |||
| 6ea25e2272 | |||
| 888c335c2e | |||
| 4dcf97c4c1 | |||
| 352ee3a318 | |||
| c8abff33c1 | |||
| 998690f58c | |||
| 6e68c2ec02 | |||
| 896b7c7559 | |||
| 69b190775c | |||
| b769de0690 | |||
| 19482529ee | |||
| ad8e325139 | |||
| b901a69f5c | |||
| 62a165e4cf | |||
| 29616dc163 | |||
| 60324d4b7a | |||
| cfa6575b4f | |||
| 3b01e4e4e0 | |||
| fa4a93c465 | |||
| 74d6d53ac6 | |||
| 8070a656fe | |||
| 105a0c2029 | |||
| e887546c27 | |||
| 9305232f8c | |||
| 7832a6342a | |||
| c924a47188 | |||
| 1d42d55064 | |||
| dd7550dbad | |||
| 7df7daa050 | |||
| 090a7e664e | |||
| 3d49bed0cf | |||
| 9f28098d04 | |||
| e761b22c61 | |||
| 4d62f545c5 | |||
| f789495c39 | |||
| 46a64c0f68 | |||
| ab8a39e71f | |||
| 630301a7ba | |||
| d4fd987e84 | |||
| c5abe5d882 | |||
| 71dbbc1b5a | |||
| c9a9585573 | |||
| bb2f398fa2 | |||
| afc54aeb20 | |||
| 9c142e5509 | |||
| 27f98f50d3 | |||
| 0145594adc | |||
| 67ee0de7e3 | |||
| 087718c47a | |||
| 6bf5930703 | |||
| 90c4fa2a84 | |||
| b75c3257bd | |||
| 178b09f5bb | |||
| 70980efe39 | |||
| c124dbdd6a | |||
| 6af2a65e53 | |||
| 54f89e7568 | |||
| 66205cf648 | |||
| b38d8618b2 | |||
| 051093f4f8 | |||
| 2a85c0a474 | |||
| 7018b8b164 | |||
| 41232ccb39 | |||
| 6bd4399aee | |||
| 45dafbcdcc | |||
| a32bfd1215 | |||
| 78f7a9a244 | |||
| 44782001e2 | |||
| c7d7d07ee4 | |||
| 27390c387d | |||
| ceee3d3be1 | |||
| 983c016bba | |||
| 8a7e955453 | |||
| 376f7b261e | |||
| 80423d7e69 | |||
| da61f3dfea | |||
| a49ec4d583 | |||
| 5f849bdb3f | |||
| d875e0280c | |||
| 4188c062e7 | |||
| 21ae72d02e | |||
| d834a9c1c1 | |||
| 07b102bb80 | |||
| 480e2442ee | |||
| a9c7bf97ef | |||
| cae40c3f72 | |||
| 4f90d1a0d9 | |||
| 22b3d0e49f | |||
| 0732603a4e | |||
| e34b6f4204 | |||
| 64142de4fe | |||
| a4062f6ac0 | |||
| 76baf58d5d | |||
| e134d7f0b4 | |||
| 20a0051578 | |||
| eca3204e82 | |||
| a19ab9f4e3 | |||
| 133d52d040 | |||
| 20a77cb9c7 | |||
| cab96d2156 | |||
| 9be76cce9e | |||
| e7035f3235 | |||
| 6e4ac0c501 | |||
| aa612463cc | |||
| 9827ad43e4 | |||
| e0bb900651 | |||
| ad1b577ca9 | |||
| f72cfa9a13 | |||
| 056635119c | |||
| 2e754a5557 | |||
| 6959447c2c | |||
| 4a363b6e76 | |||
| 862cacabcb | |||
| 29e6204bde | |||
| bc6c868c8a | |||
| 9d87193d80 | |||
| 85b660fb4b | |||
| 5a6e46c32a | |||
| 457d8fc6cc | |||
| 8ebbb45a19 | |||
| 13dae75d01 | |||
| 172847bc76 | |||
| 2b2551bc50 | |||
| aa8957f137 | |||
| ba9a7916db | |||
| 5945dba412 | |||
| 7d5413ce95 | |||
| 364ee0f8ed | |||
| 213a513f54 | |||
| aa65e626f4 | |||
| 5b3b29565c | |||
| f38f81159d | |||
| 73f5d950e5 |
@@ -1,20 +1,22 @@
|
||||
#' Define default build variables
|
||||
## specifc ARGs for METHOD='direct'
|
||||
ARG OTP_VSN='26.2'
|
||||
ARG ELIXIR_VSN='1.16.2'
|
||||
## specifc ARGs for METHOD='package'
|
||||
ARG ALPINE_VSN='3.19'
|
||||
## general ARGs
|
||||
ARG OTP_VSN='27.3.2'
|
||||
ARG ELIXIR_VSN='1.18.3'
|
||||
ARG UID='9000'
|
||||
ARG USER='ejabberd'
|
||||
ARG HOME="opt/$USER"
|
||||
ARG METHOD='direct'
|
||||
ARG BUILD_DIR="/$USER"
|
||||
ARG VERSION='master'
|
||||
|
||||
################################################################################
|
||||
#' METHOD='direct' - build and install ejabberd directly from source
|
||||
FROM docker.io/erlang:${OTP_VSN}-alpine AS direct
|
||||
#' Compile ejabberdapi
|
||||
FROM docker.io/golang:1.24-alpine AS api
|
||||
RUN go install -v \
|
||||
github.com/processone/ejabberd-api/cmd/ejabberd@master \
|
||||
&& mv bin/ejabberd bin/ejabberdapi
|
||||
|
||||
################################################################################
|
||||
#' build and install ejabberd directly from source
|
||||
FROM docker.io/erlang:${OTP_VSN}-alpine AS ejabberd
|
||||
|
||||
RUN apk -U add --no-cache \
|
||||
autoconf \
|
||||
@@ -39,7 +41,8 @@ ARG ELIXIR_VSN
|
||||
RUN wget -O - https://github.com/elixir-lang/elixir/archive/v$ELIXIR_VSN.tar.gz \
|
||||
| tar -xzf -
|
||||
|
||||
WORKDIR elixir-$ELIXIR_VSN
|
||||
WORKDIR /elixir-$ELIXIR_VSN
|
||||
ENV ERL_FLAGS="+JPperf true"
|
||||
RUN make install clean
|
||||
|
||||
RUN mix local.hex --force \
|
||||
@@ -50,6 +53,7 @@ COPY / $BUILD_DIR/
|
||||
|
||||
WORKDIR $BUILD_DIR
|
||||
RUN mv .github/container/ejabberdctl.template . \
|
||||
&& mv .github/container/ejabberd.yml.example . \
|
||||
&& ./autogen.sh \
|
||||
&& ./configure --with-rebar=mix --enable-all \
|
||||
&& make deps \
|
||||
@@ -67,36 +71,18 @@ RUN cp -p $BUILD_DIR/tools/captcha*.sh $HOME-$VERSION/lib
|
||||
RUN find "$HOME-$VERSION/bin" -name 'ejabberd' -delete \
|
||||
&& find "$HOME-$VERSION/releases" -name 'COOKIE' -delete
|
||||
|
||||
RUN wget -O "$HOME/conf/cacert.pem" 'https://curl.se/ca/cacert.pem' \
|
||||
&& sed -i '/^loglevel:/a \ \
|
||||
\nca_file: /opt/ejabberd/conf/cacert.pem \
|
||||
\ncertfiles: \
|
||||
\n - /opt/ejabberd/conf/server.pem' "$HOME/conf/ejabberd.yml"
|
||||
RUN wget -O "$HOME/conf/cacert.pem" 'https://curl.se/ca/cacert.pem'
|
||||
|
||||
################################################################################
|
||||
#' METHOD='package' - install ejabberd from binary tarball package
|
||||
FROM docker.io/alpine:${ALPINE_VSN} AS package
|
||||
COPY tarballs/ejabberd-*-linux-musl-*.tar.gz /tmp/
|
||||
WORKDIR /rootfs
|
||||
ARG HOME
|
||||
RUN home_root_dir=$(echo $HOME | sed 's|\(.*\)/.*|\1 |') \
|
||||
&& mkdir -p $home_root_dir \
|
||||
&& ARCH=$(uname -m | sed -e 's/x86_64/x64/;s/aarch64/arm64/') \
|
||||
&& tar -xzf /tmp/ejabberd-*-linux-musl-$ARCH.tar.gz -C $home_root_dir
|
||||
|
||||
################################################################################
|
||||
#' Prepare ejabberd for runtime
|
||||
FROM ${METHOD} AS ejabberd
|
||||
RUN apk -U add --no-cache \
|
||||
git \
|
||||
libcap \
|
||||
openssl
|
||||
|
||||
WORKDIR /rootfs
|
||||
ARG HOME
|
||||
RUN mkdir -p usr/local/bin $HOME/conf $HOME/database $HOME/logs $HOME/upload
|
||||
|
||||
ARG BUILD_DIR
|
||||
COPY --from=api /go/bin/ejabberdapi usr/local/bin/
|
||||
|
||||
RUN if [ ! -d $HOME/.ejabberd-modules ]; \
|
||||
then \
|
||||
if [ -d $BUILD_DIR/.ejabberd-modules ]; \
|
||||
@@ -116,11 +102,35 @@ RUN export PEM=$HOME/conf/server.pem \
|
||||
-days 3650 \
|
||||
-subj "/CN=localhost"
|
||||
|
||||
RUN sed -i 's|^#CTL_OVER_HTTP=|CTL_OVER_HTTP=../|' "$HOME/conf/ejabberdctl.cfg"
|
||||
|
||||
RUN home_root_dir=$(echo $HOME | sed 's|\(.*\)/.*|\1 |') \
|
||||
&& setcap 'cap_net_bind_service=+ep' $(find $home_root_dir -name beam.smp) \
|
||||
&& echo -e \
|
||||
"#!/bin/sh \
|
||||
\n[ -z \$ERLANG_NODE_ARG ] && export ERLANG_NODE_ARG=ejabberd@localhost \
|
||||
\nexport EMA=\"\$EJABBERD_MACRO_ADMIN\" \
|
||||
\nexport HOST=\"\${EJABBERD_MACRO_HOST:-localhost}\" \
|
||||
\nif [ -n \"\$EMA\" ] \
|
||||
\nthen \
|
||||
\n if [ \"\$EMA\" != \"\${EMA%%@*}\" ] \
|
||||
\n then \
|
||||
\n export USERNAME=\"\${EMA%%@*}\" \
|
||||
\n export HOST=\"\${EMA##*@}\" \
|
||||
\n else \
|
||||
\n export USERNAME=\"\$EMA\" \
|
||||
\n export SHOW_WARNING=\"true\" \
|
||||
\n fi \
|
||||
\nelif [ -n \"\$REGISTER_ADMIN_PASSWORD\" ] \
|
||||
\nthen \
|
||||
\n export USERNAME=\"admin\" \
|
||||
\nelse \
|
||||
\n export USERNAME=\"\$(od -A n -N 8 -t x8 /dev/urandom)\" \
|
||||
\nfi \
|
||||
\nexport EJABBERD_MACRO_ADMIN=\"\$USERNAME@\$HOST\" \
|
||||
\n[ -n \"\$SHOW_WARNING\" ] && echo \"WARNING: The EJABBERD_MACRO_ADMIN environment variable was set to '\$EMA', but it should include the host... I'll overwrite it to become '\$EJABBERD_MACRO_ADMIN'.\" \
|
||||
\n[ -n \"\$CTL_ON_CREATE\" ] && export SEPARATOR=\";\" \
|
||||
\n[ -n \"\$REGISTER_ADMIN_PASSWORD\" ] && export CTL_ON_CREATE=\"register \${EJABBERD_MACRO_ADMIN%%@*} \${EJABBERD_MACRO_ADMIN##*@} \$REGISTER_ADMIN_PASSWORD \$SEPARATOR \$CTL_ON_CREATE\" \
|
||||
\nexport CONFIG_DIR=/$HOME/conf \
|
||||
\nexport LOGS_DIR=/$HOME/logs \
|
||||
\nexport SPOOL_DIR=/$HOME/database \
|
||||
@@ -137,28 +147,28 @@ RUN home_root_dir=$(echo $HOME | sed 's|\(.*\)/.*|\1 |') \
|
||||
ARG UID
|
||||
RUN chown -R $UID:$UID $HOME
|
||||
|
||||
RUN cp /rootfs/$HOME-$VERSION/lib/captcha*.sh usr/local/bin/
|
||||
RUN mkdir $HOME/sql \
|
||||
&& find /rootfs/$HOME-$VERSION/lib/ -name *.sql -exec cp {} $HOME/sql \; -exec cp {} $HOME/database \;
|
||||
|
||||
################################################################################
|
||||
#' METHOD='direct' - Remove erlang/OTP & rebar3
|
||||
FROM docker.io/erlang:${OTP_VSN}-alpine AS runtime-direct
|
||||
#' Remove erlang/OTP & rebar3
|
||||
FROM docker.io/erlang:${OTP_VSN}-alpine AS runtime
|
||||
RUN apk del .erlang-rundeps \
|
||||
&& rm -f $(which rebar3) \
|
||||
&& find /usr -type d -name 'erlang' -exec rm -rf {} + \
|
||||
&& find /usr -type l -exec test ! -e {} \; -delete
|
||||
|
||||
################################################################################
|
||||
#' METHOD='package' - define runtime base image
|
||||
FROM docker.io/alpine:${ALPINE_VSN} AS runtime-package
|
||||
|
||||
################################################################################
|
||||
#' Update alpine, finalize runtime environment
|
||||
FROM runtime-${METHOD} AS runtime
|
||||
COPY --from=ejabberd /tmp/runDeps /tmp/runDeps
|
||||
RUN apk -U upgrade --available --no-cache \
|
||||
&& apk add --no-cache \
|
||||
$(cat /tmp/runDeps) \
|
||||
so:libcap.so.2 \
|
||||
so:libtdsodbc.so.0 \
|
||||
curl \
|
||||
tini \
|
||||
&& rm /tmp/runDeps \
|
||||
&& ln -fs /usr/lib/libtdsodbc.so.0 /usr/lib/libtdsodbc.so
|
||||
|
||||
ARG USER
|
||||
@@ -167,9 +177,13 @@ ARG HOME
|
||||
RUN addgroup $USER -g $UID \
|
||||
&& adduser -s /sbin/nologin -D -u $UID -h /$HOME -G $USER $USER
|
||||
|
||||
RUN ln -fs /usr/local/bin/ /opt/ejabberd/bin
|
||||
RUN rm -rf /home \
|
||||
&& ln -fs /opt /home
|
||||
|
||||
################################################################################
|
||||
#' Build together production image
|
||||
FROM scratch AS prod
|
||||
FROM scratch
|
||||
ARG USER
|
||||
ARG HOME
|
||||
|
||||
@@ -186,7 +200,7 @@ HEALTHCHECK \
|
||||
WORKDIR /$HOME
|
||||
USER $USER
|
||||
VOLUME ["/$HOME"]
|
||||
EXPOSE 1883 4369-4399 5210 5222 5269 5280 5443
|
||||
EXPOSE 1880 1883 4369-4399 5210 5222 5269 5280 5443
|
||||
|
||||
ENTRYPOINT ["/sbin/tini","--","ejabberdctl"]
|
||||
CMD ["foreground"]
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
###
|
||||
### ejabberd configuration file
|
||||
###
|
||||
### The parameters used in this configuration file are explained at
|
||||
###
|
||||
### https://docs.ejabberd.im/admin/configuration
|
||||
###
|
||||
### The configuration file is written in YAML.
|
||||
### *******************************************************
|
||||
### ******* !!! WARNING !!! *******
|
||||
### ******* YAML IS INDENTATION SENSITIVE *******
|
||||
### ******* MAKE SURE YOU INDENT SECTIONS CORRECTLY *******
|
||||
### *******************************************************
|
||||
### Refer to http://en.wikipedia.org/wiki/YAML for the brief description.
|
||||
###
|
||||
|
||||
define_macro:
|
||||
HOST: localhost
|
||||
## ADMIN: ... # set by /usr/local/bin/ejabberdctl
|
||||
PORT_C2S: 5222
|
||||
PORT_C2S_TLS: 5223
|
||||
PORT_S2S: 5269
|
||||
PORT_HTTP_TLS: 5443
|
||||
PORT_HTTP: 5280
|
||||
PORT_BROWSER: 1880
|
||||
PORT_STUN: 5478
|
||||
PORT_MQTT: 1883
|
||||
PORT_PROXY65: 7777
|
||||
|
||||
hosts:
|
||||
- HOST
|
||||
|
||||
loglevel: info
|
||||
|
||||
## If you already have certificates, list them here
|
||||
# certfiles:
|
||||
# - /etc/letsencrypt/live/domain.tld/fullchain.pem
|
||||
# - /etc/letsencrypt/live/domain.tld/privkey.pem
|
||||
|
||||
ca_file: /opt/ejabberd/conf/cacert.pem
|
||||
certfiles:
|
||||
- /opt/ejabberd/conf/server.pem
|
||||
|
||||
listen:
|
||||
-
|
||||
port: PORT_C2S
|
||||
ip: "::"
|
||||
module: ejabberd_c2s
|
||||
max_stanza_size: 262144
|
||||
shaper: c2s_shaper
|
||||
access: c2s
|
||||
starttls_required: true
|
||||
-
|
||||
port: PORT_C2S_TLS
|
||||
ip: "::"
|
||||
module: ejabberd_c2s
|
||||
max_stanza_size: 262144
|
||||
shaper: c2s_shaper
|
||||
access: c2s
|
||||
tls: true
|
||||
-
|
||||
port: PORT_S2S
|
||||
ip: "::"
|
||||
module: ejabberd_s2s_in
|
||||
max_stanza_size: 524288
|
||||
shaper: s2s_shaper
|
||||
-
|
||||
port: PORT_HTTP_TLS
|
||||
ip: "::"
|
||||
module: ejabberd_http
|
||||
tls: true
|
||||
request_handlers:
|
||||
/admin: ejabberd_web_admin
|
||||
/api: mod_http_api
|
||||
/bosh: mod_bosh
|
||||
/captcha: ejabberd_captcha
|
||||
/upload: mod_http_upload
|
||||
/ws: ejabberd_http_ws
|
||||
-
|
||||
port: PORT_HTTP
|
||||
ip: "::"
|
||||
module: ejabberd_http
|
||||
request_handlers:
|
||||
/admin: ejabberd_web_admin
|
||||
/.well-known/acme-challenge: ejabberd_acme
|
||||
-
|
||||
port: PORT_BROWSER
|
||||
ip: "::"
|
||||
module: ejabberd_http
|
||||
request_handlers:
|
||||
/: ejabberd_web_admin
|
||||
-
|
||||
port: "unix:../sockets/ctl_over_http.sock"
|
||||
module: ejabberd_http
|
||||
unix_socket:
|
||||
mode: '0600'
|
||||
request_handlers:
|
||||
/ctl: ejabberd_ctl
|
||||
-
|
||||
port: PORT_STUN
|
||||
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: PORT_MQTT
|
||||
ip: "::"
|
||||
module: mod_mqtt
|
||||
backlog: 1000
|
||||
|
||||
s2s_use_starttls: optional
|
||||
|
||||
acl:
|
||||
local:
|
||||
user_regexp: ""
|
||||
loopback:
|
||||
ip:
|
||||
- 127.0.0.0/8
|
||||
- ::1/128
|
||||
admin:
|
||||
user:
|
||||
- ADMIN
|
||||
|
||||
access_rules:
|
||||
local:
|
||||
allow: local
|
||||
c2s:
|
||||
deny: blocked
|
||||
allow: all
|
||||
announce:
|
||||
allow: admin
|
||||
configure:
|
||||
allow: admin
|
||||
muc_create:
|
||||
allow: local
|
||||
pubsub_createnode:
|
||||
allow: local
|
||||
trusted_network:
|
||||
allow: loopback
|
||||
|
||||
api_permissions:
|
||||
"console commands":
|
||||
from: ejabberd_ctl
|
||||
who: all
|
||||
what: "*"
|
||||
"webadmin commands":
|
||||
from: ejabberd_web_admin
|
||||
who: admin
|
||||
what: "*"
|
||||
"admin access":
|
||||
who:
|
||||
access:
|
||||
allow:
|
||||
- acl: loopback
|
||||
- acl: admin
|
||||
oauth:
|
||||
scope: "ejabberd:admin"
|
||||
access:
|
||||
allow:
|
||||
- acl: loopback
|
||||
- acl: admin
|
||||
what:
|
||||
- "*"
|
||||
- "!stop"
|
||||
- "!start"
|
||||
"public commands":
|
||||
who:
|
||||
ip: 127.0.0.1/8
|
||||
what:
|
||||
- status
|
||||
- connected_users_number
|
||||
|
||||
shaper:
|
||||
normal:
|
||||
rate: 3000
|
||||
burst_size: 20000
|
||||
fast: 100000
|
||||
|
||||
shaper_rules:
|
||||
max_user_sessions: 10
|
||||
max_user_offline_messages:
|
||||
5000: admin
|
||||
100: all
|
||||
c2s_shaper:
|
||||
none: admin
|
||||
normal: all
|
||||
s2s_shaper: fast
|
||||
|
||||
modules:
|
||||
mod_adhoc: {}
|
||||
mod_admin_extra: {}
|
||||
mod_announce:
|
||||
access: announce
|
||||
mod_avatar: {}
|
||||
mod_blocking: {}
|
||||
mod_bosh: {}
|
||||
mod_caps: {}
|
||||
mod_carboncopy: {}
|
||||
mod_client_state: {}
|
||||
mod_configure: {}
|
||||
mod_disco: {}
|
||||
mod_fail2ban: {}
|
||||
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
|
||||
## For small servers SQLite is a good fit and is very easy
|
||||
## to configure. Uncomment this when you have SQL configured:
|
||||
## db_type: sql
|
||||
assume_mam_usage: true
|
||||
default: always
|
||||
mod_mqtt: {}
|
||||
mod_muc:
|
||||
access:
|
||||
- allow
|
||||
access_admin:
|
||||
- allow: admin
|
||||
access_create: muc_create
|
||||
access_persistent: muc_create
|
||||
access_mam:
|
||||
- allow
|
||||
default_room_options:
|
||||
mam: true
|
||||
mod_muc_admin: {}
|
||||
mod_offline:
|
||||
access_max_user_messages: max_user_offline_messages
|
||||
mod_ping: {}
|
||||
mod_privacy: {}
|
||||
mod_private: {}
|
||||
mod_proxy65:
|
||||
access: local
|
||||
max_connections: 5
|
||||
port: PORT_PROXY65
|
||||
mod_pubsub:
|
||||
access_createnode: pubsub_createnode
|
||||
plugins:
|
||||
- flat
|
||||
- pep
|
||||
force_node_config:
|
||||
## Avoid buggy clients to make their bookmarks public
|
||||
storage:bookmarks:
|
||||
access_model: whitelist
|
||||
mod_push: {}
|
||||
mod_push_keepalive: {}
|
||||
mod_register:
|
||||
## Only accept registration requests from the "trusted"
|
||||
## network (see access_rules section above).
|
||||
## Think twice before enabling registration from any
|
||||
## address. See the Jabber SPAM Manifesto for details:
|
||||
## https://github.com/ge0rg/jabber-spam-fighting-manifesto
|
||||
ip_access: trusted_network
|
||||
mod_roster:
|
||||
versioning: true
|
||||
mod_s2s_bidi: {}
|
||||
mod_s2s_dialback: {}
|
||||
mod_shared_roster: {}
|
||||
mod_stream_mgmt:
|
||||
resend_on_timeout: if_offline
|
||||
mod_stun_disco: {}
|
||||
mod_vcard: {}
|
||||
mod_vcard_xupdate: {}
|
||||
mod_version:
|
||||
show_os: false
|
||||
|
||||
### Local Variables:
|
||||
### mode: yaml
|
||||
### End:
|
||||
### vim: set filetype=yaml tabstop=8
|
||||
@@ -71,6 +71,10 @@ done
|
||||
: "${SPOOL_DIR:="{{spool_dir}}"}"
|
||||
: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
|
||||
|
||||
# backward support for old mnesia spool dir path
|
||||
: "${SPOOL_DIR_OLD:="$SPOOL_DIR/$ERLANG_NODE"}"
|
||||
[ -r "$SPOOL_DIR_OLD/schema.DAT" ] && [ ! -r "$SPOOL_DIR/schema.DAT" ] && SPOOL_DIR="$SPOOL_DIR_OLD"
|
||||
|
||||
# define erl parameters
|
||||
ERLANG_OPTS="+K $POLL +P $ERL_PROCESSES $ERL_OPTIONS"
|
||||
if [ -n "$FIREWALL_WINDOW" ] ; then
|
||||
@@ -265,7 +269,7 @@ help()
|
||||
|
||||
# dynamic node name helper
|
||||
uid() {
|
||||
ERTSVERSION="$("$ERL" -version 2>&1 | sed 's|.*\([0-9][0-9]\).*|\1|g')"
|
||||
ERTSVERSION="$("$ERL" -version 2>&1 | sed 's|.* \([0-9]*[0-9]\).*|\1|g')"
|
||||
if [ $ERTSVERSION -lt 11 ] ; then # otp 23.0 includes erts 11.0
|
||||
# Erlang/OTP lower than 23, which doesn's support dynamic node code
|
||||
N=1
|
||||
@@ -305,6 +309,8 @@ stop_epmd()
|
||||
# if all ok, ensure runtime directory exists and make it current directory
|
||||
check_start()
|
||||
{
|
||||
ECSIMAGE_DBPATH=$HOME/database/$ERLANG_NODE
|
||||
[ ! -d "$ECSIMAGE_DBPATH" ] && ln -s $HOME/database $HOME/database/$ERLANG_NODE
|
||||
[ -n "$ERL_DIST_PORT" ] && return
|
||||
"$EPMD" -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && {
|
||||
pgrep -f "$ERLANG_NODE" >/dev/null && {
|
||||
@@ -377,6 +383,54 @@ wait_status()
|
||||
[ $timeout -gt 0 ]
|
||||
}
|
||||
|
||||
exec_other_command()
|
||||
{
|
||||
if [ -z "$CTL_OVER_HTTP" ] || [ ! -S "$CTL_OVER_HTTP" ] \
|
||||
|| [ ! -x "$(command -v curl)" ] || [ -z "$1" ] || [ "$1" = "help" ] \
|
||||
|| [ "$1" = "mnesia_info_ctl" ]|| [ "$1" = "print_sql_schema" ] ; then
|
||||
run_erl "$(uid ctl)" -hidden -noinput \
|
||||
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
|
||||
-s ejabberd_ctl \
|
||||
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
|
||||
result=$?
|
||||
case $result in
|
||||
3) help;;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
else
|
||||
exec_ctl_over_http_socket "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
exec_ctl_over_http_socket()
|
||||
{
|
||||
COMMAND=${1}
|
||||
CARGS=""
|
||||
while [ $# -gt 0 ]; do
|
||||
[ -z "$CARGS" ] && CARGS="[" || CARGS="${CARGS}, "
|
||||
CARGS="${CARGS}\"$1\""
|
||||
shift
|
||||
done
|
||||
CARGS="${CARGS}]"
|
||||
TEMPHEADERS=temp-headers.log
|
||||
curl \
|
||||
--unix-socket ${CTL_OVER_HTTP} \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "Accept: application/json" \
|
||||
--data "${CARGS}" \
|
||||
--dump-header ${TEMPHEADERS} \
|
||||
--no-progress-meter \
|
||||
"http://localhost/ctl/${COMMAND}"
|
||||
result=$(sed -n 's/.*status-code: \([0-9]*\).*/\1/p' < $TEMPHEADERS)
|
||||
rm ${TEMPHEADERS}
|
||||
case $result in
|
||||
2|3) exec_other_command help ${COMMAND};;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
}
|
||||
|
||||
# ensure we can change current directory to SPOOL_DIR
|
||||
[ -f "$SPOOL_DIR/schema.DAT" ] || FIRST_RUN=true
|
||||
[ -d "$SPOOL_DIR" ] || run_cmd mkdir -p "$SPOOL_DIR"
|
||||
@@ -452,15 +506,6 @@ case $1 in
|
||||
;;
|
||||
*)
|
||||
set_dist_client
|
||||
run_erl "$(uid ctl)" -hidden -noinput \
|
||||
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
|
||||
-s ejabberd_ctl \
|
||||
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
|
||||
result=$?
|
||||
case $result in
|
||||
2|3) help;;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
exec_other_command "$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
+12
-20
@@ -25,11 +25,11 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
otp: ['20.0', '25', '26', '27']
|
||||
runs-on: ubuntu-20.04
|
||||
otp: ['25', '26', '27']
|
||||
runs-on: ubuntu-24.04
|
||||
services:
|
||||
redis:
|
||||
image: redis
|
||||
image: public.ecr.aws/docker/library/redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Test shell scripts
|
||||
if: matrix.otp == '26'
|
||||
if: matrix.otp == '27'
|
||||
run: |
|
||||
shellcheck test/ejabberd_SUITE_data/gencerts.sh
|
||||
shellcheck tools/captcha.sh
|
||||
@@ -50,13 +50,6 @@ jobs:
|
||||
with:
|
||||
otp-version: ${{ matrix.otp }}
|
||||
|
||||
- name: Get a compatible Rebar3
|
||||
if: matrix.otp < 24
|
||||
run: |
|
||||
rm rebar3
|
||||
wget https://github.com/processone/ejabberd/raw/21.12/rebar3
|
||||
chmod +x rebar3
|
||||
|
||||
- name: Install MS SQL Server
|
||||
run: |
|
||||
docker run -d -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=ejabberd_Test1" \
|
||||
@@ -83,6 +76,8 @@ jobs:
|
||||
WITH PASSWORD 'ejabberd_test';"
|
||||
sudo -u postgres psql -c "GRANT ALL PRIVILEGES
|
||||
ON DATABASE ejabberd_test TO ejabberd_test;"
|
||||
sudo -u postgres psql -c "GRANT ALL ON SCHEMA public TO ejabberd_test;"
|
||||
sudo -u postgres psql -c "ALTER DATABASE ejabberd_test OWNER TO ejabberd_test;"
|
||||
sudo -u postgres psql ejabberd_test -c "GRANT ALL PRIVILEGES ON ALL
|
||||
TABLES IN SCHEMA public
|
||||
TO ejabberd_test;"
|
||||
@@ -107,10 +102,6 @@ jobs:
|
||||
~/.cache/rebar3/
|
||||
key: ${{matrix.otp}}-${{hashFiles('rebar.config')}}
|
||||
|
||||
- name: Get compatible Rebar binaries
|
||||
if: matrix.otp < 21
|
||||
run: ./rebar3 unlock eredis
|
||||
|
||||
- name: Compile
|
||||
run: |
|
||||
./autogen.sh
|
||||
@@ -129,7 +120,6 @@ jobs:
|
||||
- run: make dialyzer
|
||||
- run: make test-eunit
|
||||
- run: make elvis
|
||||
if: matrix.otp >= 23
|
||||
|
||||
- name: Check Production Release
|
||||
run: |
|
||||
@@ -153,9 +143,9 @@ jobs:
|
||||
grep -q "is started in" $RE/logs/ejabberd.log
|
||||
|
||||
- name: Run XMPP Interoperability Tests against CI server.
|
||||
if: matrix.otp == '26'
|
||||
if: matrix.otp == '27'
|
||||
continue-on-error: true
|
||||
uses: XMPP-Interop-Testing/xmpp-interop-tests-action@v1.4.0
|
||||
uses: XMPP-Interop-Testing/xmpp-interop-tests-action@v1.5.0
|
||||
with:
|
||||
domain: 'localhost'
|
||||
adminAccountUsername: 'admin'
|
||||
@@ -185,7 +175,7 @@ jobs:
|
||||
./rebar3 cover
|
||||
|
||||
- name: Check results
|
||||
if: always() && (steps.ct.outcome != 'skipped' || steps.ct2.outcome != 'skipped')
|
||||
if: always() && (steps.ct.outcome != 'skipped')
|
||||
id: ctresults
|
||||
run: |
|
||||
[[ -d _build ]] && ln -s _build/test/logs/last/ logs || true
|
||||
@@ -203,7 +193,7 @@ jobs:
|
||||
find logs/ -name exunit.log -exec cat '{}' ';'
|
||||
|
||||
- name: Send to coveralls
|
||||
if: matrix.otp == '26'
|
||||
if: matrix.otp == '27'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
@@ -267,6 +257,8 @@ jobs:
|
||||
sudo -u postgres psql -c "CREATE DATABASE ejabberd_test;"
|
||||
sudo -u postgres psql -c "GRANT ALL PRIVILEGES
|
||||
ON DATABASE ejabberd_test TO ejabberd_test;"
|
||||
sudo -u postgres psql -c "GRANT ALL ON SCHEMA public TO ejabberd_test;"
|
||||
sudo -u postgres psql -c "ALTER DATABASE ejabberd_test OWNER TO ejabberd_test;"
|
||||
sudo -u postgres psql ejabberd_test -c "GRANT ALL PRIVILEGES ON ALL
|
||||
TABLES IN SCHEMA public
|
||||
TO ejabberd_test;"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
name: Container
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '22 2 */6 * *' # every 6 days to avoid gha cache being evicted
|
||||
push:
|
||||
paths-ignore:
|
||||
- '.devcontainer/**'
|
||||
@@ -19,7 +17,7 @@ env:
|
||||
jobs:
|
||||
container:
|
||||
name: Container
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
packages: write
|
||||
steps:
|
||||
@@ -28,52 +26,6 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache build directory
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/build/
|
||||
key: ${{runner.os}}-ctr-ct-ng-1.26.0
|
||||
|
||||
- name: Get erlang/OTP version for bootstrapping
|
||||
run: |
|
||||
echo "OTP_VSN=$(awk '/^otp_vsn=/ {{gsub(/[^0-9.rc-]/, ""); print}}' tools/make-binaries)" >> $GITHUB_ENV
|
||||
echo "ELIXIR_VSN=$(awk '/^elixir_vsn=/ {{gsub(/[^0-9.]/, ""); print}}' tools/make-binaries)" >> $GITHUB_ENV
|
||||
|
||||
- name: Install prerequisites
|
||||
run: |
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get -qq install makeself
|
||||
# https://github.com/crosstool-ng/crosstool-ng/blob/master/testing/docker/ubuntu21.10/Dockerfile
|
||||
sudo apt-get -qq install build-essential autoconf bison flex gawk
|
||||
sudo apt-get -qq install help2man libncurses5-dev libtool libtool-bin
|
||||
sudo apt-get -qq install python3-dev texinfo unzip
|
||||
|
||||
- name: Install erlang/OTP
|
||||
uses: erlef/setup-beam@v1
|
||||
with:
|
||||
otp-version: ${{ env.OTP_VSN }}
|
||||
elixir-version: ${{ env.ELIXIR_VSN }}
|
||||
version-type: strict
|
||||
|
||||
- name: Remove Elixir Matchers
|
||||
run: |
|
||||
echo "::remove-matcher owner=elixir-mixCompileWarning::"
|
||||
echo "::remove-matcher owner=elixir-credoOutputDefault::"
|
||||
echo "::remove-matcher owner=elixir-mixCompileError::"
|
||||
echo "::remove-matcher owner=elixir-mixTestFailure::"
|
||||
echo "::remove-matcher owner=elixir-dialyzerOutputDefault::"
|
||||
|
||||
- name: Build musl-libc based binary archives
|
||||
run: |
|
||||
sed -i "s|targets='.*'|targets='x86_64-linux-musl aarch64-linux-musl'|" tools/make-binaries
|
||||
mv .github/container/ejabberdctl.template .
|
||||
CHECK_DEPS=false tools/make-binaries
|
||||
|
||||
- name: Collect packages
|
||||
run: |
|
||||
mkdir tarballs
|
||||
mv ejabberd-*.tar.gz tarballs
|
||||
|
||||
- name: Checkout ejabberd-contrib
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -111,7 +63,6 @@ jobs:
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
build-args: |
|
||||
METHOD=package
|
||||
VERSION=${{ steps.gitdescribe.outputs.ver }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
@@ -21,13 +21,13 @@ on:
|
||||
jobs:
|
||||
binaries:
|
||||
name: Binaries
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Cache build directory
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/build/
|
||||
key: ${{runner.os}}-ct-ng-1.26.0
|
||||
key: ${{runner.os}}-ct-ng-1.27.0
|
||||
- name: Install prerequisites
|
||||
run: |
|
||||
sudo apt-get -qq update
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
release:
|
||||
name: Release
|
||||
needs: [binaries]
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.ref_type == 'tag'
|
||||
steps:
|
||||
- name: Download packages
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
rebar: 'rebar'
|
||||
runs-on: ubuntu-24.04
|
||||
container:
|
||||
image: erlang:${{ matrix.otp }}
|
||||
image: public.ecr.aws/docker/library/erlang:${{ matrix.otp }}
|
||||
|
||||
steps:
|
||||
|
||||
@@ -164,10 +164,10 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
elixir: ['1.13', '1.14', '1.15', '1.16', '1.17']
|
||||
elixir: ['1.13', '1.14', '1.15', '1.16', '1.17', '1.18']
|
||||
runs-on: ubuntu-24.04
|
||||
container:
|
||||
image: elixir:${{ matrix.elixir }}
|
||||
image: public.ecr.aws/docker/library/elixir:${{ matrix.elixir }}
|
||||
|
||||
steps:
|
||||
|
||||
@@ -287,10 +287,10 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
elixir: ['1.13', '1.14', '1.15', '1.16', '1.17']
|
||||
elixir: ['1.13', '1.14', '1.15', '1.16', '1.17', '1.18']
|
||||
runs-on: ubuntu-24.04
|
||||
container:
|
||||
image: elixir:${{ matrix.elixir }}
|
||||
image: public.ecr.aws/docker/library/elixir:${{ matrix.elixir }}
|
||||
|
||||
steps:
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -19,7 +19,7 @@
|
||||
"cwd": "."
|
||||
},
|
||||
{
|
||||
"name": "Relive",
|
||||
"name": "Relive (VSCode)",
|
||||
"type": "erlang",
|
||||
"request": "launch",
|
||||
"runinterminal": [
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
[ ! -f Makefile ] \
|
||||
&& ./autogen.sh \
|
||||
&& ./configure --with-rebar=rebar3 \
|
||||
&& make deps
|
||||
&& make
|
||||
|
||||
make relive
|
||||
|
||||
+130
@@ -1,3 +1,133 @@
|
||||
## Version 25.04
|
||||
|
||||
#### Security fixes
|
||||
- Fixes issue with handling of user provided occupant-id in messages and presences sent to muc room. Server was replacing
|
||||
just first instance of occupant-id with its own version, leaving other ones untouched. That would mean that depending
|
||||
on order in which clients send occupant-id, they could see value provided by sender, and that could be used to spoof
|
||||
as different sender.
|
||||
|
||||
#### Commands API
|
||||
- `kick_users`: New command to kick all logged users for a given host
|
||||
|
||||
#### Bugfixes
|
||||
- Fix issue with sql schema auto upgrade when using `sqlite` database
|
||||
- Fix problem with container update, that could ignore previous data stored in `mnesia` database
|
||||
- Revert limit of allowed characters in shared roster group names, that will again allow using symbols like `:`
|
||||
|
||||
## Version 25.03
|
||||
|
||||
#### Commands API
|
||||
- `ejabberdctl`: New option `CTL_OVER_HTTP` ([#4340](https://github.com/processone/ejabberd/issues/4340))
|
||||
- `ejabberd_web_admin`: Support commands with tuple arguments
|
||||
- `mod_adhoc_api`: New module to execute API Commands using Ad-Hoc Commands ([#4357](https://github.com/processone/ejabberd/issues/4357))
|
||||
- `mod_http_api`: Sort list elements in a command result
|
||||
- Show warning when registering command with an existing name
|
||||
- Fix commands unregistration
|
||||
- `change_room_option`: Add forgotten support to set `enable_hats` room option
|
||||
- `change_room_option`: Verify room option value before setting it ([#4337](https://github.com/processone/ejabberd/issues/4337))
|
||||
- `create_room_with_opts`: Recommend using `;` and `=` separators
|
||||
- `list_cluster_detailed`: Fix crash when a node is down
|
||||
- `mnesia_list_tables`: Allow using this internal command
|
||||
- `mnesia_table_change_storage`: Allow using this internal command
|
||||
- `status`: Separate command result with newline
|
||||
- `update_sql`: Fix updating tables created by ejabberd internally
|
||||
- `update_sql`: Fix MySQL support
|
||||
|
||||
#### Configuration
|
||||
- `acl`: Fix bug matching the acl `shared_group: NAME`
|
||||
- `define_keyword`: New option to define keywords ([#4350](https://github.com/processone/ejabberd/issues/4350))
|
||||
- `define_macro`: Add option to `globals()` because it's useless inside `host_config`
|
||||
- `ejabberd.yml.example`: Enable `mod_muc_occupantid` by default
|
||||
- Add support to use keywords in toplevel, listener and modules
|
||||
- Show warning also when deprecated listener option is set as disabled ([#4345](https://github.com/processone/ejabberd/issues/4345))
|
||||
|
||||
#### Container
|
||||
- Bump versions to Erlang/OTP 27.3 and Elixir 1.18.3
|
||||
- Add `ERL_FLAGS` to compile elixir on qemu cross-platform
|
||||
- Copy files to stable path, add ecs backwards compatibility
|
||||
- Fix warning about relative workdir
|
||||
- Improve entrypoint script: register account, or set random
|
||||
- Link path to Mnesia spool dir for backwards compatibility
|
||||
- Place `sockets/` outside `database/`
|
||||
- Use again direct METHOD, qemu got fixed ([#4280](https://github.com/processone/ejabberd/issues/4280))
|
||||
- `ejabberd.yml.example`: Copy main example configuration file
|
||||
- `ejabberd.yml.example`: Define and use macros in the default configuration file
|
||||
- `ejabberd.yml.example`: Enable `CTL_OVER_HTTP` by default
|
||||
- `ejabberd.yml.example`: Listen for webadmin in a port number lower than any other
|
||||
- `ejabberdapi`: Compile during build
|
||||
- `CONTAINER.md`: Include documentation for ecs container image
|
||||
|
||||
#### Core and Modules
|
||||
- `ejabberd_auth`: Add support for `auth_stored_password_types`
|
||||
- `ejabberd_router`: Don't rewrite "self-addressed" privileged IQs as results ([#4348](https://github.com/processone/ejabberd/issues/4348))
|
||||
- `misc`: Fix json version of `json_encode_with_kv_list` for nested kv lists ([#4338](https://github.com/processone/ejabberd/issues/4338))
|
||||
- OAuth: Fix crashes when oauth is feed with invalid jid ([#4355](https://github.com/processone/ejabberd/issues/4355))
|
||||
- PubSub: Bubble up db errors in `nodetree_tree_sql:set_node`
|
||||
- `mod_configure`: Add option `access` to let configure the access name
|
||||
- `mod_mix_pam`: Remove `Channels` roster group of mix channels ([#4297](https://github.com/processone/ejabberd/issues/4297))
|
||||
- `mod_muc`: Document MUC room option vcard_xupdate
|
||||
- `mod_privilege`: Accept non-privileged IQs from privileged components ([#4341](https://github.com/processone/ejabberd/issues/4341))
|
||||
- `mod_private`: Improve exception handling
|
||||
- `mod_private`: Don't warn on conversion errors
|
||||
- `mod_private`: Handle invalid PEP-native bookmarks
|
||||
- `mod_private`: Don't crash on invalid bookmarks
|
||||
- `mod_s2s_bidi`: Stop processing other handlers in s2s_in_handle_info ([#4344](https://github.com/processone/ejabberd/issues/4344))
|
||||
- `mod_s2s_bidi`: Fix issue with wrong namespace
|
||||
|
||||
#### Dependencies
|
||||
- `ex_doc`: Bump to 0.37.2
|
||||
- `stringprep`: Bump to 1.0.31
|
||||
- `provider_asn1`: Bump to 0.4.1
|
||||
- `xmpp` Bump to bring fix for ssdp hash calculation
|
||||
- `xmpp` Bump to get support for webchat_url ([#3041](https://github.com/processone/ejabberd/issues/3041))
|
||||
- `xmpp` Bump to get XEP-0317 Hats namespaces version 0.2.0
|
||||
- `xmpp` Bump to bring SSDP to XEP version 0.4
|
||||
- `yconf` Bump to support macro inside string
|
||||
|
||||
#### Development and Testing
|
||||
- `mix.exs`: Keep debug info when building `dev` release
|
||||
- `mix.exs`: The `ex_doc` dependency is only relevant for the `edoc` Mix environment
|
||||
- `ext_mod`: add `$libdir/include` to include path
|
||||
- `ext_mod`: fix greedy include path ([#4359](https://github.com/processone/ejabberd/issues/4359))
|
||||
- `gen_mod`: Support registering commands and `hook_subscribe` in `start/2` result
|
||||
- `c2s_handle_bind`: New event in `ejabberd_c2s` ([#4356](https://github.com/processone/ejabberd/issues/4356))
|
||||
- `muc_disco_info_extras`: New event `mod_muc_room` useful for `mod_muc_webchat_url` ([#3041](https://github.com/processone/ejabberd/issues/3041))
|
||||
- VSCode: Fix compiling support
|
||||
- Add tests for config features `define_macro` and `define_keyword`
|
||||
- Allow test to run using `ct_run`
|
||||
- Fixes to handle re-running test after `update_sql`
|
||||
- Uninstall `mod_example` when the tests has finished
|
||||
|
||||
#### Documentation
|
||||
- Add XEPs that are indirectly supported and required by XEP-0479
|
||||
- Document that XEP-0474 0.4.0 was recently upgraded
|
||||
- Don't use backtick quotes for ejabberd name
|
||||
- Fix values allowed in db_type of mod_auth_fast documentation
|
||||
- Reword explanation about ACL names and definitions
|
||||
- Update moved or broken URLs in documentation
|
||||
|
||||
#### Installers
|
||||
- Bump Erlang/OTP 27.3 and Elixir 1.18.3
|
||||
- Bump OpenSSL 3.4.1
|
||||
- Bump crosstool-NG 1.27.0
|
||||
- Fix building Termcap and Linux-PAM
|
||||
|
||||
#### Matrix Gateway
|
||||
- Preserve XMPP message IDs in Matrix rooms
|
||||
- Better Matrix room topic and room roles to MUC conversion, support room aliases in invites
|
||||
- Add `muc#user` element to presences and an initial empty subject
|
||||
- Fix `gen_iq_handler:remove_iq_handler` call
|
||||
- Properly handle IQ requests
|
||||
- Support Matrix room aliases
|
||||
- Fix handling of 3PI events
|
||||
|
||||
#### Unix Domain Socket
|
||||
- Add support for socket relative path
|
||||
- Use `/tmp` for temporary socket, as path is restricted to 107 chars
|
||||
- Handle unix socket when logging remote client
|
||||
- When stopping listener, delete Unix Domain Socket file
|
||||
- `get_auto_url` option: Don't build auto URL if port is unix domain socket ([#4345](https://github.com/processone/ejabberd/issues/4345))
|
||||
|
||||
## Version 24.12
|
||||
|
||||
#### Miscelanea
|
||||
|
||||
+3
-3
@@ -55,7 +55,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
[homepage]: https://www.contributor-covenant.org/
|
||||
[version]: https://www.contributor-covenant.org/version/1/4/
|
||||
|
||||
+401
-197
@@ -1,41 +1,44 @@
|
||||
|
||||
[](https://github.com/processone/ejabberd/tags)
|
||||
[](https://github.com/processone/ejabberd/pkgs/container/ejabberd)
|
||||
[](https://github.com/processone/ejabberd/pkgs/container/ejabberd)
|
||||
[](https://hub.docker.com/r/ejabberd/ecs/)
|
||||
|
||||
`ejabberd` Container Image
|
||||
==========================
|
||||
ejabberd Container Images
|
||||
=========================
|
||||
|
||||
[ejabberd][home] is an open-source,
|
||||
robust, scalable and extensible realtime platform built using [Erlang/OTP][erlang],
|
||||
that includes [XMPP][xmpp] Server, [MQTT][mqtt] Broker and [SIP][sip] Service.
|
||||
|
||||
[home]: https://ejabberd.im/
|
||||
[home]: https://www.ejabberd.im/
|
||||
[erlang]: https://www.erlang.org/
|
||||
[xmpp]: https://xmpp.org/
|
||||
[mqtt]: https://mqtt.org/
|
||||
[sip]: https://en.wikipedia.org/wiki/Session_Initiation_Protocol
|
||||
|
||||
This document explains how to use the `ejabberd` container image available in
|
||||
[ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd),
|
||||
built using the files in `.github/container/`.
|
||||
This image is based in Alpine 3.19, includes Erlang/OTP 26.2 and Elixir 1.16.1.
|
||||
This page documents those container images ([images comparison](#images-comparison)):
|
||||
|
||||
Alternatively, there is also the `ecs` container image available in
|
||||
[docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/),
|
||||
built using the
|
||||
[docker-ejabberd/ecs](https://github.com/processone/docker-ejabberd/tree/master/ecs)
|
||||
repository.
|
||||
Check the [differences between `ejabberd` and `ecs` images](https://github.com/processone/docker-ejabberd/blob/master/ecs/HUB-README.md#alternative-image-in-github).
|
||||
- [](https://github.com/processone/ejabberd/pkgs/container/ejabberd)
|
||||
published in [ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd),
|
||||
built using [ejabberd](https://github.com/processone/ejabberd/tree/master/.github/container) repository,
|
||||
both for stable ejabberd releases and the `master` branch, in x64 and arm64 architectures.
|
||||
|
||||
If you are using a Windows operating system, check the tutorials mentioned in
|
||||
[ejabberd Docs > Docker Image](https://docs.ejabberd.im/admin/install/container/#ejabberd-container-image).
|
||||
- [](https://hub.docker.com/r/ejabberd/ecs/)
|
||||
published in [docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/),
|
||||
built using [docker-ejabberd/ecs](https://github.com/processone/docker-ejabberd/tree/master/ecs) repository
|
||||
for ejabberd stable releases in x64 architectures.
|
||||
|
||||
For Microsoft Windows, see
|
||||
[Docker Desktop for Windows 10](https://www.process-one.net/blog/install-ejabberd-on-windows-10-using-docker-desktop/),
|
||||
and [Docker Toolbox for Windows 7](https://www.process-one.net/blog/install-ejabberd-on-windows-7-using-docker-toolbox/).
|
||||
|
||||
For Kubernetes Helm, see [help-ejabberd](https://github.com/sando38/helm-ejabberd).
|
||||
|
||||
|
||||
Start ejabberd
|
||||
--------------
|
||||
|
||||
### With default configuration
|
||||
### daemon
|
||||
|
||||
Start ejabberd in a new container:
|
||||
|
||||
@@ -46,22 +49,28 @@ docker run --name ejabberd -d -p 5222:5222 ghcr.io/processone/ejabberd
|
||||
That runs the container as a daemon,
|
||||
using ejabberd default configuration file and XMPP domain `localhost`.
|
||||
|
||||
Stop the running container:
|
||||
|
||||
```bash
|
||||
docker stop ejabberd
|
||||
```
|
||||
|
||||
Restart the stopped ejabberd container:
|
||||
|
||||
```bash
|
||||
docker restart ejabberd
|
||||
```
|
||||
|
||||
Stop the running container:
|
||||
|
||||
### Start with Erlang console attached
|
||||
```bash
|
||||
docker stop ejabberd
|
||||
```
|
||||
|
||||
Start ejabberd with an Erlang console attached using the `live` command:
|
||||
Remove the ejabberd container:
|
||||
|
||||
```bash
|
||||
docker rm ejabberd
|
||||
```
|
||||
|
||||
|
||||
### with Erlang console
|
||||
|
||||
Start ejabberd with an interactive Erlang console attached using the `live` command:
|
||||
|
||||
```bash
|
||||
docker run --name ejabberd -it -p 5222:5222 ghcr.io/processone/ejabberd live
|
||||
@@ -70,48 +79,67 @@ docker run --name ejabberd -it -p 5222:5222 ghcr.io/processone/ejabberd live
|
||||
That uses the default configuration file and XMPP domain `localhost`.
|
||||
|
||||
|
||||
### Start with your configuration and database
|
||||
### with your data
|
||||
|
||||
Pass a configuration file as a volume
|
||||
and share the local directory to store database:
|
||||
|
||||
```bash
|
||||
mkdir database
|
||||
chown ejabberd database
|
||||
mkdir conf && cp ejabberd.yml.example conf/ejabberd.yml
|
||||
|
||||
cp ejabberd.yml.example ejabberd.yml
|
||||
mkdir database && chown ejabberd database
|
||||
|
||||
docker run --name ejabberd -it \
|
||||
-v $(pwd)/ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml \
|
||||
-v $(pwd)/conf/ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml \
|
||||
-v $(pwd)/database:/opt/ejabberd/database \
|
||||
-p 5222:5222 ghcr.io/processone/ejabberd live
|
||||
```
|
||||
|
||||
Notice that ejabberd runs in the container with an account named `ejabberd`,
|
||||
Notice that ejabberd runs in the container with an account named `ejabberd`
|
||||
with UID 9000 and group `ejabberd` with GID 9000,
|
||||
and the volumes you mount must grant proper rights to that account.
|
||||
|
||||
|
||||
Next steps
|
||||
----------
|
||||
|
||||
### Register the administrator account
|
||||
### Register admin account
|
||||
|
||||
The default ejabberd configuration does not grant admin privileges
|
||||
to any account,
|
||||
you may want to register a new account in ejabberd
|
||||
and grant it admin rights.
|
||||
#### [](https://github.com/processone/ejabberd/pkgs/container/ejabberd) [:orange_circle:](#images-comparison)
|
||||
|
||||
Register an account using the `ejabberdctl` script:
|
||||
If you set the `REGISTER_ADMIN_PASSWORD` environment variable,
|
||||
an account is automatically registered with that password,
|
||||
and admin privileges are granted to it.
|
||||
The account created depends on what variables you have set:
|
||||
|
||||
- `EJABBERD_MACRO_ADMIN=juliet@example.org` -> `juliet@example.org`
|
||||
- `EJABBERD_MACRO_HOST=example.org` -> `admin@example.org`
|
||||
- None of those variables are set -> `admin@localhost`
|
||||
|
||||
The account registration is shown in the container log:
|
||||
|
||||
```
|
||||
:> ejabberdctl register admin example.org somePassw0rd
|
||||
User admin@example.org successfully registered
|
||||
```
|
||||
|
||||
Alternatively, you can register the account manually yourself
|
||||
and edit `conf/ejabberd.yml` and add the ACL as explained in
|
||||
[ejabberd Docs: Administration Account](https://docs.ejabberd.im/admin/install/next-steps/#administration-account).
|
||||
|
||||
---
|
||||
|
||||
#### [](https://hub.docker.com/r/ejabberd/ecs/)
|
||||
|
||||
The default ejabberd configuration has already granted admin privilege
|
||||
to an account that would be called `admin@localhost`,
|
||||
so you just need to register it, for example:
|
||||
|
||||
```bash
|
||||
docker exec -it ejabberd ejabberdctl register admin localhost passw0rd
|
||||
```
|
||||
|
||||
Then edit conf/ejabberd.yml and add the ACL as explained in
|
||||
[ejabberd Docs: Administration Account](https://docs.ejabberd.im/admin/install/next-steps/#administration-account)
|
||||
|
||||
|
||||
### Check ejabberd log files
|
||||
### Check ejabberd log
|
||||
|
||||
Check the content of the log files inside the container,
|
||||
even if you do not put it on a shared persistent drive:
|
||||
@@ -121,7 +149,7 @@ docker exec -it ejabberd tail -f logs/ejabberd.log
|
||||
```
|
||||
|
||||
|
||||
### Inspect the container files
|
||||
### Inspect container files
|
||||
|
||||
The container uses Alpine Linux. Start a shell inside the container:
|
||||
|
||||
@@ -130,7 +158,7 @@ docker exec -it ejabberd sh
|
||||
```
|
||||
|
||||
|
||||
### Open ejabberd debug console
|
||||
### Open debug console
|
||||
|
||||
Open an interactive debug Erlang console attached to a running ejabberd in a running container:
|
||||
|
||||
@@ -155,7 +183,7 @@ docker exec -it ejabberd vi conf/ejabberd.yml
|
||||
|
||||
and add this option:
|
||||
```yaml
|
||||
captcha_cmd: /opt/ejabberd-22.04/lib/captcha.sh
|
||||
captcha_cmd: "$HOME/bin/captcha.sh"
|
||||
```
|
||||
|
||||
Finally, reload the configuration file or restart the container:
|
||||
@@ -176,20 +204,22 @@ For more details about CAPTCHA options, please check the
|
||||
documentation section.
|
||||
|
||||
|
||||
Advanced Container Configuration
|
||||
--------------------------------
|
||||
Advanced
|
||||
--------
|
||||
|
||||
### Ports
|
||||
|
||||
This container image exposes the ports:
|
||||
The container image exposes several ports
|
||||
(check also [Docs: Firewall Settings](https://docs.ejabberd.im/admin/guide/security/#firewall-settings)):
|
||||
|
||||
- `5222`: The default port for XMPP clients.
|
||||
- `5269`: For XMPP federation. Only needed if you want to communicate with users on other servers.
|
||||
- `5280`: For admin interface.
|
||||
- `5280`: For admin interface (URL is `admin/`).
|
||||
- `1880`: For admin interface (URL is `/`, useful for [podman-desktop](https://podman-desktop.io/) and [docker-desktop](https://www.docker.com/products/docker-desktop/)) [:orange_circle:](#images-comparison)
|
||||
- `5443`: With encryption, used for admin interface, API, CAPTCHA, OAuth, Websockets and XMPP BOSH.
|
||||
- `1883`: Used for MQTT
|
||||
- `4369-4399`: EPMD and Erlang connectivity, used for `ejabberdctl` and clustering
|
||||
- `5210`: Erlang connectivity when `ERL_DIST_PORT` is set, alternative to EPMD
|
||||
- `5210`: Erlang connectivity when `ERL_DIST_PORT` is set, alternative to EPMD [:orange_circle:](#images-comparison)
|
||||
|
||||
|
||||
### Volumes
|
||||
@@ -206,11 +236,26 @@ You should back up or export the content of the directory to persistent storage
|
||||
- `/opt/ejabberd/logs/`: Directory containing log files
|
||||
- `/opt/ejabberd/upload/`: Directory containing uploaded files. This should also be backed up.
|
||||
|
||||
All these files are owned by `ejabberd` user inside the container.
|
||||
All these files are owned by an account named `ejabberd` with group `ejabberd` in the container.
|
||||
Its corresponding `UID:GID` is `9000:9000`.
|
||||
If you prefer bind mounts instead of volumes, then
|
||||
you need to map this to valid `UID:GID` on your host to get read/write access on
|
||||
mounted directories.
|
||||
|
||||
It's possible to install additional ejabberd modules using volumes,
|
||||
[this comment](https://github.com/processone/docker-ejabberd/issues/81#issuecomment-1036115146)
|
||||
explains how to install an additional module using docker-compose.
|
||||
If using Docker, try:
|
||||
```bash
|
||||
mkdir database
|
||||
sudo chown 9000:9000 database
|
||||
```
|
||||
|
||||
If using Podman, try:
|
||||
```bash
|
||||
mkdir database
|
||||
podman unshare chown 9000:9000 database
|
||||
```
|
||||
|
||||
It's possible to install additional ejabberd modules using volumes, check
|
||||
[this Docs tutorial](https://docs.ejabberd.im/developer/extending-ejabberd/modules/#your-module-in-ejabberd-modules-with-ejabberd-container).
|
||||
|
||||
|
||||
### Commands on start
|
||||
@@ -221,23 +266,29 @@ and reads `CTL_ON_START` every time the container is started.
|
||||
Those variables can contain one ejabberdctl command,
|
||||
or several commands separated with the blankspace and `;` characters.
|
||||
|
||||
By default failure of any of commands executed that way would
|
||||
abort start, this can be disabled by prefixing commands with `!`
|
||||
If any of those commands returns a failure, the container starting gets aborted.
|
||||
If there is a command with a result that can be ignored,
|
||||
prefix that command with `!`
|
||||
|
||||
Example usage (or check the [full example](#customized-example)):
|
||||
This example, registers an `admin@localhost` account when the container is first created.
|
||||
Everytime the container starts, it shows the list of registered accounts,
|
||||
checks that the admin account exists and password is valid,
|
||||
changes the password of an account if it exists (ignoring any failure),
|
||||
and shows the ejabberd starts (check also the [full example](#customized-example)):
|
||||
```yaml
|
||||
environment:
|
||||
- CTL_ON_CREATE=! register admin localhost asd
|
||||
- CTL_ON_CREATE=register admin localhost asd
|
||||
- CTL_ON_START=stats registeredusers ;
|
||||
check_password admin localhost asd ;
|
||||
! change_password bot123 localhost qqq ;
|
||||
status
|
||||
```
|
||||
|
||||
|
||||
### Macros in environment
|
||||
### Macros in environment [:high_brightness:](#images-comparison)
|
||||
|
||||
ejabberd reads `EJABBERD_MACRO_*` environment variables
|
||||
and uses them to define the `*`
|
||||
and uses them to define the corresponding
|
||||
[macros](https://docs.ejabberd.im/admin/configuration/file-format/#macros-in-configuration-file),
|
||||
overwriting the corresponding macro definition if it was set in the configuration file.
|
||||
This is supported since ejabberd 24.12.
|
||||
@@ -247,18 +298,61 @@ For example, if you configure this in `ejabberd.yml`:
|
||||
```yaml
|
||||
acl:
|
||||
admin:
|
||||
user: ADMINJID
|
||||
user: ADMIN
|
||||
```
|
||||
|
||||
now you can define the admin account JID using an environment variable:
|
||||
```yaml
|
||||
environment:
|
||||
- EJABBERD_MACRO_ADMINJID=admin@localhost
|
||||
- EJABBERD_MACRO_ADMIN=admin@localhost
|
||||
```
|
||||
|
||||
Check the [full example](#customized-example) for other example.
|
||||
|
||||
|
||||
### ejabberdapi
|
||||
|
||||
When the container is running (and thus ejabberd), you can exec commands inside the container
|
||||
using `ejabberdctl` or any other of the available interfaces, see
|
||||
[Understanding ejabberd "commands"](https://docs.ejabberd.im/developer/ejabberd-api/#understanding-ejabberd-commands)
|
||||
|
||||
Additionally, the container image includes the `ejabberdapi` executable.
|
||||
Please check the [ejabberd-api homepage](https://github.com/processone/ejabberd-api)
|
||||
for configuration and usage details.
|
||||
|
||||
For example, if you configure ejabberd like this:
|
||||
```yaml
|
||||
listen:
|
||||
-
|
||||
port: 5282
|
||||
module: ejabberd_http
|
||||
request_handlers:
|
||||
"/api": mod_http_api
|
||||
|
||||
acl:
|
||||
loopback:
|
||||
ip:
|
||||
- 127.0.0.0/8
|
||||
- ::1/128
|
||||
- ::FFFF:127.0.0.1/128
|
||||
|
||||
api_permissions:
|
||||
"admin access":
|
||||
who:
|
||||
access:
|
||||
allow:
|
||||
acl: loopback
|
||||
what:
|
||||
- "register"
|
||||
```
|
||||
|
||||
Then you could register new accounts with this query:
|
||||
|
||||
```bash
|
||||
docker exec -it ejabberd ejabberdapi register --endpoint=http://127.0.0.1:5282/ --jid=admin@localhost --password=passw0rd
|
||||
```
|
||||
|
||||
|
||||
### Clustering
|
||||
|
||||
When setting several containers to form a
|
||||
@@ -273,6 +367,8 @@ For this you can either:
|
||||
- edit `conf/ejabberdctl.cfg` and set variables `ERLANG_NODE` and `ERLANG_COOKIE`
|
||||
- set the environment variables `ERLANG_NODE_ARG` and `ERLANG_COOKIE`
|
||||
|
||||
---
|
||||
|
||||
Example to connect a local `ejabberdctl` to a containerized ejabberd:
|
||||
|
||||
1. When creating the container, export port 5210, and set `ERLANG_COOKIE`:
|
||||
@@ -282,7 +378,7 @@ Example to connect a local `ejabberdctl` to a containerized ejabberd:
|
||||
-p 5210:5210 -p 5222:5222 \
|
||||
ghcr.io/processone/ejabberd
|
||||
```
|
||||
2. Set `ERL_DIST_PORT=5210` in ejabberdctl.cfg of container and local ejabberd
|
||||
2. Set `ERL_DIST_PORT=5210` in `ejabberdctl.cfg` of container and local ejabberd
|
||||
3. Restart the container
|
||||
4. Now use `ejabberdctl` in your local ejabberd deployment
|
||||
|
||||
@@ -298,19 +394,175 @@ Example using environment variables (see full example [docker-compose.yml](https
|
||||
- ERLANG_COOKIE=dummycookie123
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Build a Container Image
|
||||
-----------------------
|
||||
Once you have the ejabberd nodes properly set and running,
|
||||
you can tell the secondary nodes to join the master node using the
|
||||
[`join_cluster`](https://docs.ejabberd.im/developer/ejabberd-api/admin-api/#join-cluster)
|
||||
API call.
|
||||
|
||||
This container image includes ejabberd as a standalone OTP release built using Elixir.
|
||||
That OTP release is configured with:
|
||||
Example using environment variables (see the full
|
||||
[`docker-compose.yml` clustering example](#clustering-example)):
|
||||
```yaml
|
||||
environment:
|
||||
- ERLANG_NODE_ARG=ejabberd@replica
|
||||
- ERLANG_COOKIE=dummycookie123
|
||||
- CTL_ON_CREATE=join_cluster ejabberd@main
|
||||
```
|
||||
|
||||
### Change Mnesia Node Name
|
||||
|
||||
To use the same Mnesia database in a container with a different hostname,
|
||||
it is necessary to change the old hostname stored in Mnesia.
|
||||
|
||||
This section is equivalent to the ejabberd Documentation
|
||||
[Change Computer Hostname](https://docs.ejabberd.im/admin/guide/managing/#change-computer-hostname),
|
||||
but particularized to containers that use this
|
||||
ecs container image from ejabberd 23.01 or older.
|
||||
|
||||
#### Setup Old Container
|
||||
|
||||
Let's assume a container running ejabberd 23.01 (or older) from
|
||||
this ecs container image, with the database directory binded
|
||||
and one registered account.
|
||||
This can be produced with:
|
||||
```bash
|
||||
OLDCONTAINER=ejaold
|
||||
NEWCONTAINER=ejanew
|
||||
|
||||
mkdir database
|
||||
sudo chown 9000:9000 database
|
||||
docker run -d --name $OLDCONTAINER -p 5222:5222 \
|
||||
-v $(pwd)/database:/opt/ejabberd/database \
|
||||
ghcr.io/processone/ejabberd:23.01
|
||||
docker exec -it $OLDCONTAINER ejabberdctl started
|
||||
docker exec -it $OLDCONTAINER ejabberdctl register user1 localhost somepass
|
||||
docker exec -it $OLDCONTAINER ejabberdctl registered_users localhost
|
||||
```
|
||||
|
||||
Methods to know the Erlang node name:
|
||||
```bash
|
||||
ls database/ | grep ejabberd@
|
||||
docker exec -it $OLDCONTAINER ejabberdctl status
|
||||
docker exec -it $OLDCONTAINER grep "started in the node" logs/ejabberd.log
|
||||
```
|
||||
|
||||
#### Change Mnesia Node
|
||||
|
||||
First of all let's store the Erlang node names and paths in variables.
|
||||
In this example they would be:
|
||||
```bash
|
||||
OLDCONTAINER=ejaold
|
||||
NEWCONTAINER=ejanew
|
||||
OLDNODE=ejabberd@95145ddee27c
|
||||
NEWNODE=ejabberd@localhost
|
||||
OLDFILE=/opt/ejabberd/database/old.backup
|
||||
NEWFILE=/opt/ejabberd/database/new.backup
|
||||
```
|
||||
|
||||
1. Start your old container that can still read the Mnesia database correctly.
|
||||
If you have the Mnesia spool files,
|
||||
but don't have access to the old container anymore, go to
|
||||
[Create Temporary Container](#create-temporary-container)
|
||||
and later come back here.
|
||||
|
||||
2. Generate a backup file and check it was created:
|
||||
```bash
|
||||
docker exec -it $OLDCONTAINER ejabberdctl backup $OLDFILE
|
||||
ls -l database/*.backup
|
||||
```
|
||||
|
||||
3. Stop ejabberd:
|
||||
```bash
|
||||
docker stop $OLDCONTAINER
|
||||
```
|
||||
|
||||
4. Create the new container. For example:
|
||||
```bash
|
||||
docker run \
|
||||
--name $NEWCONTAINER \
|
||||
-d \
|
||||
-p 5222:5222 \
|
||||
-v $(pwd)/database:/opt/ejabberd/database \
|
||||
ghcr.io/processone/ejabberd:latest
|
||||
```
|
||||
|
||||
5. Convert the backup file to new node name:
|
||||
```bash
|
||||
docker exec -it $NEWCONTAINER ejabberdctl mnesia_change_nodename $OLDNODE $NEWNODE $OLDFILE $NEWFILE
|
||||
```
|
||||
|
||||
6. Install the backup file as a fallback:
|
||||
```bash
|
||||
docker exec -it $NEWCONTAINER ejabberdctl install_fallback $NEWFILE
|
||||
```
|
||||
|
||||
7. Restart the container:
|
||||
```bash
|
||||
docker restart $NEWCONTAINER
|
||||
```
|
||||
|
||||
8. Check that the information of the old database is available.
|
||||
In this example, it should show that the account `user1` is registered:
|
||||
```bash
|
||||
docker exec -it $NEWCONTAINER ejabberdctl registered_users localhost
|
||||
```
|
||||
|
||||
9. When the new container is working perfectly with the converted Mnesia database,
|
||||
you may want to remove the unneeded files:
|
||||
the old container, the old Mnesia spool files, and the backup files.
|
||||
|
||||
#### Create Temporary Container
|
||||
|
||||
In case the old container that used the Mnesia database is not available anymore,
|
||||
a temporary container can be created just to read the Mnesia database
|
||||
and make a backup of it, as explained in the previous section.
|
||||
|
||||
This method uses `--hostname` command line argument for docker,
|
||||
and `ERLANG_NODE_ARG` environment variable for ejabberd.
|
||||
Their values must be the hostname of your old container
|
||||
and the Erlang node name of your old ejabberd node.
|
||||
To know the Erlang node name please check
|
||||
[Setup Old Container](#setup-old-container).
|
||||
|
||||
Command line example:
|
||||
```bash
|
||||
OLDHOST=${OLDNODE#*@}
|
||||
docker run \
|
||||
-d \
|
||||
--name $OLDCONTAINER \
|
||||
--hostname $OLDHOST \
|
||||
-p 5222:5222 \
|
||||
-v $(pwd)/database:/opt/ejabberd/database \
|
||||
-e ERLANG_NODE_ARG=$OLDNODE \
|
||||
ghcr.io/processone/ejabberd:latest
|
||||
```
|
||||
|
||||
Check the old database content is available:
|
||||
```bash
|
||||
docker exec -it $OLDCONTAINER ejabberdctl registered_users localhost
|
||||
```
|
||||
|
||||
Now that you have ejabberd running with access to the Mnesia database,
|
||||
you can continue with step 2 of previous section
|
||||
[Change Mnesia Node](#change-mnesia-node).
|
||||
|
||||
|
||||
Build Container Image
|
||||
----------------
|
||||
|
||||
The container image includes ejabberd as a standalone OTP release built using Elixir.
|
||||
|
||||
### Build `ejabberd` [](https://github.com/processone/ejabberd/pkgs/container/ejabberd)
|
||||
|
||||
The ejabberd Erlang/OTP release is configured with:
|
||||
|
||||
- `mix.exs`: Customize ejabberd release
|
||||
- `vars.config`: ejabberd compilation configuration options
|
||||
- `config/runtime.exs`: Customize ejabberd paths
|
||||
- `ejabberd.yml.template`: ejabberd default config file
|
||||
|
||||
### Direct build
|
||||
#### Direct build
|
||||
|
||||
Build ejabberd Community Server container image from ejabberd master git repository:
|
||||
|
||||
@@ -321,7 +573,7 @@ docker buildx build \
|
||||
.
|
||||
```
|
||||
|
||||
### Podman build
|
||||
#### Podman build
|
||||
|
||||
To build the image using Podman, please notice:
|
||||
|
||||
@@ -346,30 +598,27 @@ podman stop eja1
|
||||
podman run --name eja1 -it -e EJABBERD_BYPASS_WARNINGS=true -p 5222:5222 localhost/ejabberd live
|
||||
```
|
||||
|
||||
### Package build for `arm64`
|
||||
### Build `ecs` [](https://hub.docker.com/r/ejabberd/ecs/)
|
||||
|
||||
By default, `.github/container/Dockerfile` builds this container by directly compiling ejabberd,
|
||||
it is a fast and direct method.
|
||||
However, a problem with QEMU prevents building the container in QEMU using Erlang/OTP 25
|
||||
for the `arm64` architecture.
|
||||
The ejabberd Erlang/OTP release is configured with:
|
||||
|
||||
Providing `--build-arg METHOD=package` is an alternate method to build the container
|
||||
used by the Github Actions workflow that provides `amd64` and `arm64` container images.
|
||||
It first builds an ejabberd binary package, and later installs it in the image.
|
||||
That method avoids using QEMU, so it can build `arm64` container images, but is extremely
|
||||
slow the first time it's used, and consequently not recommended for general use.
|
||||
- `rel/config.exs`: Customize ejabberd release
|
||||
- `rel/dev.exs`: ejabberd environment configuration for development release
|
||||
- `rel/prod.exs`: ejabberd environment configuration for production release
|
||||
- `vars.config`: ejabberd compilation configuration options
|
||||
- `conf/ejabberd.yml`: ejabberd default config file
|
||||
|
||||
In this case, to build the ejabberd container image for arm64 architecture:
|
||||
Build ejabberd Community Server base image from ejabberd master on Github:
|
||||
|
||||
```bash
|
||||
docker buildx build \
|
||||
--build-arg METHOD=package \
|
||||
--platform linux/arm64 \
|
||||
-t personal/ejabberd:$VERSION \
|
||||
-f .github/container/Dockerfile \
|
||||
.
|
||||
docker build -t personal/ejabberd .
|
||||
```
|
||||
|
||||
Build ejabberd Community Server base image for a given ejabberd version:
|
||||
|
||||
```bash
|
||||
./build.sh 18.03
|
||||
```
|
||||
|
||||
Composer Examples
|
||||
-----------------
|
||||
@@ -430,26 +679,21 @@ stores the mnesia database in a local path,
|
||||
registers an account when it's created,
|
||||
and checks the number of registered accounts every time it's started.
|
||||
|
||||
Download or copy the ejabberd configuration file:
|
||||
Prepare an ejabberd configuration file:
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/processone/ejabberd/master/ejabberd.yml.example
|
||||
mv ejabberd.yml.example ejabberd.yml
|
||||
```
|
||||
|
||||
Use a macro in `ejabberd.yml` to set the served vhost, with `localhost` as default value:
|
||||
```yaml
|
||||
define_macro:
|
||||
XMPPHOST: localhost
|
||||
|
||||
hosts:
|
||||
- XMPPHOST
|
||||
mkdir conf && cp ejabberd.yml.example conf/ejabberd.yml
|
||||
```
|
||||
|
||||
Create the database directory and allow the container access to it:
|
||||
```bash
|
||||
mkdir database
|
||||
sudo chown 9000:9000 database
|
||||
```
|
||||
|
||||
- Docker:
|
||||
```bash
|
||||
mkdir database && sudo chown 9000:9000 database
|
||||
```
|
||||
- Podman:
|
||||
```bash
|
||||
mkdir database && podman unshare chown 9000:9000 database
|
||||
```
|
||||
|
||||
If using Docker, write this `docker-compose.yml` file
|
||||
and start it with `docker-compose up`:
|
||||
@@ -463,8 +707,9 @@ services:
|
||||
image: ghcr.io/processone/ejabberd
|
||||
container_name: ejabberd
|
||||
environment:
|
||||
- EJABBERD_MACRO_XMPPHOST=example.com
|
||||
- CTL_ON_CREATE=register admin example.com asd
|
||||
- EJABBERD_MACRO_HOST=example.com
|
||||
- EJABBERD_MACRO_ADMIN=admin@example.com
|
||||
- REGISTER_ADMIN_PASSWORD=somePassw0rd
|
||||
- CTL_ON_START=registered_users example.com ;
|
||||
status
|
||||
ports:
|
||||
@@ -473,7 +718,7 @@ services:
|
||||
- "5280:5280"
|
||||
- "5443:5443"
|
||||
volumes:
|
||||
- ./ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml:ro
|
||||
- ./conf/ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml:ro
|
||||
- ./database:/opt/ejabberd/database
|
||||
```
|
||||
|
||||
@@ -494,8 +739,12 @@ spec:
|
||||
- name: ejabberd
|
||||
image: ghcr.io/processone/ejabberd
|
||||
env:
|
||||
- name: CTL_ON_CREATE
|
||||
value: register admin example.com asd
|
||||
- name: EJABBERD_MACRO_HOST
|
||||
value: example.com
|
||||
- name: EJABBERD_MACRO_ADMIN
|
||||
value: admin@example.com
|
||||
- name: REGISTER_ADMIN_PASSWORD
|
||||
value: somePassw0rd
|
||||
- name: CTL_ON_START
|
||||
value: registered_users example.com ;
|
||||
status
|
||||
@@ -518,7 +767,7 @@ spec:
|
||||
volumes:
|
||||
- name: config
|
||||
hostPath:
|
||||
path: ./ejabberd.yml
|
||||
path: ./conf/ejabberd.yml
|
||||
type: File
|
||||
- name: db
|
||||
hostPath:
|
||||
@@ -551,11 +800,17 @@ services:
|
||||
|
||||
main:
|
||||
image: ghcr.io/processone/ejabberd
|
||||
container_name: ejabberd
|
||||
container_name: main
|
||||
environment:
|
||||
- ERLANG_NODE_ARG=ejabberd@main
|
||||
- ERLANG_COOKIE=dummycookie123
|
||||
- CTL_ON_CREATE=! register admin localhost asd
|
||||
healthcheck:
|
||||
test: netstat -nl | grep -q 5222
|
||||
start_period: 5s
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 120
|
||||
|
||||
replica:
|
||||
image: ghcr.io/processone/ejabberd
|
||||
@@ -654,92 +909,41 @@ spec:
|
||||
|
||||
```
|
||||
|
||||
Your configuration file should use those macros to allow each ejabberd node
|
||||
use different listening port numbers:
|
||||
|
||||
```diff
|
||||
diff --git a/ejabberd.yml.example b/ejabberd.yml.example
|
||||
index 39e423a64..6e875b48f 100644
|
||||
--- a/ejabberd.yml.example
|
||||
+++ b/ejabberd.yml.example
|
||||
@@ -24,9 +24,19 @@ loglevel: info
|
||||
# - /etc/letsencrypt/live/domain.tld/fullchain.pem
|
||||
# - /etc/letsencrypt/live/domain.tld/privkey.pem
|
||||
|
||||
+define_macro:
|
||||
+ PORT_C2S: 5222
|
||||
+ PORT_C2S_TLS: 5223
|
||||
+ PORT_S2S: 5269
|
||||
+ PORT_HTTP_TLS: 5443
|
||||
+ PORT_HTTP: 5280
|
||||
+ PORT_STUN: 5478
|
||||
+ PORT_MQTT: 1883
|
||||
+ PORT_PROXY65: 7777
|
||||
+
|
||||
listen:
|
||||
-
|
||||
- port: 5222
|
||||
+ port: PORT_C2S
|
||||
ip: "::"
|
||||
module: ejabberd_c2s
|
||||
max_stanza_size: 262144
|
||||
@@ -34,7 +44,7 @@ listen:
|
||||
access: c2s
|
||||
starttls_required: true
|
||||
-
|
||||
- port: 5223
|
||||
+ port: PORT_C2S_TLS
|
||||
ip: "::"
|
||||
module: ejabberd_c2s
|
||||
max_stanza_size: 262144
|
||||
@@ -42,13 +52,13 @@ listen:
|
||||
access: c2s
|
||||
tls: true
|
||||
-
|
||||
- port: 5269
|
||||
+ port: PORT_S2S
|
||||
ip: "::"
|
||||
module: ejabberd_s2s_in
|
||||
max_stanza_size: 524288
|
||||
shaper: s2s_shaper
|
||||
-
|
||||
- port: 5443
|
||||
+ port: PORT_HTTP_TLS
|
||||
ip: "::"
|
||||
module: ejabberd_http
|
||||
tls: true
|
||||
@@ -60,14 +70,14 @@ listen:
|
||||
/upload: mod_http_upload
|
||||
/ws: ejabberd_http_ws
|
||||
-
|
||||
- port: 5280
|
||||
+ port: PORT_HTTP
|
||||
ip: "::"
|
||||
module: ejabberd_http
|
||||
request_handlers:
|
||||
/admin: ejabberd_web_admin
|
||||
/.well-known/acme-challenge: ejabberd_acme
|
||||
-
|
||||
- port: 5478
|
||||
+ port: PORT_STUN
|
||||
ip: "::"
|
||||
transport: udp
|
||||
module: ejabberd_stun
|
||||
@@ -77,7 +87,7 @@ listen:
|
||||
## The server's public IPv6 address:
|
||||
# turn_ipv6_address: "2001:db8::3"
|
||||
-
|
||||
- port: 1883
|
||||
+ port: PORT_MQTT
|
||||
ip: "::"
|
||||
module: mod_mqtt
|
||||
backlog: 1000
|
||||
@@ -207,6 +217,7 @@ modules:
|
||||
mod_proxy65:
|
||||
access: local
|
||||
max_connections: 5
|
||||
+ port: PORT_PROXY65
|
||||
mod_pubsub:
|
||||
access_createnode: pubsub_createnode
|
||||
plugins:
|
||||
```
|
||||
Images Comparison
|
||||
-----------------
|
||||
|
||||
Let's summarize the differences between both container images. Legend:
|
||||
|
||||
- :sparkle: is the recommended alternative
|
||||
- :orange_circle: added in the latest release (ejabberd 25.03)
|
||||
- :high_brightness: added in the previous release (ejabberd 24.12)
|
||||
- :low_brightness: added in the pre-previous release (ejabberd 24.10)
|
||||
|
||||
| | [](https://github.com/processone/ejabberd/pkgs/container/ejabberd) | [](https://hub.docker.com/r/ejabberd/ecs/) |
|
||||
|:----------------------|:------------------|:-----------------------|
|
||||
| Source code | [ejabberd/.github/container](https://github.com/processone/ejabberd/tree/master/.github/container) | [docker-ejabberd/ecs](https://github.com/processone/docker-ejabberd/tree/master/ecs) |
|
||||
| Generated by | [container.yml](https://github.com/processone/ejabberd/blob/master/.github/workflows/container.yml) | [tests.yml](https://github.com/processone/docker-ejabberd/blob/master/.github/workflows/tests.yml) |
|
||||
| Built for | stable releases <br /> `master` branch | stable releases <br /> [`master` branch zip](https://github.com/processone/docker-ejabberd/actions/workflows/tests.yml) |
|
||||
| Architectures | `linux/amd64` <br /> `linux/arm64` | `linux/amd64` |
|
||||
| Software | Erlang/OTP 27.3.2-alpine <br /> Elixir 1.18.3 | Alpine 3.19 <br /> Erlang/OTP 26.2 <br /> Elixir 1.15.7 |
|
||||
| Published in | [ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd) | [docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/) <br /> [ghcr.io/processone/ecs](https://github.com/processone/docker-ejabberd/pkgs/container/ecs) |
|
||||
| :black_square_button: **Additional content** |
|
||||
| [ejabberd-contrib](https://docs.ejabberd.im/admin/guide/modules/#ejabberd-contrib) | included | not included |
|
||||
| [ejabberdapi](#ejabberdapi) | included :orange_circle: | included |
|
||||
| :black_square_button: **Ports** |
|
||||
| [1880](#ports) for WebAdmin | yes :orange_circle: | yes :orange_circle: |
|
||||
| [5210](#ports) for `ERL_DIST_PORT` | supported | supported :orange_circle: |
|
||||
| :black_square_button: **Paths** |
|
||||
| `$HOME` | `/opt/ejabberd/` | `/home/ejabberd/` |
|
||||
| User data | `$HOME` :sparkle: <br /> `/home/ejabberd/` :orange_circle: | `$HOME` <br /> `/opt/ejabberd/` :sparkle: :low_brightness: |
|
||||
| `ejabberdctl` | `ejabberdctl` :sparkle: <br /> `bin/ejabberdctl` :orange_circle: | `bin/ejabberdctl` <br /> `ejabberdctl` :sparkle: :low_brightness: |
|
||||
| [`captcha.sh`](#captcha) | `$HOME/bin/captcha.sh` :orange_circle: | `$HOME/bin/captcha.sh` :orange_circle: |
|
||||
| `*.sql` files | `$HOME/sql/*.sql` :sparkle: :orange_circle: <br /> `$HOME/database/*.sql` :orange_circle: | `$HOME/database/*.sql` <br /> `$HOME/sql/*.sql` :sparkle: :orange_circle: |
|
||||
| Mnesia spool files | `$HOME/database/` :sparkle: <br /> `$HOME/database/NODENAME/` :orange_circle: | `$HOME/database/NODENAME/` <br /> `$HOME/database/` :sparkle: :orange_circle: |
|
||||
| :black_square_button: **Variables** |
|
||||
| [`EJABBERD_MACRO_*`](#macros-in-environment) | supported :high_brightness: | supported :high_brightness: |
|
||||
| Macros used in `ejabberd.yml` | yes :orange_circle: | yes :orange_circle: |
|
||||
| [`EJABBERD_MACRO_ADMIN`](#register-admin-account) | Grant admin rights :orange_circle: <br /> (default `admin@localhost`) <br /> | Hardcoded `admin@localhost` |
|
||||
| [`REGISTER_ADMIN_PASSWORD`](#register-admin-account) | Register admin account :orange_circle: | unsupported |
|
||||
| `CTL_OVER_HTTP` | enabled :orange_circle: | unsupported |
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ gives us the option to relicense the code with a more permissive license in the
|
||||
|
||||
[coc]: https://github.com/processone/ejabberd/blob/master/CODE_OF_CONDUCT.md
|
||||
[stackoverflow]: https://stackoverflow.com/questions/tagged/ejabberd?sort=newest
|
||||
[list]: https://lists.jabber.ru/mailman/listinfo/ejabberd
|
||||
[list]: https://web.archive.org/web/20230319174915/http://lists.jabber.ru/mailman/listinfo/ejabberd
|
||||
[muc]: xmpp:ejabberd@conference.process-one.net
|
||||
[github]: https://github.com/processone/ejabberd
|
||||
[github-issues]: https://github.com/processone/ejabberd/issues
|
||||
|
||||
@@ -104,7 +104,7 @@ There are several places to get in touch with other ejabberd developers and admi
|
||||
License
|
||||
-------
|
||||
|
||||
- `ejabberd` is released under the __GNU General Public License v2__ (see [COPYING](COPYING))
|
||||
- ejabberd is released under the __GNU General Public License v2__ (see [COPYING](COPYING))
|
||||
- [ejabberd translations](https://github.com/processone/ejabberd-po/) under __MIT License__.
|
||||
|
||||
[discussions]: https://github.com/processone/ejabberd/discussions
|
||||
@@ -116,7 +116,7 @@ License
|
||||
[fluux]: https://fluux.io/
|
||||
[homebrew]: https://docs.ejabberd.im/admin/install/homebrew/
|
||||
[hubecs]: https://hub.docker.com/r/ejabberd/ecs/
|
||||
[im]: https://ejabberd.im/
|
||||
[im]: https://www.ejabberd.im/
|
||||
[issues]: https://github.com/processone/ejabberd/issues
|
||||
[localization]: https://docs.ejabberd.im/developer/extending-ejabberd/localization/
|
||||
[mqtt]: https://mqtt.org/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.59)
|
||||
AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 24.12` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
|
||||
AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 25.04` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
|
||||
REQUIRE_ERLANG_MIN="9.0.5 (Erlang/OTP 20.0)"
|
||||
REQUIRE_ERLANG_MAX="100.0.0 (No Max)"
|
||||
|
||||
|
||||
+35
-8
@@ -134,6 +134,15 @@
|
||||
<xmpp:note>mod_muc</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0048.html"/>
|
||||
<xmpp:version>1.2</xmpp:version>
|
||||
<xmpp:since>0.5.0</xmpp:since>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:note>mod_pubsub</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0049.html"/>
|
||||
@@ -476,6 +485,15 @@
|
||||
<xmpp:note>mod_s2s_dialback</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0223.html"/>
|
||||
<xmpp:version>1.1.1</xmpp:version>
|
||||
<xmpp:since>2.0.0</xmpp:since>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:note>mod_pubsub</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0227.html"/>
|
||||
@@ -512,6 +530,15 @@
|
||||
<xmpp:note>mod_pubsub</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0249.html"/>
|
||||
<xmpp:version>1.2</xmpp:version>
|
||||
<xmpp:since>0.5.0</xmpp:since>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:note>mod_muc</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0279.html"/>
|
||||
@@ -524,7 +551,7 @@
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0280.html"/>
|
||||
<xmpp:version>0.13.2</xmpp:version>
|
||||
<xmpp:version>1.0.1</xmpp:version>
|
||||
<xmpp:since>13.06</xmpp:since>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:note>mod_carboncopy</xmpp:note>
|
||||
@@ -551,10 +578,10 @@
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0317.html"/>
|
||||
<xmpp:version>0.1</xmpp:version>
|
||||
<xmpp:version>0.2.0</xmpp:version>
|
||||
<xmpp:since>21.12</xmpp:since>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:note>mod_muc_room, conversejs/prosody compatible</xmpp:note>
|
||||
<xmpp:note>mod_muc_room, 0.2.0 since 25.03</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
@@ -731,10 +758,10 @@
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0424.html"/>
|
||||
<xmpp:version>0.4.0</xmpp:version>
|
||||
<xmpp:version>0.4.2</xmpp:version>
|
||||
<xmpp:since>24.02</xmpp:since>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:note></xmpp:note>
|
||||
<xmpp:status>partial</xmpp:status>
|
||||
<xmpp:note>mod_mam, Tombstones not implemented</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
@@ -767,10 +794,10 @@
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0474.html"/>
|
||||
<xmpp:version>0.3.0</xmpp:version>
|
||||
<xmpp:version>0.4.0</xmpp:version>
|
||||
<xmpp:since>24.02</xmpp:since>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:note></xmpp:note>
|
||||
<xmpp:note>, 0.4.0 since 25.03</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
|
||||
@@ -118,7 +118,12 @@ api_permissions:
|
||||
from: ejabberd_web_admin
|
||||
who: admin
|
||||
what: "*"
|
||||
"admin access":
|
||||
"adhoc commands":
|
||||
from: mod_adhoc_api
|
||||
who: admin
|
||||
what: "*"
|
||||
"http access":
|
||||
from: mod_http_api
|
||||
who:
|
||||
access:
|
||||
allow:
|
||||
@@ -159,6 +164,7 @@ shaper_rules:
|
||||
|
||||
modules:
|
||||
mod_adhoc: {}
|
||||
mod_adhoc_api: {}
|
||||
mod_admin_extra: {}
|
||||
mod_announce:
|
||||
access: announce
|
||||
@@ -199,6 +205,7 @@ modules:
|
||||
default_room_options:
|
||||
mam: true
|
||||
mod_muc_admin: {}
|
||||
mod_muc_occupantid: {}
|
||||
mod_offline:
|
||||
access_max_user_messages: max_user_offline_messages
|
||||
mod_ping: {}
|
||||
|
||||
@@ -198,6 +198,17 @@
|
||||
#
|
||||
#CONTRIB_MODULES_CONF_DIR=/etc/ejabberd/modules
|
||||
|
||||
#.
|
||||
#' CTL_OVER_HTTP: Path to ejabberdctl HTTP listener socket
|
||||
#
|
||||
# To speedup ejabberdctl execution time for ejabberd commands,
|
||||
# you can setup an ejabberd_http listener with ejabberd_ctl handling requests,
|
||||
# listening in a unix domain socket.
|
||||
#
|
||||
# Default: disabled
|
||||
#
|
||||
#CTL_OVER_HTTP=sockets/ctl_over_http.sock
|
||||
|
||||
#.
|
||||
#'
|
||||
# vim: foldmarker=#',#. foldmethod=marker:
|
||||
|
||||
+57
-12
@@ -71,6 +71,10 @@ done
|
||||
: "${SPOOL_DIR:="{{spool_dir}}"}"
|
||||
: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
|
||||
|
||||
# backward support for old mnesia spool dir path
|
||||
: "${SPOOL_DIR_OLD:="$SPOOL_DIR/$ERLANG_NODE"}"
|
||||
[ -r "$SPOOL_DIR_OLD/schema.DAT" ] && [ ! -r "$SPOOL_DIR/schema.DAT" ] && SPOOL_DIR="$SPOOL_DIR_OLD"
|
||||
|
||||
# define erl parameters
|
||||
ERLANG_OPTS="+K $POLL +P $ERL_PROCESSES $ERL_OPTIONS"
|
||||
if [ -n "$FIREWALL_WINDOW" ] ; then
|
||||
@@ -179,7 +183,9 @@ livewarning()
|
||||
echo "Please be extremely cautious with your actions,"
|
||||
echo "and exit immediately if you are not completely sure."
|
||||
echo ""
|
||||
echo "To exit and detach this shell from ejabberd, press:"
|
||||
echo "To stop ejabberd gracefully:"
|
||||
echo " ejabberd:stop()."
|
||||
echo "To quit erlang immediately, press:"
|
||||
echo " control+g and then q"
|
||||
echo ""
|
||||
echo "--------------------------------------------------------------------"
|
||||
@@ -253,7 +259,7 @@ help()
|
||||
|
||||
# dynamic node name helper
|
||||
uid() {
|
||||
ERTSVERSION="$("$ERL" -version 2>&1 | sed 's|.*\([0-9][0-9]\).*|\1|g')"
|
||||
ERTSVERSION="$("$ERL" -version 2>&1 | sed 's|.* \([0-9]*[0-9]\).*|\1|g')"
|
||||
if [ $ERTSVERSION -lt 11 ] ; then # otp 23.0 includes erts 11.0
|
||||
# Erlang/OTP lower than 23, which doesn's support dynamic node code
|
||||
N=1
|
||||
@@ -332,6 +338,54 @@ wait_status()
|
||||
[ $timeout -gt 0 ]
|
||||
}
|
||||
|
||||
exec_other_command()
|
||||
{
|
||||
if [ -z "$CTL_OVER_HTTP" ] || [ ! -S "$CTL_OVER_HTTP" ] \
|
||||
|| [ ! -x "$(command -v curl)" ] || [ -z "$1" ] || [ "$1" = "help" ] \
|
||||
|| [ "$1" = "mnesia_info_ctl" ]|| [ "$1" = "print_sql_schema" ] ; then
|
||||
exec_erl "$(uid ctl)" -hidden -noinput \
|
||||
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
|
||||
-s ejabberd_ctl \
|
||||
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
|
||||
result=$?
|
||||
case $result in
|
||||
3) help;;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
else
|
||||
exec_ctl_over_http_socket "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
exec_ctl_over_http_socket()
|
||||
{
|
||||
COMMAND=${1}
|
||||
CARGS=""
|
||||
while [ $# -gt 0 ]; do
|
||||
[ -z "$CARGS" ] && CARGS="[" || CARGS="${CARGS}, "
|
||||
CARGS="${CARGS}\"$1\""
|
||||
shift
|
||||
done
|
||||
CARGS="${CARGS}]"
|
||||
TEMPHEADERS=temp-headers.log
|
||||
curl \
|
||||
--unix-socket ${CTL_OVER_HTTP} \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "Accept: application/json" \
|
||||
--data "${CARGS}" \
|
||||
--dump-header ${TEMPHEADERS} \
|
||||
--no-progress-meter \
|
||||
"http://localhost/ctl/${COMMAND}"
|
||||
result=$(sed -n 's/.*status-code: \([0-9]*\).*/\1/p' < $TEMPHEADERS)
|
||||
rm ${TEMPHEADERS}
|
||||
case $result in
|
||||
2|3) exec_other_command help ${COMMAND};;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
}
|
||||
|
||||
# ensure we can change current directory to SPOOL_DIR
|
||||
[ -d "$SPOOL_DIR" ] || exec_cmd mkdir -p "$SPOOL_DIR"
|
||||
cd "$SPOOL_DIR" || {
|
||||
@@ -400,15 +454,6 @@ case $1 in
|
||||
;;
|
||||
*)
|
||||
set_dist_client
|
||||
exec_erl "$(uid ctl)" -hidden -noinput \
|
||||
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
|
||||
-s ejabberd_ctl \
|
||||
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
|
||||
result=$?
|
||||
case $result in
|
||||
2|3) help;;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
exec_other_command "$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -18,5 +18,5 @@
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-record(passwd, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$1',
|
||||
-record(passwd, {us = {<<"">>, <<"">>} :: {binary(), binary()} | {binary(), binary(), atom()} | '$1',
|
||||
password = <<"">> :: binary() | scram() | '_'}).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%%% RFC 1928 constants.
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% ejabberd, Copyright (C) 2017-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2017-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% @copyright (C) 2002-2024 ProcessOne, SARL. All Rights Reserved.
|
||||
%%% @copyright (C) 2002-2025 ProcessOne, SARL. All Rights Reserved.
|
||||
%%%
|
||||
%%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%%% you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+344
-57
@@ -2,12 +2,12 @@
|
||||
.\" Title: ejabberd.yml
|
||||
.\" Author: [see the "AUTHOR" section]
|
||||
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
|
||||
.\" Date: 12/17/2024
|
||||
.\" Date: 04/16/2025
|
||||
.\" Manual: \ \&
|
||||
.\" Source: \ \&
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "EJABBERD\&.YML" "5" "12/17/2024" "\ \&" "\ \&"
|
||||
.TH "EJABBERD\&.YML" "5" "04/16/2025" "\ \&" "\ \&"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
@@ -82,14 +82,14 @@ All options can be changed in runtime by running \fIejabberdctl reload\-config\f
|
||||
.sp
|
||||
Some options can be specified for particular virtual host(s) only using \fIhost_config\fR or \fIappend_host_config\fR options\&. Such options are called \fIlocal\fR\&. Examples are \fImodules\fR, \fIauth_method\fR and \fIdefault_db\fR\&. The options that cannot be defined per virtual host are called \fIglobal\fR\&. Examples are \fIloglevel\fR, \fIcertfiles\fR and \fIlisten\fR\&. It is a configuration mistake to put \fIglobal\fR options under \fIhost_config\fR or \fIappend_host_config\fR section \- ejabberd will refuse to load such configuration\&.
|
||||
.sp
|
||||
It is not recommended to write ejabberd\&.yml from scratch\&. Instead it is better to start from "default" configuration file available at https://github\&.com/processone/ejabberd/blob/24\&.12/ejabberd\&.yml\&.example\&. Once you get ejabberd running you can start changing configuration options to meet your requirements\&.
|
||||
It is not recommended to write ejabberd\&.yml from scratch\&. Instead it is better to start from "default" configuration file available at https://github\&.com/processone/ejabberd/blob/25\&.04/ejabberd\&.yml\&.example\&. Once you get ejabberd running you can start changing configuration options to meet your requirements\&.
|
||||
.sp
|
||||
Note that this document is intended to provide comprehensive description of all configuration options that can be consulted to understand the meaning of a particular option, its format and possible values\&. It will be quite hard to understand how to configure ejabberd by reading this document only \- for this purpose the reader is recommended to read online Configuration Guide available at https://docs\&.ejabberd\&.im/admin/configuration\&.
|
||||
.SH "TOP LEVEL OPTIONS"
|
||||
.sp
|
||||
This section describes top level options of ejabberd 24\&.12\&. The options that changed in this version are marked with 🟤\&.
|
||||
This section describes top level options of ejabberd 25\&.04\&. The options that changed in this version are marked with 🟤\&.
|
||||
.PP
|
||||
\fBaccess_rules\fR: \fI{AccessName: {allow|deny: ACLRules|ACLName}}\fR
|
||||
\fBaccess_rules\fR: \fI{AccessName: {allow|deny: ACLName|ACLDefinition}}\fR
|
||||
.RS 4
|
||||
This option defines
|
||||
\fIbasic\&.md#access\-rules|Access Rules\fR\&. Each access rule is assigned a name that can be referenced from other parts of the configuration file (mostly from
|
||||
@@ -305,7 +305,7 @@ acme:
|
||||
\fBallow_contrib_modules\fR: \fItrue | false\fR
|
||||
.RS 4
|
||||
Whether to allow installation of third\-party modules or not\&. See
|
||||
\fI\&.\&./\&.\&./developer/extending\-ejabberd/modules\&.md#ejabberd\-contrib|ejabberd\-contrib\fR
|
||||
\fI\&.\&./\&.\&./admin/guide/modules\&.md#ejabberd\-contrib|ejabberd\-contrib\fR
|
||||
documentation section\&. The default value is
|
||||
\fItrue\fR\&.
|
||||
.RE
|
||||
@@ -423,7 +423,7 @@ methods to use\&. If several methods are defined, authentication is considered s
|
||||
This is used by the contributed module
|
||||
\fIejabberd_auth_http\fR
|
||||
that can be installed from the
|
||||
ejabberd\-contrib
|
||||
\fI\&.\&./\&.\&./admin/guide/modules\&.md#ejabberd\-contrib|ejabberd\-contrib\fR
|
||||
Git repository\&. Please refer to that module\(cqs README file for details\&.
|
||||
.RE
|
||||
.PP
|
||||
@@ -469,6 +469,17 @@ format\&. You shouldn\(cqt change this if you already have passwords generated w
|
||||
\fIsha\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBauth_stored_password_types\fR: \fI[plain | scram_sha1 | scram_sha256 | scram_sha512]\fR
|
||||
.RS 4
|
||||
\fINote\fR
|
||||
about this option: added in 25\&.03\&. List of password types that should be stored simultaneously for each user in database\&. When the user sets the account password, database will be updated to store the password in formats compatible with each type listed here\&. This can be used to migrate user passwords to a more secure format\&. If this option if set, it will override values set in
|
||||
\fIauth_scram_hash\fR
|
||||
and
|
||||
\fIauth_password_format\fR
|
||||
options\&. The default value is
|
||||
[]\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBauth_use_cache\fR: \fItrue | false\fR
|
||||
.RS 4
|
||||
Same as
|
||||
@@ -587,11 +598,11 @@ A maximum number of items (not memory!) in cache\&. The rule of thumb, for all t
|
||||
\fINote\fR
|
||||
about this option: improved in 23\&.01\&. Full path to a script that generates
|
||||
\fIbasic\&.md#captcha|CAPTCHA\fR
|
||||
images\&.
|
||||
images\&. The keyword
|
||||
\fI@VERSION@\fR
|
||||
is replaced with ejabberd version number in
|
||||
\fIXX\&.YY\fR
|
||||
format\&.
|
||||
format\&. The keyword
|
||||
\fI@SEMVER@\fR
|
||||
is replaced with ejabberd version number in semver format when compiled with Elixir\(cqs mix, or XX\&.YY format otherwise\&. Alternatively, it can be the name of a module that implements ejabberd CAPTCHA support\&. There is no default value: when this option is not set, CAPTCHA functionality is completely disabled\&.
|
||||
.sp
|
||||
@@ -696,14 +707,38 @@ Default volatile (in\-memory) storage for ejabberd\&. Modules and other componen
|
||||
\fImnesia\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBdefine_macro\fR: \fI{MacroName: MacroValue}\fR
|
||||
\fBdefine_keyword\fR: \fI{NAME: Value}\fR
|
||||
.RS 4
|
||||
Defines a
|
||||
\fI\&.\&./configuration/file\-format\&.md#macros\-in\-configuration\-file|macro\fR\&. The value can be any valid arbitrary YAML value\&. For convenience, it\(cqs recommended to define a
|
||||
\fIMacroName\fR
|
||||
in capital letters\&. Duplicated macros are not allowed\&. Macros are processed after additional configuration files have been included, so it is possible to use macros that are defined in configuration files included before the usage\&. It is possible to use a
|
||||
\fIMacroValue\fR
|
||||
in the definition of another macro\&.
|
||||
\fINote\fR
|
||||
about this option: added in 25\&.03\&. Allows to define configuration
|
||||
\fI\&.\&./configuration/file\-format\&.md#macros\-and\-keywords|keywords\fR\&.
|
||||
.sp
|
||||
\fBExample\fR:
|
||||
.sp
|
||||
.if n \{\
|
||||
.RS 4
|
||||
.\}
|
||||
.nf
|
||||
define_keyword:
|
||||
SQL_USERNAME: "eja\&.global"
|
||||
|
||||
host_config:
|
||||
localhost:
|
||||
define_keyword:
|
||||
SQL_USERNAME: "eja\&.localhost"
|
||||
|
||||
sql_username: "prefix\&.@SQL_USERNAME@"
|
||||
.fi
|
||||
.if n \{\
|
||||
.RE
|
||||
.\}
|
||||
.RE
|
||||
.PP
|
||||
\fBdefine_macro\fR: \fI{NAME: Value}\fR
|
||||
.RS 4
|
||||
\fINote\fR
|
||||
about this option: improved in 25\&.03\&. Allows to define configuration
|
||||
\fI\&.\&./configuration/file\-format\&.md#macros\-and\-keywords|macros\fR\&.
|
||||
.sp
|
||||
\fBExample\fR:
|
||||
.sp
|
||||
@@ -911,9 +946,7 @@ host_config:
|
||||
.RS 4
|
||||
List of one or more
|
||||
\fI\&.\&./configuration/basic\&.md#host\-names|host names\fR
|
||||
(or domains) that
|
||||
\fIejabberd\fR
|
||||
will serve\&. This is a
|
||||
(or domains) that ejabberd will serve\&. This is a
|
||||
\fBmandatory\fR
|
||||
option\&.
|
||||
.RE
|
||||
@@ -946,7 +979,7 @@ Disallows the usage of those options in the included file
|
||||
.RS 4
|
||||
\fINote\fR
|
||||
about this option: added in 23\&.10\&. Modules to install from
|
||||
\fI\&.\&./\&.\&./developer/extending\-ejabberd/modules\&.md#ejabberd\-contrib|ejabberd\-contrib\fR
|
||||
\fI\&.\&./\&.\&./admin/guide/modules\&.md#ejabberd\-contrib|ejabberd\-contrib\fR
|
||||
at start time\&. The default value is an empty list of modules:
|
||||
\fI[]\fR\&.
|
||||
.RE
|
||||
@@ -1008,10 +1041,23 @@ Whether to dereference aliases or not\&. The default value is
|
||||
\fBldap_dn_filter\fR: \fI{Filter: FilterAttrs}\fR
|
||||
.RS 4
|
||||
This filter is applied on the results returned by the main filter\&. The filter performs an additional LDAP lookup to make the complete result\&. This is useful when you are unable to define all filter rules in
|
||||
\fIldap_filter\fR\&. You can define "%u", "%d", "%s" and "%D" pattern variables in
|
||||
\fIFilter\fR: "%u" is replaced by a user\(cqs part of the JID, "%d" is replaced by the corresponding domain (virtual host), all "%s" variables are consecutively replaced by values from the attributes in
|
||||
\fIldap_filter\fR\&. You can define
|
||||
\fI"%u"\fR,
|
||||
\fI"%d"\fR,
|
||||
\fI"%s"\fR
|
||||
and
|
||||
\fI"%D"\fR
|
||||
pattern variables in
|
||||
\fIFilter: "%u"\fR
|
||||
is replaced by a user\(cqs part of the JID,
|
||||
\fI"%d"\fR
|
||||
is replaced by the corresponding domain (virtual host), all
|
||||
\fI"%s"\fR
|
||||
variables are consecutively replaced by values from the attributes in
|
||||
\fIFilterAttrs\fR
|
||||
and "%D" is replaced by Distinguished Name from the result set\&. There is no default value, which means the result is not filtered\&. WARNING: Since this filter makes additional LDAP lookups, use it only as the last resort: try to define all filter rules in
|
||||
and
|
||||
\fI"%D"\fR
|
||||
is replaced by Distinguished Name from the result set\&. There is no default value, which means the result is not filtered\&. WARNING: Since this filter makes additional LDAP lookups, use it only as the last resort: try to define all filter rules in
|
||||
\fIldap_filter\fR
|
||||
option if possible\&.
|
||||
.sp
|
||||
@@ -1038,7 +1084,10 @@ Whether to encrypt LDAP connection using TLS or not\&. The default value is
|
||||
\fBldap_filter\fR: \fIFilter\fR
|
||||
.RS 4
|
||||
An LDAP filter as defined in
|
||||
RFC4515\&. There is no default value\&. Example: "(&(objectClass=shadowAccount)(memberOf=XMPP Users))"\&. NOTE: don\(cqt forget to close brackets and don\(cqt use superfluous whitespaces\&. Also you must not use "uid" attribute in the filter because this attribute will be appended to the filter automatically\&.
|
||||
RFC4515\&. There is no default value\&. Example:
|
||||
\fI"(&(objectClass=shadowAccount)(memberOf=XMPP Users))"\fR\&. NOTE: don\(cqt forget to close brackets and don\(cqt use superfluous whitespaces\&. Also you must not use
|
||||
\fI"uid"\fR
|
||||
attribute in the filter because this attribute will be appended to the filter automatically\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBldap_password\fR: \fIPassword\fR
|
||||
@@ -1101,11 +1150,15 @@ LDAP attributes which hold a list of attributes to use as alternatives for getti
|
||||
\fIAttr\fR
|
||||
is an LDAP attribute which holds the user\(cqs part of the JID and
|
||||
\fIAttrFormat\fR
|
||||
must contain one and only one pattern variable "%u" which will be replaced by the user\(cqs part of the JID\&. For example, "%u@example\&.org"\&. If the value is in the form of
|
||||
must contain one and only one pattern variable
|
||||
\fI"%u"\fR
|
||||
which will be replaced by the user\(cqs part of the JID\&. For example,
|
||||
\fI"%\fR\fIu@example\fR\fI\&.org"\fR\&. If the value is in the form of
|
||||
\fI[Attr]\fR
|
||||
then
|
||||
\fIAttrFormat\fR
|
||||
is assumed to be "%u"\&.
|
||||
is assumed to be
|
||||
\fI"%u"\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBlisten\fR: \fI[Options, \&.\&.\&.]\fR
|
||||
@@ -1193,7 +1246,7 @@ This option can be used to tune tick time parameter of
|
||||
.RS 4
|
||||
Whether to use the
|
||||
\fIdatabase\&.md#default\-and\-new\-schemas|new SQL schema\fR\&. All schemas are located at
|
||||
https://github\&.com/processone/ejabberd/tree/24\&.12/sql\&. There are two schemas available\&. The default legacy schema stores one XMPP domain into one ejabberd database\&. The
|
||||
https://github\&.com/processone/ejabberd/tree/25\&.04/sql\&. There are two schemas available\&. The default legacy schema stores one XMPP domain into one ejabberd database\&. The
|
||||
\fInew\fR
|
||||
schema can handle several XMPP domains in a single ejabberd database\&. Using this
|
||||
\fInew\fR
|
||||
@@ -1434,7 +1487,7 @@ or
|
||||
if the latter is not set\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBredis_server 🟤\fR: \fIHost | IP Address | Unix Socket Path\fR
|
||||
\fBredis_server\fR: \fIHost | IP Address | Unix Socket Path\fR
|
||||
.RS 4
|
||||
\fINote\fR
|
||||
about this option: improved in 24\&.12\&. A hostname, IP address or unix domain socket file of the
|
||||
@@ -1675,7 +1728,7 @@ shaper:
|
||||
.\}
|
||||
.RE
|
||||
.PP
|
||||
\fBshaper_rules\fR: \fI{ShaperRuleName: {Number|ShaperName: ACLRule|ACLName}}\fR
|
||||
\fBshaper_rules\fR: \fI{ShaperRuleName: {Number|ShaperName: ACLName|ACLDefinition}}\fR
|
||||
.RS 4
|
||||
This option defines
|
||||
\fI\&.\&./configuration/basic\&.md#shaper\-rules|shaper rules\fR
|
||||
@@ -1990,7 +2043,7 @@ seconds\&.
|
||||
.RE
|
||||
.SH "MODULES"
|
||||
.sp
|
||||
This section describes modules options of ejabberd 24\&.12\&. The modules that changed in this version are marked with 🟤\&.
|
||||
This section describes modules options of ejabberd 25\&.04\&. The modules that changed in this version are marked with 🟤\&.
|
||||
.SS "mod_adhoc"
|
||||
.sp
|
||||
This module implements XEP\-0050: Ad\-Hoc Commands\&. It\(cqs an auxiliary module and is only needed by some of the other modules\&.
|
||||
@@ -2009,6 +2062,63 @@ Provide the Commands item in the Service Discovery\&. Default value:
|
||||
\fIfalse\fR\&.
|
||||
.RE
|
||||
.RE
|
||||
.SS "mod_adhoc_api"
|
||||
.sp
|
||||
\fINote\fR about this option: added in 25\&.03\&.
|
||||
.sp
|
||||
Execute API Commands in a XMPP client using XEP\-0050: Ad\-Hoc Commands\&. This module requires \fImod_adhoc\fR (to execute the commands), and recommends \fImod_disco\fR (to discover the commands)\&.
|
||||
.sp
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
.nr an-break-flag 1
|
||||
.br
|
||||
.ps +1
|
||||
\fBAvailable options:\fR
|
||||
.RS 4
|
||||
.PP
|
||||
\fBdefault_version\fR: \fIinteger() | string()\fR
|
||||
.RS 4
|
||||
What API version to use\&. If setting an ejabberd version, it will use the latest API version that was available in that ejabberd version\&. For example, setting
|
||||
\fI"24\&.06"\fR
|
||||
in this option implies
|
||||
\fI2\fR\&. The default value is the latest version\&.
|
||||
.RE
|
||||
.RE
|
||||
.sp
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
.nr an-break-flag 1
|
||||
.br
|
||||
.ps +1
|
||||
\fBExample:\fR
|
||||
.RS 4
|
||||
.sp
|
||||
.if n \{\
|
||||
.RS 4
|
||||
.\}
|
||||
.nf
|
||||
acl:
|
||||
admin:
|
||||
user: jan@localhost
|
||||
|
||||
api_permissions:
|
||||
"adhoc commands":
|
||||
from: mod_adhoc_api
|
||||
who: admin
|
||||
what:
|
||||
\- "[tag:roster]"
|
||||
\- "[tag:session]"
|
||||
\- stats
|
||||
\- status
|
||||
|
||||
modules:
|
||||
mod_adhoc_api:
|
||||
default_version: 2
|
||||
.fi
|
||||
.if n \{\
|
||||
.RE
|
||||
.\}
|
||||
.RE
|
||||
.SS "mod_admin_extra"
|
||||
.sp
|
||||
This module provides additional administrative commands\&.
|
||||
@@ -2097,13 +2207,27 @@ This module can be used to update existing SQL database from the default to the
|
||||
The module has no options\&.
|
||||
.SS "mod_announce"
|
||||
.sp
|
||||
This module enables configured users to broadcast announcements and to set the message of the day (MOTD)\&. Configured users can perform these actions with an XMPP client either using Ad\-hoc Commands or sending messages to specific JIDs\&.
|
||||
This module enables configured users to broadcast announcements and to set the message of the day (MOTD)\&. Configured users can perform these actions with an XMPP client either using Ad\-Hoc Commands or sending messages to specific JIDs\&.
|
||||
.if n \{\
|
||||
.sp
|
||||
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\&.
|
||||
.\}
|
||||
.RS 4
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
.nr an-break-flag 1
|
||||
.br
|
||||
.ps +1
|
||||
\fBNote\fR
|
||||
.ps -1
|
||||
.br
|
||||
.sp
|
||||
The Ad\-hoc Commands are listed in the Server Discovery\&. For this feature to work, \fImod_adhoc\fR must be enabled\&.
|
||||
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\&.
|
||||
.sp .5v
|
||||
.RE
|
||||
.sp
|
||||
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:
|
||||
To send announcements using XEP\-0050: Ad\-Hoc Commands, this module requires \fImod_adhoc\fR (to execute the commands), and recommends \fImod_disco\fR (to discover the commands)\&.
|
||||
.sp
|
||||
To send announcements by sending messages to specific JIDs, these are the destination JIDs:
|
||||
.sp
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
@@ -2113,7 +2237,7 @@ The specific JIDs where messages can be sent are listed below\&. The first JID i
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
example\&.org/announce/all (example\&.org/announce/all\-hosts/all):: The message is sent to all registered users\&. If the user is online and connected to several resources, only the resource with the highest priority will receive the message\&. If the registered user is not connected, the message will be stored offline in assumption that offline storage (see
|
||||
\fIexample\&.org/announce/all\fR: Send the message to all registered users in that vhost\&. 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 is stored offline in assumption that offline storage (see
|
||||
\fImod_offline\fR) is enabled\&.
|
||||
.RE
|
||||
.sp
|
||||
@@ -2125,7 +2249,7 @@ example\&.org/announce/all (example\&.org/announce/all\-hosts/all):: The message
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
example\&.org/announce/online (example\&.org/announce/all\-hosts/online):: The message is sent to all connected users\&. If the user is online and connected to several resources, all resources will receive the message\&.
|
||||
\fIexample\&.org/announce/online\fR: Send the message to all connected users\&. If the user is online and connected to several resources, all resources will receive the message\&.
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
@@ -2136,7 +2260,8 @@ example\&.org/announce/online (example\&.org/announce/all\-hosts/online):: The m
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
example\&.org/announce/motd (example\&.org/announce/all\-hosts/motd):: The message is set as the message of the day (MOTD) and is sent to users when they login\&. In addition the message is sent to all connected users (similar to announce/online)\&.
|
||||
\fIexample\&.org/announce/motd\fR: Set the message of the day (MOTD) that is sent to users when they login\&. Also sends the message to all connected users (similar to
|
||||
\fIannounce/online\fR)\&.
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
@@ -2147,7 +2272,7 @@ example\&.org/announce/motd (example\&.org/announce/all\-hosts/motd):: The messa
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
example\&.org/announce/motd/update (example\&.org/announce/all\-hosts/motd/update):: The message is set as message of the day (MOTD) and is sent to users when they login\&. The message is not sent to any currently connected user\&.
|
||||
\fIexample\&.org/announce/motd/update\fR: Set the message of the day (MOTD) that is sent to users when they login\&. This does not send the message to any currently connected user\&.
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
@@ -2158,7 +2283,64 @@ example\&.org/announce/motd/update (example\&.org/announce/all\-hosts/motd/updat
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
example\&.org/announce/motd/delete (example\&.org/announce/all\-hosts/motd/delete):: Any message sent to this JID removes the existing message of the day (MOTD)\&.
|
||||
\fIexample\&.org/announce/motd/delete\fR: Remove the existing message of the day (MOTD) by sending a message to this JID\&.
|
||||
.RE
|
||||
.sp
|
||||
There are similar destination JIDs to apply to all virtual hosts in ejabberd:
|
||||
.sp
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
\fIexample\&.org/announce/all\-hosts/all\fR: send to all registered accounts
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
\fIexample\&.org/announce/all\-hosts/online\fR: send to online sessions
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
\fIexample\&.org/announce/all\-hosts/motd\fR: set MOTD and send to online
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
\fIexample\&.org/announce/all\-hosts/motd/update\fR: update MOTD
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
\fIexample\&.org/announce/all\-hosts/motd/delete\fR: delete MOTD
|
||||
.RE
|
||||
.sp
|
||||
.it 1 an-trap
|
||||
@@ -2211,11 +2393,11 @@ Same as top\-level
|
||||
option, but applied to this module only\&.
|
||||
.RE
|
||||
.RE
|
||||
.SS "mod_auth_fast 🟤"
|
||||
.SS "mod_auth_fast"
|
||||
.sp
|
||||
\fINote\fR about this option: added in 24\&.12\&.
|
||||
.sp
|
||||
The module adds support for XEP\-0480: Fast Authentication Streamlining Tokens that allows users to authenticate using self managed tokens\&.
|
||||
The module adds support for XEP\-0484: Fast Authentication Streamlining Tokens that allows users to authenticate using self\-managed tokens\&.
|
||||
.sp
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
@@ -2225,7 +2407,7 @@ The module adds support for XEP\-0480: Fast Authentication Streamlining Tokens t
|
||||
\fBAvailable options:\fR
|
||||
.RS 4
|
||||
.PP
|
||||
\fBdb_type\fR: \fImnesia | sql\fR
|
||||
\fBdb_type\fR: \fImnesia\fR
|
||||
.RS 4
|
||||
Same as top\-level
|
||||
\fIdefault_db\fR
|
||||
@@ -2234,7 +2416,7 @@ option, but applied to this module only\&.
|
||||
.PP
|
||||
\fBtoken_lifetime\fR: \fItimeout()\fR
|
||||
.RS 4
|
||||
Time that tokens will be keept, measured from it\(cqs creation time\&. Default value set to 30 days
|
||||
Time that tokens will be kept, measured from it\(cqs creation time\&. Default value set to 30 days
|
||||
.RE
|
||||
.PP
|
||||
\fBtoken_refresh_age\fR: \fItimeout()\fR
|
||||
@@ -2257,7 +2439,7 @@ This time determines age of token, that qualifies for automatic refresh\&. Defau
|
||||
.nf
|
||||
modules:
|
||||
mod_auth_fast:
|
||||
token_timeout: 14days
|
||||
token_lifetime: 14days
|
||||
.fi
|
||||
.if n \{\
|
||||
.RE
|
||||
@@ -2578,9 +2760,90 @@ While a client is inactive, queue presence stanzas that indicate (un)availabilit
|
||||
.RE
|
||||
.SS "mod_configure"
|
||||
.sp
|
||||
The module provides server configuration functionality via XEP\-0050: Ad\-Hoc Commands\&. Implements many commands as defined in XEP\-0133: Service Administration\&. This module requires \fImod_adhoc\fR to be loaded\&.
|
||||
The module provides server configuration functionalities using XEP\-0030: Service Discovery and XEP\-0050: Ad\-Hoc Commands:
|
||||
.sp
|
||||
The module has no options\&.
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
List and discover outgoing s2s, online client sessions and all registered accounts
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
Most of the ad\-hoc commands defined in
|
||||
XEP\-0133: Service Administration
|
||||
.RE
|
||||
.sp
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.sp -1
|
||||
.IP \(bu 2.3
|
||||
.\}
|
||||
Additional custom ad\-hoc commands specific to ejabberd
|
||||
.RE
|
||||
.sp
|
||||
This module requires \fImod_adhoc\fR (to execute the commands), and recommends \fImod_disco\fR (to discover the commands)\&.
|
||||
.sp
|
||||
Please notice that all the ad\-hoc commands implemented by this module have an equivalent API Command that you can execute using \fImod_adhoc_api\fR or any other API frontend\&.
|
||||
.sp
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
.nr an-break-flag 1
|
||||
.br
|
||||
.ps +1
|
||||
\fBAvailable options:\fR
|
||||
.RS 4
|
||||
.PP
|
||||
\fBaccess\fR: \fIAccessName\fR
|
||||
.RS 4
|
||||
\fINote\fR
|
||||
about this option: added in 25\&.03\&. This option defines which access rule will be used to control who is allowed to access the features provided by this module\&. The default value is
|
||||
\fIconfigure\fR\&.
|
||||
.RE
|
||||
.RE
|
||||
.sp
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
.nr an-break-flag 1
|
||||
.br
|
||||
.ps +1
|
||||
\fBExample:\fR
|
||||
.RS 4
|
||||
.sp
|
||||
.if n \{\
|
||||
.RS 4
|
||||
.\}
|
||||
.nf
|
||||
acl:
|
||||
admin:
|
||||
user: sun@localhost
|
||||
|
||||
access_rules:
|
||||
configure:
|
||||
allow: admin
|
||||
|
||||
modules:
|
||||
mod_configure:
|
||||
access: configure
|
||||
.fi
|
||||
.if n \{\
|
||||
.RE
|
||||
.\}
|
||||
.RE
|
||||
.SS "mod_conversejs"
|
||||
.sp
|
||||
\fINote\fR about this option: added in 21\&.12 and improved in 22\&.05\&.
|
||||
@@ -3060,7 +3323,8 @@ To run a command, send a POST request to the corresponding URL: \fIhttp://localh
|
||||
.PP
|
||||
\fBdefault_version\fR: \fIinteger() | string()\fR
|
||||
.RS 4
|
||||
What API version to use when none is specified in the URL path\&. If setting an ejabberd version, it will use the latest API version that was available in that ejabberd version\&. For example, setting
|
||||
\fINote\fR
|
||||
about this option: added in 24\&.12\&. What API version to use when none is specified in the URL path\&. If setting an ejabberd version, it will use the latest API version that was available in that ejabberd version\&. For example, setting
|
||||
\fI"24\&.06"\fR
|
||||
in this option implies
|
||||
\fI2\fR\&. The default value is the latest version\&.
|
||||
@@ -3578,6 +3842,22 @@ The module has no options\&.
|
||||
.SS "mod_mam"
|
||||
.sp
|
||||
This module implements XEP\-0313: Message Archive Management and XEP\-0441: Message Archive Management Preferences\&. Compatible XMPP clients can use it to store their chat history on the server\&.
|
||||
.if n \{\
|
||||
.sp
|
||||
.\}
|
||||
.RS 4
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
.nr an-break-flag 1
|
||||
.br
|
||||
.ps +1
|
||||
\fBNote\fR
|
||||
.ps -1
|
||||
.br
|
||||
.sp
|
||||
Mnesia backend for mod_mam is not recommended: it\(cqs limited to 2GB and often gets corrupted when reaching this limit\&. SQL backend is recommended\&. Namely, for small servers SQLite is a preferred choice because it\(cqs very easy to configure\&.
|
||||
.sp .5v
|
||||
.RE
|
||||
.sp
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
@@ -3678,9 +3958,9 @@ When this option is disabled, for each individual subscriber a separate mucsub m
|
||||
.RE
|
||||
.SS "mod_matrix_gw"
|
||||
.sp
|
||||
\fINote\fR about this option: added in 24\&.02\&.
|
||||
\fINote\fR about this option: improved in 25\&.03\&.
|
||||
.sp
|
||||
Matrix gateway\&. Erlang/OTP 25 or higher is required to use this module\&.
|
||||
Matrix gateway\&. Erlang/OTP 25 or higher is required to use this module\&. This module is available since ejabberd 24\&.02\&.
|
||||
.sp
|
||||
.it 1 an-trap
|
||||
.nr an-no-space-flag 1
|
||||
@@ -4351,7 +4631,10 @@ Short description of the room\&. The default value is an empty string\&.
|
||||
.PP
|
||||
\fBenable_hats\fR: \fItrue | false\fR
|
||||
.RS 4
|
||||
Allow extended roles as defined in XEP\-0317 Hats\&. The default value is
|
||||
\fINote\fR
|
||||
about this option: improved in 25\&.03\&. Allow extended roles as defined in XEP\-0317 Hats\&. Check the
|
||||
\fI\&.\&./\&.\&./tutorials/muc\-hats\&.md|MUC Hats\fR
|
||||
tutorial\&. The default value is
|
||||
\fIfalse\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
@@ -4467,6 +4750,12 @@ A human\-readable title of the room\&. There is no default value
|
||||
A custom vCard for the room\&. See the equivalent mod_muc option\&.The default value is an empty string\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBvcard_xupdate\fR: \fIundefined | external | AvatarHash\fR
|
||||
.RS 4
|
||||
Set the hash of the avatar image\&. The default value is
|
||||
\fIundefined\fR\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBvoice_request_min_interval\fR: \fINumber\fR
|
||||
.RS 4
|
||||
Minimum interval between voice requests, in seconds\&. The default value is
|
||||
@@ -6308,9 +6597,7 @@ is
|
||||
.PP
|
||||
\fBaccess_from\fR: \fIAccessName\fR
|
||||
.RS 4
|
||||
By default,
|
||||
\fIejabberd\fR
|
||||
doesn\(cqt allow the client to register new accounts from s2s or existing c2s sessions\&. You can change it by defining access rule in this option\&. Use with care: allowing registration from s2s leads to uncontrolled massive accounts creation by rogue users\&.
|
||||
By default, ejabberd doesn\(cqt allow the client to register new accounts from s2s or existing c2s sessions\&. You can change it by defining access rule in this option\&. Use with care: allowing registration from s2s leads to uncontrolled massive accounts creation by rogue users\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBaccess_remove\fR: \fIAccessName\fR
|
||||
@@ -8085,7 +8372,7 @@ Should the operating system be revealed or not\&. The default value is
|
||||
.RE
|
||||
.SH "LISTENERS"
|
||||
.sp
|
||||
This section describes listeners options of ejabberd 24\&.12\&.
|
||||
This section describes listeners options of ejabberd 25\&.04\&.
|
||||
.sp
|
||||
TODO
|
||||
.SH "AUTHOR"
|
||||
@@ -8093,13 +8380,13 @@ TODO
|
||||
ProcessOne\&.
|
||||
.SH "VERSION"
|
||||
.sp
|
||||
This document describes the configuration file of ejabberd 24\&.12\&. Configuration options of other ejabberd versions may differ significantly\&.
|
||||
This document describes the configuration file of ejabberd 25\&.04\&. Configuration options of other ejabberd versions may differ significantly\&.
|
||||
.SH "REPORTING BUGS"
|
||||
.sp
|
||||
Report bugs to https://github\&.com/processone/ejabberd/issues
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
Default configuration file: https://github\&.com/processone/ejabberd/blob/24\&.12/ejabberd\&.yml\&.example
|
||||
Default configuration file: https://github\&.com/processone/ejabberd/blob/25\&.04/ejabberd\&.yml\&.example
|
||||
.sp
|
||||
Main site: https://ejabberd\&.im
|
||||
.sp
|
||||
@@ -8110,4 +8397,4 @@ Configuration Guide: https://docs\&.ejabberd\&.im/admin/configuration
|
||||
Source code: https://github\&.com/processone/ejabberd
|
||||
.SH "COPYING"
|
||||
.sp
|
||||
Copyright (c) 2002\-2024 ProcessOne\&.
|
||||
Copyright (c) 2002\-2025 ProcessOne\&.
|
||||
|
||||
@@ -79,20 +79,6 @@ defmodule Ejabberd.MixProject do
|
||||
end
|
||||
end
|
||||
|
||||
defp if_type_exported(module, typeDef, okResult) do
|
||||
try do
|
||||
{:ok, concrete} = :dialyzer_utils.get_core_from_beam(:code.which(module))
|
||||
{:ok, types} = :dialyzer_utils.get_record_and_type_info(concrete)
|
||||
if Map.has_key?(types, typeDef) do
|
||||
okResult
|
||||
else
|
||||
[]
|
||||
end
|
||||
rescue
|
||||
_ -> []
|
||||
end
|
||||
end
|
||||
|
||||
defp erlc_options do
|
||||
# Use our own includes + includes from all dependencies
|
||||
includes = ["include", deps_include()]
|
||||
@@ -113,7 +99,7 @@ defmodule Ejabberd.MixProject do
|
||||
if_version_below(~c"25", [{:d, :OTP_BELOW_25}]) ++
|
||||
if_version_below(~c"26", [{:d, :OTP_BELOW_26}]) ++
|
||||
if_version_below(~c"27", [{:d, :OTP_BELOW_27}]) ++
|
||||
if_type_exported(:odbc, {:opaque, :connection_reference, 0}, [{:d, :ODBC_HAS_TYPES}])
|
||||
if_version_below(~c"28", [{:d, :OTP_BELOW_28}])
|
||||
defines = for {:d, value} <- result, do: {:d, value}
|
||||
result ++ [{:d, :ALL_DEFS, defines}]
|
||||
end
|
||||
@@ -133,9 +119,9 @@ defmodule Ejabberd.MixProject do
|
||||
[{:cache_tab, "~> 1.0"},
|
||||
{:dialyxir, "~> 1.2", only: [:test], runtime: false},
|
||||
{:eimp, "~> 1.0"},
|
||||
{:ex_doc, "~> 0.31", only: [:dev, :edoc], runtime: false},
|
||||
{:ex_doc, "~> 0.31", only: [:edoc], runtime: false},
|
||||
{:fast_tls, "~> 1.1.22"},
|
||||
{:fast_xml, "~> 1.1.53", override: true},
|
||||
{:fast_xml, "~> 1.1.53"},
|
||||
{:fast_yaml, "~> 1.0"},
|
||||
{:idna, "~> 6.0"},
|
||||
{:mqtree, "~> 1.0"},
|
||||
@@ -144,8 +130,8 @@ defmodule Ejabberd.MixProject do
|
||||
{:p1_utils, "~> 1.0"},
|
||||
{:pkix, "~> 1.0"},
|
||||
{:stringprep, ">= 1.0.26"},
|
||||
{:xmpp, "~> 1.9.1"},
|
||||
{:yconf, "~> 1.0.17"}]
|
||||
{:xmpp, "~> 1.10.0"},
|
||||
{:yconf, ">= 1.0.18"}]
|
||||
++ cond_deps()
|
||||
end
|
||||
|
||||
@@ -175,7 +161,7 @@ defmodule Ejabberd.MixProject do
|
||||
{if_version_below(~c"22", true), {:lager, "~> 3.9.1"}},
|
||||
{config(:lua), {:luerl, "~> 1.2.0"}},
|
||||
{config(:mysql), {:p1_mysql, ">= 1.0.24"}},
|
||||
{config(:pgsql), {:p1_pgsql, ">= 1.1.26"}},
|
||||
{config(:pgsql), {:p1_pgsql, ">= 1.1.32"}},
|
||||
{config(:sqlite), {:sqlite3, "~> 1.1"}},
|
||||
{config(:stun), {:stun, "~> 1.0"}}], do:
|
||||
dep
|
||||
@@ -281,6 +267,7 @@ defmodule Ejabberd.MixProject do
|
||||
ejabberd: [
|
||||
include_executables_for: [:unix],
|
||||
# applications: [runtime_tools: :permanent]
|
||||
strip_beams: Mix.env() != :dev,
|
||||
steps: [©_extra_files/1, :assemble | maybe_tar]
|
||||
]
|
||||
]
|
||||
|
||||
@@ -2,38 +2,38 @@
|
||||
"base64url": {:hex, :base64url, "1.0.1", "f8c7f2da04ca9a5d0f5f50258f055e1d699f0e8bf4cfdb30b750865368403cf6", [:rebar3], [], "hexpm", "f9b3add4731a02a9b0410398b475b33e7566a695365237a6bdee1bb447719f5c"},
|
||||
"cache_tab": {:hex, :cache_tab, "1.0.31", "e4097b50a6f373ab1e0a5f01bab0bef6626771a4cd6c93404ed6d54810e11fbc", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "8582b60a4a09b247ef86355ba9e07fce9e11edc0345a775c9171f971c72b6351"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"},
|
||||
"eimp": {:hex, :eimp, "1.0.23", "aaf32efab061143403dadbaa63e699ef8e81702fbfa96fd436d5e9be4d6a8d3a", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "907c780023cb2893e4fc4bdbe6a4f02c355913862ac67f0ecc26605e816b628a"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
|
||||
"eimp": {:hex, :eimp, "1.0.24", "853db317ba394d479d2f1181e0b0135a3cd3c2c7eb48ff6cfb035a28dd354b14", [:rebar3], [{:p1_utils, "~> 1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "7d61432eb8a45659c0be475f44e75eeb651743aa64a1de8adf785cdad81961ad"},
|
||||
"epam": {:hex, :epam, "1.0.14", "aa0b85d27f4ef3a756ae995179df952a0721237e83c6b79d644347b75016681a", [:rebar3], [], "hexpm", "2f3449e72885a72a6c2a843f561add0fc2f70d7a21f61456930a547473d4d989"},
|
||||
"eredis": {:hex, :eredis, "1.7.1", "39e31aa02adcd651c657f39aafd4d31a9b2f63c6c700dc9cece98d4bc3c897ab", [:mix, :rebar3], [], "hexpm", "7c2b54c566fed55feef3341ca79b0100a6348fd3f162184b7ed5118d258c3cc1"},
|
||||
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
|
||||
"esip": {:hex, :esip, "1.0.56", "63c0fdc667be751714e1e5c14621a9334f21b60ac1bb68be889454ca9ca021b7", [:rebar3], [{:fast_tls, "1.1.22", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.2.15", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "9ef3660cef93b623f7368dcd5c79f4e704358631909e6dd464e335378815da1f"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.35.1", "de804c590d3df2d9d5b8aec77d758b00c814b356119b3d4455e4b8a8687aecaf", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "2121c6402c8d44b05622677b761371a759143b958c6c19f6558ff64d0aed40df"},
|
||||
"esip": {:hex, :esip, "1.0.57", "4b14e4832d08b9ffc10d855b5d10b3083232b1d53deb4c046679496ce85569c4", [:rebar3], [{:fast_tls, "1.1.22", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.2.17", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "19c357e1817b1e04792ef359bf900400f3e6d0e5ade929fd72f88ea9b44af2ed"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.37.3", "f7816881a443cd77872b7d6118e8a55f547f49903aef8747dbcb345a75b462f9", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "e6aebca7156e7c29b5da4daa17f6361205b2ae5f26e5c7d8ca0d3f7e18972233"},
|
||||
"exsync": {:hex, :exsync, "0.4.1", "0a14fe4bfcb80a509d8a0856be3dd070fffe619b9ba90fec13c58b316c176594", [:mix], [{:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "cefb22aa805ec97ffc5b75a4e1dc54bcaf781e8b32564bf74abbe5803d1b5178"},
|
||||
"ezlib": {:hex, :ezlib, "1.0.13", "3c7f62862850a241159c10b218ecf580bce54d0890601b65144dacc2633be2b0", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "9ee62ab3f8ed55a0fd11a9569fcb8e458683f95575417272192b069f092abfbb"},
|
||||
"fast_tls": {:hex, :fast_tls, "1.1.22", "44356b256afad4399c2fc5059a3066669dafd8bd4e4e796c9c1cf8910ddd265e", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "e65779aefb7ab15c4755230fef8077e687d20cc5a3984a5974f9f657e8e2485b"},
|
||||
"fast_xml": {:hex, :fast_xml, "1.1.55", "ace020f2521f2a484ac8467d2822af85534a346e2aae03ffcbc34f29318befaf", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "83f3e23a780ed5f567cdec73953f06c95b838d709dbfa86b59a98a8d23c99f85"},
|
||||
"fast_yaml": {:hex, :fast_yaml, "1.0.37", "f71d472fbf787ccd161b914d1eb486116a0f4f2e835337a378fbd31b59d2e74b", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "8de868721bf7e2172414f7d3148ede0f3c922b496455cd625dd5c4429515a769"},
|
||||
"file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
|
||||
"file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
|
||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||
"jiffy": {:hex, :jiffy, "1.1.2", "a9b6c9a7ec268e7cf493d028f0a4c9144f59ccb878b1afe42841597800840a1b", [:rebar3], [], "hexpm", "bb61bc42a720bbd33cb09a410e48bb79a61012c74cb8b3e75f26d988485cf381"},
|
||||
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
|
||||
"luerl": {:hex, :luerl, "1.2.3", "df25f41944e57a7c4d9ef09d238bc3e850276c46039cfc12b8bb42eccf36fcb1", [:rebar3], [], "hexpm", "1b4b9d0ca5d7d280d1d2787a6a5ee9f5a212641b62bff91556baa53805df3aed"},
|
||||
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"},
|
||||
"mqtree": {:hex, :mqtree, "1.0.17", "82f54b8f2d22b4445db1d6cccb7fe9ead049d61410c29e32475f3ceb3ee62a89", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "5fe8b7cf8fbc4783d0fceb94654ac2bbf3242a58cd0397d249ded8ae021be2a3"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
|
||||
"p1_acme": {:hex, :p1_acme, "1.0.25", "db91f0d6c193cd1d5c0b0fa3939a898dbf56a6075db4347cde26e802715de50c", [:rebar3], [{:base64url, "~> 1.0", [hex: :base64url, repo: "hexpm", optional: false]}, {:idna, "~> 6.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~> 1.1.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~> 1.11.10", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~> 1.0.17", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "a7b55b47495ddb4f98a15e65451ec3ad43f4637b955c74cd695d98e6a645d08c"},
|
||||
"p1_mysql": {:hex, :p1_mysql, "1.0.25", "875d4cbdc7c9990270df3292cce2514e4c18a9fdfd19bef258cb4d0c45b4f243", [:rebar3], [], "hexpm", "e6187ffae95b726098e88f3ee6f2344ac259ce2c26e0ee403b05feef341ae434"},
|
||||
"p1_mysql": {:hex, :p1_mysql, "1.0.26", "574d07c9936c53b1ec3556db3cf064cc14a6c39039835b3d940471bfa5ac8e2b", [:rebar3], [], "hexpm", "ea138083f2c54719b9cf549dbf5802a288b0019ea3e5449b354c74cc03fafdec"},
|
||||
"p1_oauth2": {:hex, :p1_oauth2, "0.6.14", "1c5f82535574de87e2059695ac4b91f8f9aebacbc1c80287dae6f02552d47aea", [:rebar3], [], "hexpm", "1fd3ac474e43722d9d5a87c6df8d36f698ed87af7bb81cbbb66361451d99ae8f"},
|
||||
"p1_pgsql": {:hex, :p1_pgsql, "1.1.29", "fae0c90cbc5931865958150f1b667fb0d20b063f6a46a17770a4e5232ded632c", [:rebar3], [{:xmpp, "~> 1.9.0", [hex: :xmpp, repo: "hexpm", optional: false]}], "hexpm", "a6ff58e8b174993f3895da3ea6211a9f9d0c54d1a6e28bb321da3b3cd68b38c1"},
|
||||
"p1_pgsql": {:hex, :p1_pgsql, "1.1.32", "3f95d7e3413fc8f0be80abb4be1a0d7f67066a36905085cd5a423145598b0cb0", [:rebar3], [{:xmpp, "~> 1.10.0", [hex: :xmpp, repo: "hexpm", optional: false]}], "hexpm", "268b01e8f4eb75c211a31495a25c2815c549aecce2f0df1a161c6e0a2cde061e"},
|
||||
"p1_utils": {:hex, :p1_utils, "1.0.26", "67b0c4ac9fa3ba3ef563b31aa111b0a004439a37fac85e027f1c3617e1c7ec6c", [:rebar3], [], "hexpm", "d0379e8c1156b98bd64f8129c1de022fcca4f2fdb7486ce73bf0ed2c3376b04c"},
|
||||
"pkix": {:hex, :pkix, "1.0.10", "d3bfadf7b7cfe2a3636f1b256c9cce5f646a07ce31e57ee527668502850765a0", [:rebar3], [], "hexpm", "e02164f83094cb124c41b1ab28988a615d54b9adc38575f00f19a597a3ac5d0e"},
|
||||
"sqlite3": {:hex, :sqlite3, "1.1.15", "e819defd280145c328457d7af897d2e45e8e5270e18812ee30b607c99cdd21af", [:rebar3], [], "hexpm", "3c0ba4e13322c2ad49de4e2ddd28311366adde54beae8dba9d9e3888f69d2857"},
|
||||
"stringprep": {:hex, :stringprep, "1.0.30", "46cf0ff631b3e7328f61f20b454d59428d87738f25d709798b5dcbb9b83c23f1", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "f6fc9b3384a03877830f89b2f38580caf3f4a27448a4a333d6a8c3975c220b9a"},
|
||||
"stun": {:hex, :stun, "1.2.15", "eec510af6509201ff97f1f2c87b7977c833bf29c04e985383370ec21f04e4ccf", [:rebar3], [{:fast_tls, "1.1.22", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "f6d8a541a29fd13f2ce658b676c0cc661262b96e045b52def1644b75ebc0edef"},
|
||||
"stringprep": {:hex, :stringprep, "1.0.31", "fa1688c156dd271722aa18c423a4163e710d2f4f475ad0bc220910df669b53af", [:rebar3], [{:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "e9699c88e8db16b3a41f0e45ac6874a4da81a6e4854a77d76ede6d09b08e3530"},
|
||||
"stun": {:hex, :stun, "1.2.17", "c54614a592812ea125a2e6827aac5a438571b591616426ec1419ba9b48252f54", [:rebar3], [{:fast_tls, "1.1.22", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "6b318244c21e8524a9aae3ac9a05cd8234ee994c1c2c815de68d306086ad768d"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
||||
"xmpp": {:hex, :xmpp, "1.9.1", "a1642d93cdbdf947f32344b0e05fcc8efcfb9f11c32832acc9bd826b52adbe48", [:rebar3], [{:ezlib, "~> 1.0.12", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "~> 1.1.19", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "~> 1.1.51", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "~> 6.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "~> 1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "~> 1.0.29", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "d2b1431af6e4c1a4c8bf90caf0cc11cdeb047b8323b87e9d7e4826d4913275dc"},
|
||||
"yconf": {:hex, :yconf, "1.0.17", "dcf242e27f3fc5d0743d6b8175dd39bc14a1f4ed7e6ea986366a44a6ff3b2a3a", [:rebar3], [{:fast_yaml, "1.0.37", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "dd2892923241449a46cc8457b9ec0fb14030700735a5885955677c735c341a25"},
|
||||
"xmpp": {:hex, :xmpp, "1.10.0", "68a6dff8db8987c4592b2d5dd71d3f947b4ebd15209c9acaca5909a642670630", [:rebar3], [{:ezlib, "~> 1.0.12", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "~> 1.1.19", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "~> 1.1.51", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "~> 6.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "~> 1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "~> 1.0.29", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "ceeae43b8fe97649d8f8546b3f7f2b38ecfc931c0cdd5c7445ffb3f80fcb7d85"},
|
||||
"yconf": {:hex, :yconf, "1.0.18", "e565edc8aabb8164c3bebc86969095d296ad315dcbb46af65dccbc6c71eae0f6", [:rebar3], [{:fast_yaml, "1.0.37", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "fa950ec6503f92d6417fb8cc1d982403f041697e8e1bbf4d4588fb919b9562ea"},
|
||||
}
|
||||
|
||||
@@ -295,7 +295,6 @@
|
||||
{"No pending subscriptions found","Не са намерени чакащи абонаменти"}.
|
||||
{"No privacy list with this name found","Не е намерен списък за поверителност с това име"}.
|
||||
{"No private data found in this query","Няма открити лични данни в тази заявка"}.
|
||||
{"No <privileged_iq/> element found","Елементът <privileged_iq/> не е намерен"}.
|
||||
{"No running node found","Не е намерен работещ нод"}.
|
||||
{"No services available","Няма налични услуги"}.
|
||||
{"No statistics found for this item","Не е налична статистика за този елемент"}.
|
||||
|
||||
+7
-3
@@ -22,7 +22,7 @@
|
||||
{"Administrator privileges required","Es necessita tenir privilegis d'administrador"}.
|
||||
{"All activity","Tota l'activitat"}.
|
||||
{"All Users","Tots els usuaris"}.
|
||||
{"Allow subscription","Permetre subscripcions"}.
|
||||
{"Allow subscription","Permetre subscripció"}.
|
||||
{"Allow this Jabber ID to subscribe to this pubsub node?","Permetre que aquesta Jabber ID es puga subscriure a aquest node pubsub?"}.
|
||||
{"Allow this person to register with the room?","Permetre a esta persona registrar-se a la sala?"}.
|
||||
{"Allow users to change the subject","Permetre que els usuaris canviïn el tema"}.
|
||||
@@ -46,7 +46,9 @@
|
||||
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","Qualsevol amb una subscripció de presencia de 'both' o 'from' pot subscriure's i publicar elements"}.
|
||||
{"Anyone with Voice","Qualsevol amb Veu"}.
|
||||
{"Anyone","Qualsevol"}.
|
||||
{"API Commands","Comandaments API"}.
|
||||
{"April","Abril"}.
|
||||
{"Arguments","Arguments"}.
|
||||
{"Attribute 'channel' is required for this request","L'atribut 'channel' és necessari per a aquesta petició"}.
|
||||
{"Attribute 'id' is mandatory for MIX messages","L'atribut 'id' es necessari per a missatges MIX"}.
|
||||
{"Attribute 'jid' is not allowed here","L'atribut 'jid' no està permès ací"}.
|
||||
@@ -86,6 +88,7 @@
|
||||
{"Choose whether to approve this entity's subscription.","Tria si aproves aquesta entitat de subscripció."}.
|
||||
{"City","Ciutat"}.
|
||||
{"Client acknowledged more stanzas than sent by server","El client ha reconegut més paquets dels que ha enviat el servidor"}.
|
||||
{"Clustering","Clustering"}.
|
||||
{"Commands","Comandaments"}.
|
||||
{"Conference room does not exist","La sala de conferències no existeix"}.
|
||||
{"Configuration of room ~s","Configuració de la sala ~s"}.
|
||||
@@ -295,7 +298,6 @@
|
||||
{"No pending subscriptions found","No s'han trobat subscripcions pendents"}.
|
||||
{"No privacy list with this name found","No s'ha trobat cap llista de privacitat amb aquest nom"}.
|
||||
{"No private data found in this query","No s'ha trobat dades privades en esta petició"}.
|
||||
{"No <privileged_iq/> element found","No s'ha trobat cap element <privileged_iq/>"}.
|
||||
{"No running node found","No s'ha trobat node en marxa"}.
|
||||
{"No services available","No n'hi ha serveis disponibles"}.
|
||||
{"No statistics found for this item","No n'hi ha estadístiques disponibles per a aquest element"}.
|
||||
@@ -409,6 +411,7 @@
|
||||
{"Restore binary backup immediately:","Restaurar una còpia de seguretat binària ara mateix:"}.
|
||||
{"Restore plain text backup immediately:","Restaurar una còpia de seguretat en format de text pla ara mateix:"}.
|
||||
{"Restore","Restaurar"}.
|
||||
{"Result","Resultat"}.
|
||||
{"Roles and Affiliations that May Retrieve Member List","Rols i Afiliacions que poden recuperar la llista de membres"}.
|
||||
{"Roles for which Presence is Broadcasted","Rols per als que sí se difon la seua presencia"}.
|
||||
{"Roles that May Send Private Messages","Rols que poden enviar missatges privats"}.
|
||||
@@ -585,6 +588,7 @@
|
||||
{"Visitor","Visitant"}.
|
||||
{"Voice request","Petició de veu"}.
|
||||
{"Voice requests are disabled in this conference","Les peticions de veu es troben desactivades en aquesta conferència"}.
|
||||
{"Web client which allows to join the room anonymously","Client web que permet entrar a la sala anonimament"}.
|
||||
{"Wednesday","Dimecres"}.
|
||||
{"When a new subscription is processed and whenever a subscriber comes online","Quan es processa una nova subscripció i un subscriptor es connecta"}.
|
||||
{"When a new subscription is processed","Quan es processa una nova subscripció"}.
|
||||
@@ -594,7 +598,7 @@
|
||||
{"Whether an entity wants to receive or disable notifications","Si una entitat vol rebre notificacions o no"}.
|
||||
{"Whether owners or publisher should receive replies to items","Si el propietaris o publicadors deurien de rebre respostes als elements"}.
|
||||
{"Whether the node is a leaf (default) or a collection","Si el node es fulla (per defecte) o es una col·lecció"}.
|
||||
{"Whether to allow subscriptions","Permetre subscripcions"}.
|
||||
{"Whether to allow subscriptions","Si s'hauria de permetre subscripcions"}.
|
||||
{"Whether to make all subscriptions temporary, based on subscriber presence","Si fer totes les subscripcions temporals, basat en la presencia del subscriptor"}.
|
||||
{"Whether to notify owners about new subscribers and unsubscribes","Si notificar als propietaris sobre noves subscripcions i desubscripcions"}.
|
||||
{"Who can send private messages","Qui pot enviar missatges privats"}.
|
||||
|
||||
+6
-1
@@ -46,7 +46,9 @@
|
||||
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","Jeder mit einem Präsenzabonnement von beiden oder davon darf Items abonnieren oder abrufen"}.
|
||||
{"Anyone with Voice","Jeder mit Stimme"}.
|
||||
{"Anyone","Jeder"}.
|
||||
{"API Commands","API Befehle"}.
|
||||
{"April","April"}.
|
||||
{"Arguments","Argumente"}.
|
||||
{"Attribute 'channel' is required for this request","Attribut 'channel' ist für diese Anforderung erforderlich"}.
|
||||
{"Attribute 'id' is mandatory for MIX messages","Attribut 'id' ist verpflichtend für MIX-Nachrichten"}.
|
||||
{"Attribute 'jid' is not allowed here","Attribut 'jid' ist hier nicht erlaubt"}.
|
||||
@@ -168,6 +170,7 @@
|
||||
{"has been kicked because of an affiliation change","wurde wegen einer Änderung der Zugehörigkeit hinausgeworfen"}.
|
||||
{"has been kicked because the room has been changed to members-only","wurde hinausgeworfen weil der Raum zu Nur-Mitglieder geändert wurde"}.
|
||||
{"has been kicked","wurde hinausgeworfen"}.
|
||||
{"Hash of the vCard-temp avatar of this room","Hash des vCard-temp Avatars dieses Raums"}.
|
||||
{"Hat title","Funktionstitel"}.
|
||||
{"Hat URI","Funktions-URI"}.
|
||||
{"Hats limit exceeded","Funktionslimit wurde überschritten"}.
|
||||
@@ -294,7 +297,6 @@
|
||||
{"No pending subscriptions found","Keine ausstehenden Abonnements gefunden"}.
|
||||
{"No privacy list with this name found","Keine Privacy-Liste mit diesem Namen gefunden"}.
|
||||
{"No private data found in this query","Keine privaten Daten in dieser Anfrage gefunden"}.
|
||||
{"No <privileged_iq/> element found","Kein <privileged_iq/>-Element gefunden"}.
|
||||
{"No running node found","Kein laufender Knoten gefunden"}.
|
||||
{"No services available","Keine Dienste verfügbar"}.
|
||||
{"No statistics found for this item","Keine Statistiken für dieses Item gefunden"}.
|
||||
@@ -407,6 +409,7 @@
|
||||
{"Restore binary backup immediately:","Stelle binäres Backup sofort wieder her:"}.
|
||||
{"Restore plain text backup immediately:","Stelle Klartext-Backup sofort wieder her:"}.
|
||||
{"Restore","Wiederherstellung"}.
|
||||
{"Result","Ergebnis"}.
|
||||
{"Roles and Affiliations that May Retrieve Member List","Rollen und Zugehörigkeiten die Mitgliederliste abrufen dürfen"}.
|
||||
{"Roles for which Presence is Broadcasted","Rollen für welche die Präsenz übertragen wird"}.
|
||||
{"Roles that May Send Private Messages","Rollen die Privatnachrichten senden dürfen"}.
|
||||
@@ -551,6 +554,7 @@
|
||||
{"Update message of the day on all hosts (don't send)","Aktualisiere Nachricht des Tages auf allen Hosts (nicht senden)"}.
|
||||
{"Update specs to get modules source, then install desired ones.","Aktualisieren Sie die Spezifikationen, um den Quellcode der Module zu erhalten und installieren Sie dann die gewünschten Module."}.
|
||||
{"Update Specs","Spezifikationen aktualisieren"}.
|
||||
{"Updating the vCard is not supported by the vCard storage backend","Aktualisierung der vCard wird vom vCard-Speicher-Backend nicht unterstützt"}.
|
||||
{"Upgrade","Upgrade"}.
|
||||
{"URL for Archived Discussion Logs","URL für archivierte Diskussionsprotokolle"}.
|
||||
{"User already exists","Benutzer existiert bereits"}.
|
||||
@@ -579,6 +583,7 @@
|
||||
{"Visitors are not allowed to send messages to all occupants","Besucher dürfen nicht an alle Teilnehmer Nachrichten versenden"}.
|
||||
{"Voice requests are disabled in this conference","Sprachrecht-Anforderungen sind in diesem Raum deaktiviert"}.
|
||||
{"Voice request","Sprachrecht-Anforderung"}.
|
||||
{"Web client which allows to join the room anonymously","Web-Client, der es ermöglicht, dem Raum anonym beizutreten"}.
|
||||
{"Wednesday","Mittwoch"}.
|
||||
{"When a new subscription is processed and whenever a subscriber comes online","Sobald ein neues Abonnement verarbeitet wird und wann immer ein Abonnent sich anmeldet"}.
|
||||
{"When a new subscription is processed","Sobald ein neues Abonnement verarbeitet wird"}.
|
||||
|
||||
+6
-2
@@ -46,7 +46,9 @@
|
||||
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","Cualquiera con una suscripción a la presencia de 'ambos' o 'de' puede suscribirse y recibir elementos"}.
|
||||
{"Anyone with Voice","Cualquiera con Voz"}.
|
||||
{"Anyone","Cualquiera"}.
|
||||
{"API Commands","Comandos API"}.
|
||||
{"April","Abril"}.
|
||||
{"Arguments","Argumentos"}.
|
||||
{"Attribute 'channel' is required for this request","El atributo 'channel' es necesario para esta petición"}.
|
||||
{"Attribute 'id' is mandatory for MIX messages","El atributo 'id' es necesario para mensajes MIX"}.
|
||||
{"Attribute 'jid' is not allowed here","El atributo 'jid' no está permitido aqui"}.
|
||||
@@ -86,6 +88,7 @@
|
||||
{"Choose whether to approve this entity's subscription.","Decidir si aprobar la subscripción de esta entidad."}.
|
||||
{"City","Ciudad"}.
|
||||
{"Client acknowledged more stanzas than sent by server","El cliente ha reconocido más paquetes de los que el servidor ha enviado"}.
|
||||
{"Clustering","Clustering"}.
|
||||
{"Commands","Comandos"}.
|
||||
{"Conference room does not exist","La sala de conferencias no existe"}.
|
||||
{"Configuration of room ~s","Configuración para la sala ~s"}.
|
||||
@@ -161,7 +164,7 @@
|
||||
{"Get Pending","Obtener pendientes"}.
|
||||
{"Get User Last Login Time","Ver fecha de la última conexión de usuario"}.
|
||||
{"Get User Statistics","Ver estadísticas de usuario"}.
|
||||
{"Given Name","Nombre"}.
|
||||
{"Given Name","Nombre de pila"}.
|
||||
{"Grant voice to this person?","¿Conceder voz a esta persona?"}.
|
||||
{"has been banned","ha sido bloqueado"}.
|
||||
{"has been kicked because of a system shutdown","ha sido expulsado porque el sistema se va a detener"}.
|
||||
@@ -295,7 +298,6 @@
|
||||
{"No pending subscriptions found","No se han encontrado suscripciones pendientes"}.
|
||||
{"No privacy list with this name found","No se ha encontrado una lista de privacidad con este nombre"}.
|
||||
{"No private data found in this query","No se ha encontrado ningún elemento de dato privado en esta petición"}.
|
||||
{"No <privileged_iq/> element found","No se encontró ningún elemento <privileged_iq/>"}.
|
||||
{"No running node found","No se ha encontrado ningún nodo activo"}.
|
||||
{"No services available","No hay servicios disponibles"}.
|
||||
{"No statistics found for this item","No se han encontrado estadísticas para este elemento"}.
|
||||
@@ -409,6 +411,7 @@
|
||||
{"Restore binary backup immediately:","Restaurar inmediatamente copia de seguridad binaria:"}.
|
||||
{"Restore plain text backup immediately:","Restaurar copias de seguridad de texto plano inmediatamente:"}.
|
||||
{"Restore","Restaurar"}.
|
||||
{"Result","Resultado"}.
|
||||
{"Roles and Affiliations that May Retrieve Member List","Roles y Afiliaciones que pueden obtener la lista de miembros"}.
|
||||
{"Roles for which Presence is Broadcasted","Roles para los que sí se difunde su Presencia"}.
|
||||
{"Roles that May Send Private Messages","Roles que pueden enviar mensajes privados"}.
|
||||
@@ -585,6 +588,7 @@
|
||||
{"Visitor","Visitante"}.
|
||||
{"Voice request","Petición de voz"}.
|
||||
{"Voice requests are disabled in this conference","Las peticiones de voz están desactivadas en esta sala"}.
|
||||
{"Web client which allows to join the room anonymously","Cliente web que permite entrar en la sala anonimamente"}.
|
||||
{"Wednesday","Miércoles"}.
|
||||
{"When a new subscription is processed and whenever a subscriber comes online","Cuando se procesa una nueva suscripción y cuando un suscriptor se conecta"}.
|
||||
{"When a new subscription is processed","Cuando se procesa una nueva suscripción"}.
|
||||
|
||||
@@ -295,7 +295,6 @@
|
||||
{"No pending subscriptions found","Nessuna sottoscrizione in attesa trovata"}.
|
||||
{"No privacy list with this name found","Nessun elenco di privacy con questo nome trovato"}.
|
||||
{"No private data found in this query","Non sono stati trovati dati privati in questa query"}.
|
||||
{"No <privileged_iq/> element found","Nessun elemento <privileged_iq/> trovato"}.
|
||||
{"No running node found","Nessun nodo in esecuzione trovato"}.
|
||||
{"No services available","Nessun servizio disponibile"}.
|
||||
{"No statistics found for this item","Nessuna statistica trovata per questa voce"}.
|
||||
|
||||
+5
-1
@@ -46,7 +46,9 @@
|
||||
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","Qualquer pessoa com uma assinatura presente dos dois ou de ambos pode se inscrever e recuperar os itens"}.
|
||||
{"Anyone with Voice","Qualquer pessoa com voz"}.
|
||||
{"Anyone","Qualquer pessoa"}.
|
||||
{"API Commands","Comandos API"}.
|
||||
{"April","Abril"}.
|
||||
{"Arguments","Argumentos"}.
|
||||
{"Attribute 'channel' is required for this request","O atributo 'canal' é necessário para esta solicitação"}.
|
||||
{"Attribute 'id' is mandatory for MIX messages","O atributo 'id' é obrigatório para mensagens MIX"}.
|
||||
{"Attribute 'jid' is not allowed here","O atributo 'jid' não é permitido aqui"}.
|
||||
@@ -86,6 +88,7 @@
|
||||
{"Choose whether to approve this entity's subscription.","Aprovar esta assinatura."}.
|
||||
{"City","Cidade"}.
|
||||
{"Client acknowledged more stanzas than sent by server","O cliente reconheceu mais estrofes do que as enviadas pelo servidor"}.
|
||||
{"Clustering","Agrupamento"}.
|
||||
{"Commands","Comandos"}.
|
||||
{"Conference room does not exist","A sala de conferência não existe"}.
|
||||
{"Configuration of room ~s","Configuração para ~s"}.
|
||||
@@ -295,7 +298,6 @@
|
||||
{"No pending subscriptions found","Não foram encontradas subscrições"}.
|
||||
{"No privacy list with this name found","Nenhuma lista de privacidade encontrada com este nome"}.
|
||||
{"No private data found in this query","Nenhum dado privado encontrado nesta consulta"}.
|
||||
{"No <privileged_iq/> element found","Nenhum elemento <privileged_iq/> foi encontrado"}.
|
||||
{"No running node found","Nenhum nó em execução foi encontrado"}.
|
||||
{"No services available","Não há serviços disponíveis"}.
|
||||
{"No statistics found for this item","Não foram encontradas estatísticas para este item"}.
|
||||
@@ -409,6 +411,7 @@
|
||||
{"Restore binary backup immediately:","Restaurar imediatamente o backup binário:"}.
|
||||
{"Restore plain text backup immediately:","Restaurar backup formato texto imediatamente:"}.
|
||||
{"Restore","Restaurar"}.
|
||||
{"Result","Resultado"}.
|
||||
{"Roles and Affiliations that May Retrieve Member List","As funções e as afiliações que podem recuperar a lista dos membros"}.
|
||||
{"Roles for which Presence is Broadcasted","Para quem a presença será notificada"}.
|
||||
{"Roles that May Send Private Messages","Atribuições que talvez possam enviar mensagens privadas"}.
|
||||
@@ -585,6 +588,7 @@
|
||||
{"Visitor","Visitante"}.
|
||||
{"Voice request","Requisição de voz"}.
|
||||
{"Voice requests are disabled in this conference","Requisições de voz estão desabilitadas nesta sala de conferência"}.
|
||||
{"Web client which allows to join the room anonymously","Cliente da web que permite entrar na sala de forma anônima"}.
|
||||
{"Wednesday","Quarta"}.
|
||||
{"When a new subscription is processed and whenever a subscriber comes online","Quando uma nova assinatura é processada e sempre que um assinante fica online"}.
|
||||
{"When a new subscription is processed","Quando uma nova assinatura é processada"}.
|
||||
|
||||
@@ -46,7 +46,9 @@
|
||||
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","Qualquer pessoa com uma assinatura presente dos dois ou de ambos pode se inscrever e recuperar os itens"}.
|
||||
{"Anyone with Voice","Qualquer pessoa com voz"}.
|
||||
{"Anyone","Qualquer pessoa"}.
|
||||
{"API Commands","Comandos API"}.
|
||||
{"April","Abril"}.
|
||||
{"Arguments","Argumentos"}.
|
||||
{"Attribute 'channel' is required for this request","O atributo 'canal' é necessário para esta solicitação"}.
|
||||
{"Attribute 'id' is mandatory for MIX messages","O atributo 'id' é obrigatório para mensagens MIX"}.
|
||||
{"Attribute 'jid' is not allowed here","O atributo 'jid' não é permitido aqui"}.
|
||||
@@ -86,6 +88,7 @@
|
||||
{"Choose whether to approve this entity's subscription.","Aprovar esta assinatura."}.
|
||||
{"City","Cidade"}.
|
||||
{"Client acknowledged more stanzas than sent by server","O cliente reconheceu mais estrofes do que as enviadas pelo servidor"}.
|
||||
{"Clustering","Agrupamento"}.
|
||||
{"Commands","Comandos"}.
|
||||
{"Conference room does not exist","A sala não existe"}.
|
||||
{"Configuration of room ~s","Configuração para ~s"}.
|
||||
@@ -168,6 +171,7 @@
|
||||
{"has been kicked because of an affiliation change","foi desconectado porque por afiliação inválida"}.
|
||||
{"has been kicked because the room has been changed to members-only","foi desconectado porque a política da sala mudou, só membros são permitidos"}.
|
||||
{"has been kicked","foi removido"}.
|
||||
{"Hash of the vCard-temp avatar of this room","Hash do avatar do vCard-temp desta sala"}.
|
||||
{"Hat title","Título do chapéu"}.
|
||||
{"Hat URI","URI do chapéu"}.
|
||||
{"Hats limit exceeded","O limite dos chapéus foi excedido"}.
|
||||
@@ -223,6 +227,7 @@
|
||||
{"leaves the room","Sair da sala"}.
|
||||
{"List of users with hats","Lista os utilizadores com chapéus"}.
|
||||
{"List users with hats","Lista os utilizadores com chapéus"}.
|
||||
{"Logged Out","Desconectado"}.
|
||||
{"Logging","Registando no log"}.
|
||||
{"Make participants list public","Tornar pública a lista de participantes"}.
|
||||
{"Make room CAPTCHA protected","Tornar protegida a palavra-passe da sala"}.
|
||||
@@ -406,6 +411,7 @@
|
||||
{"Restore binary backup immediately:","Restaurar imediatamente o backup binário:"}.
|
||||
{"Restore plain text backup immediately:","Restaurar backup formato texto imediatamente:"}.
|
||||
{"Restore","Restaurar"}.
|
||||
{"Result","Resultado"}.
|
||||
{"Roles and Affiliations that May Retrieve Member List","As funções e as afiliações que podem recuperar a lista dos membros"}.
|
||||
{"Roles for which Presence is Broadcasted","Para quem a presença será notificada"}.
|
||||
{"Roles that May Send Private Messages","Atribuições que talvez possam enviar mensagens privadas"}.
|
||||
@@ -437,6 +443,7 @@
|
||||
{"Set message of the day on all hosts and send to online users","Definir mensagem do dia em todos os hosts e enviar para os utilizadores online"}.
|
||||
{"Shared Roster Groups","Grupos Shared Roster"}.
|
||||
{"Show Integral Table","Mostrar Tabela Integral"}.
|
||||
{"Show Occupants Join/Leave","Mostrar a entrada e a saída de ocupantes"}.
|
||||
{"Show Ordinary Table","Mostrar Tabela Ordinária"}.
|
||||
{"Shut Down Service","Parar Serviço"}.
|
||||
{"SOCKS5 Bytestreams","Bytestreams SOCKS5"}.
|
||||
@@ -534,6 +541,7 @@
|
||||
{"Too many unacked stanzas","Quantidade excessiva de instâncias sem confirmação"}.
|
||||
{"Too many users in this conference","Há uma quantidade excessiva de utilizadores nesta conferência"}.
|
||||
{"Traffic rate limit is exceeded","Limite de banda excedido"}.
|
||||
{"~ts's MAM Archive","Arquivo ~ts's MAM"}.
|
||||
{"~ts's Offline Messages Queue","~s's Fila de Mensagens Offline"}.
|
||||
{"Tuesday","Terça"}.
|
||||
{"Unable to generate a CAPTCHA","Impossível gerar um CAPTCHA"}.
|
||||
@@ -550,12 +558,14 @@
|
||||
{"Update message of the day on all hosts (don't send)","Atualizar a mensagem do dia em todos os host (não enviar)"}.
|
||||
{"Update specs to get modules source, then install desired ones.","Atualize as especificações para obter a fonte dos módulos e instale os que desejar."}.
|
||||
{"Update Specs","Atualizar as especificações"}.
|
||||
{"Updating the vCard is not supported by the vCard storage backend","A atualização do vCard não é compatível com o back-end de armazenamento do vCard"}.
|
||||
{"Upgrade","Atualização"}.
|
||||
{"URL for Archived Discussion Logs","A URL para o arquivamento dos registos da discussão"}.
|
||||
{"User already exists","Utilizador já existe"}.
|
||||
{"User (jid)","Utilizador (jid)"}.
|
||||
{"User JID","Utilizador JID"}.
|
||||
{"User Management","Gestão de utilizadores"}.
|
||||
{"User not allowed to perform an IQ set on another user's vCard.","O utilizador não tem permissão para executar um conjunto de QI no vCard de outro utilizador."}.
|
||||
{"User removed","O utilizador foi removido"}.
|
||||
{"User session not found","A sessão do utilizador não foi encontrada"}.
|
||||
{"User session terminated","Sessão de utilizador terminada"}.
|
||||
@@ -578,6 +588,7 @@
|
||||
{"Visitor","Visitante"}.
|
||||
{"Voice request","Requisição de voz"}.
|
||||
{"Voice requests are disabled in this conference","Requisições de voz estão desativadas nesta sala de conferência"}.
|
||||
{"Web client which allows to join the room anonymously","Cliente da web que permite entrar na sala de forma anônima"}.
|
||||
{"Wednesday","Quarta"}.
|
||||
{"When a new subscription is processed and whenever a subscriber comes online","Quando uma nova assinatura é processada e sempre que um assinante fica online"}.
|
||||
{"When a new subscription is processed","Quando uma nova assinatura é processada"}.
|
||||
|
||||
+2
-1
@@ -28,7 +28,9 @@
|
||||
{"Anyone may publish","Gjithkush mund të publikojë"}.
|
||||
{"Anyone with Voice","Cilido me Zë"}.
|
||||
{"Anyone","Cilido"}.
|
||||
{"API Commands","Urdhra API"}.
|
||||
{"April","Prill"}.
|
||||
{"Arguments","Argumente"}.
|
||||
{"Attribute 'channel' is required for this request","Atributi 'channel' është i domosdoshëm për këtë kërkesë"}.
|
||||
{"Attribute 'jid' is not allowed here","Atributi 'jid' s’lejohet këtu"}.
|
||||
{"Attribute 'node' is not allowed here","Atributi 'node' s’lejohet këtu"}.
|
||||
@@ -186,7 +188,6 @@
|
||||
{"No node specified","S’u përcaktua nyjë"}.
|
||||
{"No pending subscriptions found","S’u gjetën pajtime pezull"}.
|
||||
{"No privacy list with this name found","S’u gjet listë privatësie me atë emër"}.
|
||||
{"No <privileged_iq/> element found","S’u gjetën elementë <privileged_iq/>"}.
|
||||
{"No running node found","S’u gjet nyjë në funksionim"}.
|
||||
{"No services available","S’ka shërbime të gatshme"}.
|
||||
{"No statistics found for this item","S’u gjetën statistika për këtë objekt"}.
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
{"Chatrooms","Chattrum"}.
|
||||
{"Choose a username and password to register with this server","Välj ett användarnamn och lösenord för att registrera mot denna server"}.
|
||||
{"Choose storage type of tables","Välj lagringstyp för tabeller"}.
|
||||
{"Choose whether to approve this entity's subscription.","Välj om du vill godkänna hela denna prenumertion."}.
|
||||
{"City","Stad"}.
|
||||
{"Commands","Kommandon"}.
|
||||
{"Conference room does not exist","Rummet finns inte"}.
|
||||
@@ -196,7 +195,6 @@
|
||||
{"Search users in ","Sök efter användare på "}.
|
||||
{"Send announcement to all online users on all hosts","Sänd meddelanden till alla inloggade användare på alla värdar"}.
|
||||
{"Send announcement to all online users","Sänd meddelanden till alla inloggade användare"}.
|
||||
{"Send announcement to all users on all hosts","Sänd meddelanden till alla användare på alla värdar"}.
|
||||
{"Send announcement to all users","Sänd meddelanden till alla användare"}.
|
||||
{"September","September"}.
|
||||
{"Set message of the day and send to online users","Sätt dagens status meddelande och skicka till alla användare"}.
|
||||
|
||||
@@ -0,0 +1,625 @@
|
||||
%% Generated automatically
|
||||
%% DO NOT EDIT: run `make translations` instead
|
||||
%% To improve translations please read:
|
||||
%% https://docs.ejabberd.im/developer/extending-ejabberd/localization/
|
||||
|
||||
{" (Add * to the end of field to match substring)"," (அடி மூலக்கூறுடன் பொருந்தக்கூடிய புலத்தின் முடிவில் * சேர்க்கவும்)"}.
|
||||
{" has set the subject to: "," இதற்கு பொருள் அமைத்துள்ளது: "}.
|
||||
{"# participants","# பங்கேற்பாளர்கள்"}.
|
||||
{"A description of the node","முனையின் விளக்கம்"}.
|
||||
{"A friendly name for the node","முனைக்கு ஒரு நட்பு பெயர்"}.
|
||||
{"A password is required to enter this room","இந்த அறைக்குள் நுழைய கடவுச்சொல் தேவை"}.
|
||||
{"A Web Page","ஒரு வலைப்பக்கம்"}.
|
||||
{"Accept","ஏற்றுக்கொள்"}.
|
||||
{"Access denied by service policy","பணி கொள்கையால் மறுக்கப்பட்டது"}.
|
||||
{"Access model","அணுகல் மாதிரி"}.
|
||||
{"Account doesn't exist","கணக்கு இல்லை"}.
|
||||
{"Action on user","பயனரின் செயல்"}.
|
||||
{"Add a hat to a user","ஒரு பயனருக்கு ஒரு தொப்பியைச் சேர்க்கவும்"}.
|
||||
{"Add User","பயனரைச் சேர்க்கவும்"}.
|
||||
{"Administration of ","நிர்வாகம் "}.
|
||||
{"Administration","நிர்வாகம்"}.
|
||||
{"Administrator privileges required","நிர்வாகி சலுகைகள் தேவை"}.
|
||||
{"All activity","அனைத்து செயல்பாடுகளும்"}.
|
||||
{"All Users","அனைத்து பயனர்களும்"}.
|
||||
{"Allow subscription","சந்தாவை அனுமதிக்கவும்"}.
|
||||
{"Allow this Jabber ID to subscribe to this pubsub node?","இந்த பப்சப் முனைக்கு குழுசேர இந்த சாபர் ஐடியை அனுமதிக்கவா?"}.
|
||||
{"Allow this person to register with the room?","இந்த நபரை அறையில் பதிவு செய்ய அனுமதிக்கவா?"}.
|
||||
{"Allow users to change the subject","இந்த விசயத்தை மாற்ற பயனர்களை அனுமதிக்கவும்"}.
|
||||
{"Allow users to query other users","பயனர்களை மற்ற பயனர்களை வினவ அனுமதிக்கவும்"}.
|
||||
{"Allow users to send invites","அழைப்புகளை அனுப்ப பயனர்களை அனுமதிக்கவும்"}.
|
||||
{"Allow users to send private messages","தனிப்பட்ட செய்திகளை அனுப்ப பயனர்களை அனுமதிக்கவும்"}.
|
||||
{"Allow visitors to change nickname","பார்வையாளர்களை புனைப்பெயரை மாற்ற அனுமதிக்கவும்"}.
|
||||
{"Allow visitors to send private messages to","தனிப்பட்ட செய்திகளை அனுப்ப பார்வையாளர்களை அனுமதிக்கவும்"}.
|
||||
{"Allow visitors to send status text in presence updates","முன்னிலையில் புதுப்பிப்புகளில் நிலை உரையை அனுப்ப பார்வையாளர்களை அனுமதிக்கவும்"}.
|
||||
{"Allow visitors to send voice requests","குரல் கோரிக்கைகளை அனுப்ப பார்வையாளர்களை அனுமதிக்கவும்"}.
|
||||
{"An associated LDAP group that defines room membership; this should be an LDAP Distinguished Name according to an implementation-specific or deployment-specific definition of a group.","அறை உறுப்பினர்களை வரையறுக்கும் தொடர்புடைய எல்.டி.ஏ.பி குழு; இது ஒரு குழுவின் செயல்படுத்தல்-குறிப்பிட்ட அல்லது வரிசைப்படுத்தல்-குறிப்பிட்ட வரையறையின்படி எல்.டி.ஏ.பி புகழ்பெற்ற பெயராக இருக்க வேண்டும்."}.
|
||||
{"Announcements","அறிவிப்புகள்"}.
|
||||
{"Answer associated with a picture","ஒரு படத்துடன் தொடர்புடைய பதில்"}.
|
||||
{"Answer associated with a video","வீடியோவுடன் தொடர்புடைய பதில்"}.
|
||||
{"Answer associated with speech","பேச்சுடன் தொடர்புடைய பதில்"}.
|
||||
{"Answer to a question","ஒரு கேள்விக்கு பதில்"}.
|
||||
{"Anyone in the specified roster group(s) may subscribe and retrieve items","குறிப்பிட்ட ரோச்டர் குழு (கள்) இல் உள்ள எவரும் உருப்படிகளை குழுசேரலாம் மற்றும் மீட்டெடுக்கலாம்"}.
|
||||
{"Anyone may associate leaf nodes with the collection","எவரும் இலை முனைகளை சேகரிப்புடன் தொடர்புபடுத்தலாம்"}.
|
||||
{"Anyone may publish","எவரும் வெளியிடலாம்"}.
|
||||
{"Anyone may subscribe and retrieve items","எவரும் பொருட்களை குழுசேர் மற்றும் மீட்டெடுக்கலாம்"}.
|
||||
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","அல்லது இரண்டின் இருப்பு சந்தா உள்ள எவரும் உருப்படிகளை குழுசேர் மற்றும் மீட்டெடுக்கலாம்"}.
|
||||
{"Anyone with Voice","குரல் உள்ள எவரும்"}.
|
||||
{"Anyone","யாரும்"}.
|
||||
{"April","ப-சித்திரை"}.
|
||||
{"Attribute 'channel' is required for this request","இந்த கோரிக்கைக்கு 'சேனல்' என்ற பண்புக்கூறு தேவை"}.
|
||||
{"Attribute 'id' is mandatory for MIX messages","கலவை செய்திகளுக்கு 'ஐடி' கட்டாயமாகும்"}.
|
||||
{"Attribute 'jid' is not allowed here","'சிட்' என்ற பண்புக்கூறு இங்கே அனுமதிக்கப்படவில்லை"}.
|
||||
{"Attribute 'node' is not allowed here","'முனை' என்ற பண்புக்கூறு இங்கே அனுமதிக்கப்படவில்லை"}.
|
||||
{"Attribute 'to' of stanza that triggered challenge","சவாலைத் தூண்டும் சரணத்தின் '' 'என்ற பண்புக்கூறு"}.
|
||||
{"August","ஆ-ஆவணி"}.
|
||||
{"Automatic node creation is not enabled","தானியங்கி முனை உருவாக்கம் இயக்கப்படவில்லை"}.
|
||||
{"Backup Management","காப்பு மேலாண்மை"}.
|
||||
{"Backup of ~p","~p இன் காப்புப்பிரதி"}.
|
||||
{"Backup to File at ","தாக்கல் செய்ய காப்புப்பிரதி "}.
|
||||
{"Backup","காப்புப்பிரதி"}.
|
||||
{"Bad format","மோசமான வடிவம்"}.
|
||||
{"Birthday","பிறந்த நாள்"}.
|
||||
{"Both the username and the resource are required","பயனர்பெயர் மற்றும் சான்று இரண்டும் தேவை"}.
|
||||
{"Bytestream already activated","பைட்டெச்ட்ரீம் ஏற்கனவே செயல்படுத்தப்பட்டது"}.
|
||||
{"Cannot remove active list","செயலில் உள்ள பட்டியலை அகற்ற முடியாது"}.
|
||||
{"Cannot remove default list","இயல்புநிலை பட்டியலை அகற்ற முடியாது"}.
|
||||
{"CAPTCHA web page","கேப்ட்சா வலைப்பக்கம்"}.
|
||||
{"Challenge ID","அறைகூவல் ஐடி"}.
|
||||
{"Change Password","கடவுச்சொல்லை மாற்றவும்"}.
|
||||
{"Change User Password","பயனர் கடவுச்சொல்லை மாற்றவும்"}.
|
||||
{"Changing password is not allowed","கடவுச்சொல்லை மாற்ற அனுமதிக்கப்படவில்லை"}.
|
||||
{"Changing role/affiliation is not allowed","பங்கு/இணைப்பை மாற்ற அனுமதிக்கப்படவில்லை"}.
|
||||
{"Channel already exists","சேனல் ஏற்கனவே உள்ளது"}.
|
||||
{"Channel does not exist","சேனல் இல்லை"}.
|
||||
{"Channel JID","சேனல் சிட்"}.
|
||||
{"Channels","சேனல்கள்"}.
|
||||
{"Characters not allowed:","எழுத்துக்கள் அனுமதிக்கப்படவில்லை:"}.
|
||||
{"Chatroom configuration modified","அரட்டை உள்ளமைவு மாற்றப்பட்டது"}.
|
||||
{"Chatroom is created","அரட்டை அறை உருவாக்கப்பட்டது"}.
|
||||
{"Chatroom is destroyed","அரட்டை அறை அழிக்கப்படுகிறது"}.
|
||||
{"Chatroom is started","அரட்டை அறை தொடங்கப்பட்டது"}.
|
||||
{"Chatroom is stopped","அரட்டை அறை நிறுத்தப்பட்டது"}.
|
||||
{"Chatrooms","அரட்டை அறைகள்"}.
|
||||
{"Choose a username and password to register with this server","இந்த சேவையகத்துடன் பதிவு செய்ய பயனர்பெயர் மற்றும் கடவுச்சொல்லைத் தேர்வுசெய்க"}.
|
||||
{"Choose storage type of tables","அட்டவணைகளின் சேமிப்பக வகை என்பதைத் தேர்வுசெய்க"}.
|
||||
{"Choose whether to approve this entity's subscription.","இந்த நிறுவனத்தின் சந்தாவை அங்கீகரிக்க வேண்டுமா என்பதைத் தேர்வுசெய்க."}.
|
||||
{"City","நகரம்"}.
|
||||
{"Client acknowledged more stanzas than sent by server","சேவையகத்தால் அனுப்பப்பட்டதை விட கிளையன்ட் அதிக சரணத்தை ஒப்புக் கொண்டார்"}.
|
||||
{"Commands","கட்டளைகள்"}.
|
||||
{"Conference room does not exist","மாநாட்டு அறை இல்லை"}.
|
||||
{"Configuration of room ~s","அறையின் உள்ளமைவு ~s"}.
|
||||
{"Configuration","உள்ளமைவு"}.
|
||||
{"Contact Addresses (normally, room owner or owners)","தொடர்பு முகவரிகள் (பொதுவாக, அறை உரிமையாளர் அல்லது உரிமையாளர்கள்)"}.
|
||||
{"Country","நாடு"}.
|
||||
{"Current Discussion Topic","தற்போதைய கலந்துரையாடல் தலைப்பு"}.
|
||||
{"Database failure","தரவுத்தள தோல்வி"}.
|
||||
{"Database Tables Configuration at ","தரவுத்தள அட்டவணைகள் உள்ளமைவு "}.
|
||||
{"Database","தரவுத்தளம்"}.
|
||||
{"December","கா-மார்கழி"}.
|
||||
{"Default users as participants","பங்கேற்பாளர்களாக இயல்புநிலை பயனர்கள்"}.
|
||||
{"Delete message of the day on all hosts","அனைத்து புரவலர்களிலும் அன்றைய செய்தியை நீக்கு"}.
|
||||
{"Delete message of the day","அன்றைய செய்தியை நீக்கு"}.
|
||||
{"Delete User","பயனரை நீக்கு"}.
|
||||
{"Deliver event notifications","நிகழ்வு அறிவிப்புகளை வழங்கவும்"}.
|
||||
{"Deliver payloads with event notifications","நிகழ்வு அறிவிப்புகளுடன் பேலோடுகளை வழங்கவும்"}.
|
||||
{"Disc only copy","வட்டு மட்டுமே நகலெடுக்கவும்"}.
|
||||
{"Don't tell your password to anybody, not even the administrators of the XMPP server.","உங்கள் கடவுச்சொல்லை யாரிடமும் சொல்லாதீர்கள், எக்ச்எம்பி.பி சேவையகத்தின் நிர்வாகிகள் கூட இல்லை."}.
|
||||
{"Dump Backup to Text File at ","உரை கோப்பில் காப்புப்பிரதியை டம்ப் செய்யுங்கள் "}.
|
||||
{"Dump to Text File","உரை கோப்பில் டம்ப் செய்யுங்கள்"}.
|
||||
{"Duplicated groups are not allowed by RFC6121","நகல் குழுக்கள் RFC6121 ஆல் அனுமதிக்கப்படவில்லை"}.
|
||||
{"Dynamically specify a replyto of the item publisher","உருப்படி வெளியீட்டாளரின் பதிலை மாறும் வகையில் குறிப்பிடவும்"}.
|
||||
{"Edit Properties","பண்புகளைத் திருத்து"}.
|
||||
{"Either approve or decline the voice request.","குரல் கோரிக்கையை அங்கீகரிக்கவும் அல்லது நிராகரிக்கவும்."}.
|
||||
{"ejabberd HTTP Upload service","EJABBERD HTTP பதிவேற்ற பணி"}.
|
||||
{"ejabberd MUC module","EJABBERD MUC தொகுதி"}.
|
||||
{"ejabberd Multicast service","எசாபர்ட் மல்டிகாச்ட் பணி"}.
|
||||
{"ejabberd Publish-Subscribe module","EJABBERD வெளியீட்டு-சந்தா தொகுதி"}.
|
||||
{"ejabberd SOCKS5 Bytestreams module","EJABBERD SOCKS5 BYTESTREAMS தொகுதி"}.
|
||||
{"ejabberd vCard module","EJABBERD VCARD தொகுதி"}.
|
||||
{"ejabberd Web Admin","எசாபர்ட் வலை நிர்வாகி"}.
|
||||
{"ejabberd","எசாபர்ட்"}.
|
||||
{"Email Address","மின்னஞ்சல் முகவரி"}.
|
||||
{"Email","மின்னஞ்சல்"}.
|
||||
{"Enable hats","தொப்பிகளை இயக்கவும்"}.
|
||||
{"Enable logging","பதிவை இயக்கவும்"}.
|
||||
{"Enable message archiving","செய்தி காப்பகத்தை இயக்கவும்"}.
|
||||
{"Enabling push without 'node' attribute is not supported","'முனை' பண்புக்கூறு இல்லாமல் உந்துதலை இயக்குவது ஆதரிக்கப்படவில்லை"}.
|
||||
{"End User Session","இறுதி பயனர் அமர்வு"}.
|
||||
{"Enter nickname you want to register","நீங்கள் பதிவு செய்ய விரும்பும் புனைப்பெயரை உள்ளிடவும்"}.
|
||||
{"Enter path to backup file","காப்புப்பிரதி கோப்பிற்கு பாதையை உள்ளிடவும்"}.
|
||||
{"Enter path to jabberd14 spool dir","Jabberd14 Spool அடைவு க்கு பாதையை உள்ளிடவும்"}.
|
||||
{"Enter path to jabberd14 spool file","சாபர்ட் 14 ச்பூல் கோப்புக்கு பாதையை உள்ளிடவும்"}.
|
||||
{"Enter path to text file","உரை கோப்புக்கு பாதையை உள்ளிடவும்"}.
|
||||
{"Enter the text you see","நீங்கள் பார்க்கும் உரையை உள்ளிடவும்"}.
|
||||
{"Erlang XMPP Server","எர்லாங் எக்ச்எம்பிபி சேவையகம்"}.
|
||||
{"Exclude Jabber IDs from CAPTCHA challenge","கேப்ட்சா சேலஞ்சில் இருந்து சாபர் ஐடிகளை விலக்குங்கள்"}.
|
||||
{"Export all tables as SQL queries to a file:","அனைத்து அட்டவணைகளையும் கவிமொ வினவல்களாக ஒரு கோப்பில் ஏற்றுமதி செய்யுங்கள்:"}.
|
||||
{"Export data of all users in the server to PIEFXIS files (XEP-0227):","சேவையகத்தில் உள்ள அனைத்து பயனர்களின் தரவை Piefxis கோப்புகளுக்கு (XEP-0227) ஏற்றுமதி செய்யுங்கள்:"}.
|
||||
{"Export data of users in a host to PIEFXIS files (XEP-0227):","ஓச்டில் பயனர்களின் தரவை Piefxis கோப்புகளுக்கு ஏற்றுமதி செய்யுங்கள் (XEP-0227):"}.
|
||||
{"External component failure","வெளிப்புற கூறு தோல்வி"}.
|
||||
{"External component timeout","வெளிப்புற கூறு நேரம் முடிந்தது"}.
|
||||
{"Failed to activate bytestream","பைட்டெச்ட்ரீமை செயல்படுத்தத் தவறிவிட்டது"}.
|
||||
{"Failed to extract JID from your voice request approval","உங்கள் குரல் கோரிக்கை ஒப்புதலிலிருந்து சிட் பிரித்தெடுப்பதில் தோல்வி"}.
|
||||
{"Failed to map delegated namespace to external component","வெளிப்புற கூறுகளுக்கு பிரதிநிதித்துவ பெயர்வெளியை வரைபடமாக்குவதில் தோல்வி"}.
|
||||
{"Failed to parse HTTP response","HTTP பதிலை அலசத் தவறிவிட்டது"}.
|
||||
{"Failed to process option '~s'","விருப்பத்தை '~s' செயலாக்குவதில் தோல்வி"}.
|
||||
{"Family Name","குடும்ப பெயர்"}.
|
||||
{"FAQ Entry","கேள்விகள் நுழைவு"}.
|
||||
{"February","தை-மாசி"}.
|
||||
{"File larger than ~w bytes","~w பைட்டுகளை விட பெரியது"}.
|
||||
{"Fill in the form to search for any matching XMPP User","பொருந்தக்கூடிய எக்ச்எம்பிபி பயனரைத் தேட படிவத்தை நிரப்பவும்"}.
|
||||
{"Friday","வெள்ளிக்கிழமை"}.
|
||||
{"From ~ts","~ts இலிருந்து"}.
|
||||
{"Full List of Room Admins","அறை நிர்வாகிகளின் முழு பட்டியல்"}.
|
||||
{"Full List of Room Owners","அறை உரிமையாளர்களின் முழு பட்டியல்"}.
|
||||
{"Full Name","முழு பெயர்"}.
|
||||
{"Get List of Online Users","நிகழ்நிலை பயனர்களின் பட்டியலைப் பெறுங்கள்"}.
|
||||
{"Get List of Registered Users","பதிவுசெய்யப்பட்ட பயனர்களின் பட்டியலைப் பெறுங்கள்"}.
|
||||
{"Get Number of Online Users","நிகழ்நிலை பயனர்களின் எண்ணிக்கையைப் பெறுங்கள்"}.
|
||||
{"Get Number of Registered Users","பதிவுசெய்யப்பட்ட பயனர்களின் எண்ணிக்கையைப் பெறுங்கள்"}.
|
||||
{"Get Pending","நிலுவையில் செல்லுங்கள்"}.
|
||||
{"Get User Last Login Time","பயனர் கடைசி உள்நுழைவு நேரத்தைப் பெறுங்கள்"}.
|
||||
{"Get User Statistics","பயனர் புள்ளிவிவரங்களைப் பெறுங்கள்"}.
|
||||
{"Given Name","கொடுக்கப்பட்ட பெயர்"}.
|
||||
{"Grant voice to this person?","இந்த நபருக்கு குரல் கொடுக்கவா?"}.
|
||||
{"has been banned","தடைசெய்யப்பட்டுள்ளது"}.
|
||||
{"has been kicked because of a system shutdown","கணினி பணிநிறுத்தம் காரணமாக உதைக்கப்பட்டுள்ளது"}.
|
||||
{"has been kicked because of an affiliation change","இணைப்பு மாற்றம் காரணமாக உதைக்கப்பட்டுள்ளது"}.
|
||||
{"has been kicked because the room has been changed to members-only","அறை உறுப்பினர்களுக்கு மட்டுமே மாற்றப்பட்டதால் உதைக்கப்பட்டுள்ளது"}.
|
||||
{"has been kicked","உதைக்கப்பட்டுள்ளது"}.
|
||||
{"Hash of the vCard-temp avatar of this room","இந்த அறையின் vcard-temp அவதாரத்தின் ஆச்"}.
|
||||
{"Hat title","தொப்பி தலைப்பு"}.
|
||||
{"Hat URI","தொப்பி யூரி"}.
|
||||
{"Hats limit exceeded","தொப்பிகள் வரம்பு மீறியது"}.
|
||||
{"Host unknown","புரவலன் தெரியவில்லை"}.
|
||||
{"HTTP File Upload","HTTP கோப்பு பதிவேற்றம்"}.
|
||||
{"Idle connection","செயலற்ற இணைப்பு"}.
|
||||
{"If you don't see the CAPTCHA image here, visit the web page.","நீங்கள் இங்கே கேப்ட்சா படத்தைக் காணவில்லை என்றால், வலைப்பக்கத்தைப் பார்வையிடவும்."}.
|
||||
{"Import Directory","இறக்குமதி அடைவு"}.
|
||||
{"Import File","கோப்பு இறக்குமதி"}.
|
||||
{"Import user data from jabberd14 spool file:","சாபர்ட் 14 ச்பூல் கோப்பிலிருந்து பயனர் தரவை இறக்குமதி செய்யுங்கள்:"}.
|
||||
{"Import User from File at ","கோப்பிலிருந்து பயனரை இறக்குமதி செய்யுங்கள் "}.
|
||||
{"Import users data from a PIEFXIS file (XEP-0227):","PIEFXIS கோப்பிலிருந்து (XEP-0227) பயனர்களின் தரவை இறக்குமதி செய்யுங்கள்:"}.
|
||||
{"Import users data from jabberd14 spool directory:","சாபர்ட் 14 ச்பூல் கோப்பகத்திலிருந்து பயனர்களின் தரவை இறக்குமதி செய்யுங்கள்:"}.
|
||||
{"Import Users from Dir at ","அடைவு இலிருந்து பயனர்களை இறக்குமதி செய்யுங்கள் "}.
|
||||
{"Import Users From jabberd14 Spool Files","சாபர்ட் 14 ச்பூல் கோப்புகளிலிருந்து பயனர்களை இறக்குமதி செய்யுங்கள்"}.
|
||||
{"Improper domain part of 'from' attribute","'ஃப்ரம்' பண்புக்கூறின் முறையற்ற டொமைன் பகுதி"}.
|
||||
{"Improper message type","முறையற்ற செய்தி வகை"}.
|
||||
{"Incorrect CAPTCHA submit","தவறான கேப்ட்சா சமர்ப்பிக்கவும்"}.
|
||||
{"Incorrect data form","தவறான தரவு வடிவம்"}.
|
||||
{"Incorrect password","தவறான கடவுச்சொல்"}.
|
||||
{"Incorrect value of 'action' attribute","'செயல்' பண்புக்கூறின் தவறான மதிப்பு"}.
|
||||
{"Incorrect value of 'action' in data form","தரவு வடிவத்தில் 'செயல்' இன் தவறான மதிப்பு"}.
|
||||
{"Incorrect value of 'path' in data form","தரவு வடிவத்தில் 'பாதை' இன் தவறான மதிப்பு"}.
|
||||
{"Installed Modules:","நிறுவப்பட்ட தொகுதிகள்:"}.
|
||||
{"Install","நிறுவவும்"}.
|
||||
{"Insufficient privilege","போதிய சலுகை"}.
|
||||
{"Internal server error","உள் சேவையக பிழை"}.
|
||||
{"Invalid 'from' attribute in forwarded message","அனுப்பப்பட்ட செய்தியில் 'இலிருந்து' பண்புக்கூறு"}.
|
||||
{"Invalid node name","தவறான முனை பெயர்"}.
|
||||
{"Invalid 'previd' value","தவறான 'முந்தைய' மதிப்பு"}.
|
||||
{"Invitations are not allowed in this conference","இந்த மாநாட்டில் அழைப்புகள் அனுமதிக்கப்படவில்லை"}.
|
||||
{"IP addresses","ஐபி முகவரிகள்"}.
|
||||
{"is now known as","இப்போது அழைக்கப்படுகிறது"}.
|
||||
{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","பிழை செய்திகளை அறைக்கு அனுப்ப அனுமதிக்கப்படவில்லை. பங்கேற்பாளர் (~s) ஒரு பிழை செய்தியை (~s) அனுப்பி அறையிலிருந்து உதைத்துள்ளார்"}.
|
||||
{"It is not allowed to send private messages of type \"groupchat\"","\"குரூப்சாட்\" என்ற வகை தனிப்பட்ட செய்திகளை அனுப்ப அனுமதிக்கப்படவில்லை"}.
|
||||
{"It is not allowed to send private messages to the conference","தனிப்பட்ட செய்திகளை மாநாட்டிற்கு அனுப்ப அனுமதிக்கப்படவில்லை"}.
|
||||
{"Jabber ID","சாபர் ஐடி"}.
|
||||
{"January","மா-தை"}.
|
||||
{"JID normalization denied by service policy","பணி கொள்கையால் மறுக்கப்பட்ட சிட் இயல்பாக்கம்"}.
|
||||
{"JID normalization failed","சிட் இயல்பாக்கம் தோல்வியடைந்தது"}.
|
||||
{"Joined MIX channels of ~ts","~ts இன் கலவை சேனல்களில் சேர்ந்தது"}.
|
||||
{"Joined MIX channels:","இணைந்த கலவை சேனல்கள்:"}.
|
||||
{"joins the room","அறையில் இணைகிறது"}.
|
||||
{"July","ஆ-ஆடி"}.
|
||||
{"June","வை-ஆனி"}.
|
||||
{"Just created","இப்போது உருவாக்கப்பட்டது"}.
|
||||
{"Last Activity","கடைசி செயல்பாடு"}.
|
||||
{"Last login","கடைசி உள்நுழைவு"}.
|
||||
{"Last message","கடைசி செய்தி"}.
|
||||
{"Last month","கடந்த மாதம்"}.
|
||||
{"Last year","கடந்த ஆண்டு"}.
|
||||
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","உரையின் SHA-256 ஆசின் குறைந்த குறிப்பிடத்தக்க பிட்கள் எக்சாடெசிமல் சிட்டை சமமாக இருக்க வேண்டும்"}.
|
||||
{"leaves the room","அறையை விட்டு வெளியேறுகிறது"}.
|
||||
{"List of users with hats","தொப்பிகளைக் கொண்ட பயனர்களின் பட்டியல்"}.
|
||||
{"List users with hats","தொப்பிகளுடன் பயனர்களை பட்டியலிடுங்கள்"}.
|
||||
{"Logged Out","வெளியேறியது"}.
|
||||
{"Logging","பதிவு"}.
|
||||
{"Make participants list public","பங்கேற்பாளர்கள் பட்டியலிடுங்கள்"}.
|
||||
{"Make room CAPTCHA protected","அறை கேப்ட்சா பாதுகாக்கவும்"}.
|
||||
{"Make room members-only","அறை உறுப்பினர்களை மட்டும் செய்யுங்கள்"}.
|
||||
{"Make room moderated","அறை மிதமானதாக்குங்கள்"}.
|
||||
{"Make room password protected","அறை கடவுச்சொல்லைப் பாதுகாக்கவும்"}.
|
||||
{"Make room persistent","அறையை தொடர்ந்து செய்யுங்கள்"}.
|
||||
{"Make room public searchable","அறையை பொதுவில் தேடலாம்"}.
|
||||
{"Malformed username","தவறான பயனர்பெயர்"}.
|
||||
{"MAM preference modification denied by service policy","பணி கொள்கையால் மறுக்கப்பட்ட மாம் விருப்பத்தேர்வு மாற்றம்"}.
|
||||
{"March","மா-பங்குனி"}.
|
||||
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","அதிகபட்சம் # தொடர்ச்சியாக இருக்க வேண்டும், அல்லது அதிகபட்சமாக விதிக்கப்பட்ட சேவையகத்தைத் தவிர வேறு எந்த குறிப்பிட்ட வரம்பும் இல்லாமல் `அதிகபட்சம்"}.
|
||||
{"Max payload size in bytes","பைட்டுகளில் அதிகபட்ச பேலோட் அளவு"}.
|
||||
{"Maximum file size","அதிகபட்ச கோப்பு அளவு"}.
|
||||
{"Maximum Number of History Messages Returned by Room","அறையால் திரும்பிய அதிகபட்ச வரலாற்று செய்திகளின் எண்ணிக்கை"}.
|
||||
{"Maximum number of items to persist","தொடர்ந்து அதிகபட்ச உருப்படிகளின் எண்ணிக்கை"}.
|
||||
{"Maximum Number of Occupants","அதிகபட்ச குடியிருப்பாளர்களின் எண்ணிக்கை"}.
|
||||
{"May","சி-வைகாசி"}.
|
||||
{"Membership is required to enter this room","இந்த அறைக்குள் நுழைய உறுப்பினர் தேவை"}.
|
||||
{"Memorize your password, or write it in a paper placed in a safe place. In XMPP there isn't an automated way to recover your password if you forget it.","உங்கள் கடவுச்சொல்லை மனப்பாடம் செய்யுங்கள், அல்லது பாதுகாப்பான இடத்தில் வைக்கப்பட்டுள்ள ஒரு காகிதத்தில் எழுதுங்கள். உங்கள் கடவுச்சொல்லை மறந்துவிட்டால் அதை மீட்டெடுக்க எக்ச்எம்பிபியில் தானியங்கு வழி இல்லை."}.
|
||||
{"Mere Availability in XMPP (No Show Value)","எக்ச்எம்பிபியில் வெறும் கிடைக்கும் (காட்சி மதிப்பு இல்லை)"}.
|
||||
{"Message body","செய்தி உடல்"}.
|
||||
{"Message not found in forwarded payload","அனுப்பப்பட்ட பேலோடில் செய்தி காணப்படவில்லை"}.
|
||||
{"Messages from strangers are rejected","அந்நியர்களிடமிருந்து செய்திகள் நிராகரிக்கப்படுகின்றன"}.
|
||||
{"Messages of type headline","வகை தலைப்பின் செய்திகள்"}.
|
||||
{"Messages of type normal","வகை இயல்பான செய்திகள்"}.
|
||||
{"Middle Name","நடுத்தர பெயர்"}.
|
||||
{"Minimum interval between voice requests (in seconds)","குரல் கோரிக்கைகளுக்கு இடையில் குறைந்தபட்ச இடைவெளி (நொடிகளில்)"}.
|
||||
{"Moderator privileges required","மதிப்பீட்டாளர் சலுகைகள் தேவை"}.
|
||||
{"Moderators Only","மதிப்பீட்டாளர்கள் மட்டுமே"}.
|
||||
{"Moderator","மதிப்பீட்டாளர்"}.
|
||||
{"Module failed to handle the query","தொகுதி வினவலைக் கையாளத் தவறிவிட்டது"}.
|
||||
{"Monday","திங்கள்"}.
|
||||
{"Multicast","மல்டிகாச்ட்"}.
|
||||
{"Multiple <item/> elements are not allowed by RFC6121","பல <உருப்படி/> கூறுகள் RFC6121 ஆல் அனுமதிக்கப்படாது"}.
|
||||
{"Multi-User Chat","பல பயனர் அரட்டை"}.
|
||||
{"Name","பெயர்"}.
|
||||
{"Natural Language for Room Discussions","அறை விவாதங்களுக்கு இயற்கை மொழி"}.
|
||||
{"Natural-Language Room Name","இயற்கை மொழி அறை பெயர்"}.
|
||||
{"Neither 'jid' nor 'nick' attribute found","'சிட்' அல்லது 'நிக்' பண்புக்கூறு இல்லை"}.
|
||||
{"Neither 'role' nor 'affiliation' attribute found","'பங்கு' அல்லது 'இணைப்பு' பண்புக்கூறு இல்லை"}.
|
||||
{"Never","ஒருபோதும்"}.
|
||||
{"New Password:","புதிய கடவுச்சொல்:"}.
|
||||
{"Nickname can't be empty","புனைப்பெயர் காலியாக இருக்க முடியாது"}.
|
||||
{"Nickname Registration at ","இல் புனைப்பெயர் பதிவு "}.
|
||||
{"Nickname ~s does not exist in the room","அறையில் ~s புனைப்பெயர் இல்லை"}.
|
||||
{"Nickname","புனைப்பெயர்"}.
|
||||
{"No address elements found","முகவரி கூறுகள் எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No addresses element found","முகவரிகள் உறுப்பு இல்லை"}.
|
||||
{"No 'affiliation' attribute found","'இணைப்பு' பண்புக்கூறு இல்லை"}.
|
||||
{"No available resource found","கிடைக்கக்கூடிய வளங்கள் எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No body provided for announce message","அறிவிப்பு செய்திக்கு எந்த உடலும் வழங்கப்படவில்லை"}.
|
||||
{"No child elements found","குழந்தை கூறுகள் எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No data form found","தரவு படிவம் எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No Data","தரவு இல்லை"}.
|
||||
{"No features available","நற்பொருத்தங்கள் எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No <forwarded/> element found","இல்லை <முன்னோக்கி/> உறுப்பு காணப்பட்டது"}.
|
||||
{"No hook has processed this command","இந்த கட்டளையை எந்த ஊக்கும் செயலாக்கவில்லை"}.
|
||||
{"No info about last activity found","கடைசி செயல்பாட்டைப் பற்றிய எந்த தகவலும் கிடைக்கவில்லை"}.
|
||||
{"No 'item' element found","'உருப்படி' உறுப்பு இல்லை"}.
|
||||
{"No items found in this query","இந்த வினவலில் எந்த உருப்படிகளும் காணப்படவில்லை"}.
|
||||
{"No limit","வரம்பு இல்லை"}.
|
||||
{"No module is handling this query","இந்த வினவலை எந்த தொகுதியும் கையாளவில்லை"}.
|
||||
{"No node specified","எந்த முனையும் குறிப்பிடப்படவில்லை"}.
|
||||
{"No 'password' found in data form","தரவு வடிவத்தில் 'கடவுச்சொல்' காணப்படவில்லை"}.
|
||||
{"No 'password' found in this query","இந்த வினவலில் 'கடவுச்சொல்' இல்லை"}.
|
||||
{"No 'path' found in data form","தரவு வடிவத்தில் 'பாதை' இல்லை"}.
|
||||
{"No pending subscriptions found","நிலுவையில் உள்ள சந்தாக்கள் எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No privacy list with this name found","இந்த பெயருடன் தனியுரிமை பட்டியல் எதுவும் இல்லை"}.
|
||||
{"No private data found in this query","இந்த வினவலில் தனிப்பட்ட தரவு எதுவும் காணப்படவில்லை"}.
|
||||
{"No running node found","இயங்கும் முனை எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No services available","சேவைகள் எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No statistics found for this item","இந்த உருப்படிக்கு புள்ளிவிவரங்கள் எதுவும் கிடைக்கவில்லை"}.
|
||||
{"No 'to' attribute found in the invitation","அழைப்பில் காணப்படும் 'to' பண்புக்கூறு"}.
|
||||
{"Nobody","யாரும்"}.
|
||||
{"Node already exists","முனை ஏற்கனவே உள்ளது"}.
|
||||
{"Node ID","முனை ஐடி"}.
|
||||
{"Node index not found","முனை குறியீடு கிடைக்கவில்லை"}.
|
||||
{"Node not found","முனை கிடைக்கவில்லை"}.
|
||||
{"Node ~p","முனை ~p"}.
|
||||
{"Nodeprep has failed","நோடெப்ரெப் தோல்வியுற்றது"}.
|
||||
{"Nodes","முனைகள்"}.
|
||||
{"Node","கணு"}.
|
||||
{"None","எதுவுமில்லை"}.
|
||||
{"Not allowed","அனுமதிக்கப்படவில்லை"}.
|
||||
{"Not Found","கண்டுபிடிக்கப்படவில்லை"}.
|
||||
{"Not subscribed","குழுசேரவில்லை"}.
|
||||
{"Notify subscribers when items are removed from the node","முனையிலிருந்து உருப்படிகள் அகற்றப்படும்போது சந்தாதாரர்களுக்கு அறிவிக்கவும்"}.
|
||||
{"Notify subscribers when the node configuration changes","முனை உள்ளமைவு மாறும்போது சந்தாதாரர்களுக்கு அறிவிக்கவும்"}.
|
||||
{"Notify subscribers when the node is deleted","முனை நீக்கப்படும் போது சந்தாதாரர்களுக்கு அறிவிக்கவும்"}.
|
||||
{"November","ஐ-கார்த்திகை"}.
|
||||
{"Number of answers required","தேவையான பதில்களின் எண்ணிக்கை"}.
|
||||
{"Number of occupants","குடியிருப்பாளர்களின் எண்ணிக்கை"}.
|
||||
{"Number of Offline Messages","இணைப்பில்லாத செய்திகளின் எண்ணிக்கை"}.
|
||||
{"Number of online users","நிகழ்நிலை பயனர்களின் எண்ணிக்கை"}.
|
||||
{"Number of registered users","பதிவுசெய்யப்பட்ட பயனர்களின் எண்ணிக்கை"}.
|
||||
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","உருப்படிகளை தானாக தூய்மைப்படுத்துவதற்கான விநாடிகளின் எண்ணிக்கை, அல்லது அதிகபட்சம் விதிக்கப்பட்ட சேவையகத்தைத் தவிர வேறு எந்த குறிப்பிட்ட வரம்பையும் `அதிகபட்சம்`"}.
|
||||
{"Occupants are allowed to invite others","குடியிருப்பாளர்கள் மற்றவர்களை அழைக்க அனுமதிக்கப்படுகிறார்கள்"}.
|
||||
{"Occupants are allowed to query others","குடியிருப்பாளர்கள் மற்றவர்களை வினவ அனுமதிக்கப்படுகிறார்கள்"}.
|
||||
{"Occupants May Change the Subject","குடியிருப்பாளர்கள் இந்த விசயத்தை மாற்றலாம்"}.
|
||||
{"October","பு-ஐப்பசி"}.
|
||||
{"OK","சரி"}.
|
||||
{"Old Password:","பழைய கடவுச்சொல்:"}.
|
||||
{"Online Users","நிகழ்நிலை பயனர்கள்"}.
|
||||
{"Online","ஆன்லைனில்"}.
|
||||
{"Only collection node owners may associate leaf nodes with the collection","சேகரிப்பு முனை உரிமையாளர்கள் மட்டுமே இலை முனைகளை சேகரிப்புடன் தொடர்புபடுத்தலாம்"}.
|
||||
{"Only deliver notifications to available users","கிடைக்கக்கூடிய பயனர்களுக்கு மட்டுமே அறிவிப்புகளை வழங்கவும்"}.
|
||||
{"Only <enable/> or <disable/> tags are allowed","<anafice/> அல்லது <முடக்கு/> குறிச்சொற்கள் மட்டுமே அனுமதிக்கப்படுகின்றன"}.
|
||||
{"Only <list/> element is allowed in this query","இந்த வினவலில் <பட்டியல்/> உறுப்பு மட்டுமே அனுமதிக்கப்படுகிறது"}.
|
||||
{"Only members may query archives of this room","உறுப்பினர்கள் மட்டுமே இந்த அறையின் காப்பகங்களை வினவலாம்"}.
|
||||
{"Only moderators and participants are allowed to change the subject in this room","இந்த அறையில் உள்ள விசயத்தை மாற்ற மதிப்பீட்டாளர்கள் மற்றும் பங்கேற்பாளர்கள் மட்டுமே அனுமதிக்கப்படுகிறார்கள்"}.
|
||||
{"Only moderators are allowed to change the subject in this room","இந்த அறையில் உள்ள விசயத்தை மாற்ற மதிப்பீட்டாளர்கள் மட்டுமே அனுமதிக்கப்படுகிறார்கள்"}.
|
||||
{"Only moderators are allowed to retract messages","மதிப்பீட்டாளர்கள் மட்டுமே செய்திகளைத் திரும்பப் பெற அனுமதிக்கப்படுகிறார்கள்"}.
|
||||
{"Only moderators can approve voice requests","மதிப்பீட்டாளர்கள் மட்டுமே குரல் கோரிக்கைகளை அங்கீகரிக்க முடியும்"}.
|
||||
{"Only occupants are allowed to send messages to the conference","குடியிருப்பாளர்கள் மட்டுமே மாநாட்டிற்கு செய்திகளை அனுப்ப அனுமதிக்கப்படுகிறார்கள்"}.
|
||||
{"Only occupants are allowed to send queries to the conference","மாநாட்டிற்கு வினவல்களை அனுப்ப குடியிருப்பாளர்கள் மட்டுமே அனுமதிக்கப்படுகிறார்கள்"}.
|
||||
{"Only publishers may publish","வெளியீட்டாளர்கள் மட்டுமே வெளியிடலாம்"}.
|
||||
{"Only service administrators are allowed to send service messages","பணி செய்திகளை அனுப்ப பணி நிர்வாகிகள் மட்டுமே அனுமதிக்கப்படுகிறார்கள்"}.
|
||||
{"Only those on a whitelist may associate leaf nodes with the collection","அனுமதிப்பட்டியலில் இருப்பவர்கள் மட்டுமே இலை முனைகளை சேகரிப்புடன் தொடர்புபடுத்தலாம்"}.
|
||||
{"Only those on a whitelist may subscribe and retrieve items","அனுமதிப்பட்டியலில் இருப்பவர்கள் மட்டுமே உருப்படிகளை குழுசேரலாம் மற்றும் மீட்டெடுக்கலாம்"}.
|
||||
{"Organization Name","அமைப்பு பெயர்"}.
|
||||
{"Organization Unit","அமைப்பு பிரிவு"}.
|
||||
{"Other Modules Available:","பிற தொகுதிகள் கிடைக்கின்றன:"}.
|
||||
{"Outgoing s2s Connections","வெளிச்செல்லும் எச் 2 எச் இணைப்புகள்"}.
|
||||
{"Owner privileges required","உரிமையாளர் சலுகைகள் தேவை"}.
|
||||
{"Packet relay is denied by service policy","பணி கொள்கையால் பாக்கெட் ரிலே மறுக்கப்படுகிறது"}.
|
||||
{"Participant ID","பங்கேற்பாளர் ஐடி"}.
|
||||
{"Participant","பங்கேற்பாளர்"}.
|
||||
{"Password Verification","கடவுச்சொல் சரிபார்ப்பு"}.
|
||||
{"Password Verification:","கடவுச்சொல் சரிபார்ப்பு:"}.
|
||||
{"Password","கடவுச்சொல்"}.
|
||||
{"Password:","கடவுச்சொல்:"}.
|
||||
{"Path to Dir","அடைவு க்கு பாதை"}.
|
||||
{"Path to File","தாக்கல் செய்வதற்கான பாதை"}.
|
||||
{"Payload semantic type information","பேலோட் சொற்பொருள் வகை செய்தி"}.
|
||||
{"Period: ","காலம்: "}.
|
||||
{"Persist items to storage","சேமிப்பகத்திற்கு உருப்படிகளைத் தொடருங்கள்"}.
|
||||
{"Persistent","விடாமுயற்சி"}.
|
||||
{"Ping query is incorrect","பிங் வினவல் தவறானது"}.
|
||||
{"Ping","பிங்"}.
|
||||
{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","இந்த விருப்பங்கள் பில்டின் மென்சியா தரவுத்தளத்தை மட்டுமே காப்புப் பிரதி எடுக்கும் என்பதை நினைவில் கொள்க. நீங்கள் ODBC தொகுதியைப் பயன்படுத்துகிறீர்கள் என்றால், உங்கள் கவிமொ தரவுத்தளத்தையும் தனித்தனியாக காப்புப் பிரதி எடுக்க வேண்டும்."}.
|
||||
{"Please, wait for a while before sending new voice request","தயவுசெய்து, புதிய குரல் கோரிக்கையை அனுப்புவதற்கு முன் சிறிது நேரம் காத்திருங்கள்"}.
|
||||
{"Pong","பாங்"}.
|
||||
{"Possessing 'ask' attribute is not allowed by RFC6121","'கேளுங்கள்' பண்புக்கூறு வைத்திருப்பது RFC6121 ஆல் அனுமதிக்கப்படவில்லை"}.
|
||||
{"Present real Jabber IDs to","உண்மையான சாபர் ஐடிகளை வழங்கவும்"}.
|
||||
{"Previous session not found","முந்தைய அமர்வு காணப்படவில்லை"}.
|
||||
{"Previous session PID has been killed","முந்தைய அமர்வு பிஐடி கொல்லப்பட்டுள்ளது"}.
|
||||
{"Previous session PID has exited","முந்தைய அமர்வு பிஐடி வெளியேறியது"}.
|
||||
{"Previous session PID is dead","முந்தைய அமர்வு பிஐடி இறந்துவிட்டது"}.
|
||||
{"Previous session timed out","முந்தைய அமர்வு நேரம் முடிந்தது"}.
|
||||
{"private, ","தனிப்பட்ட, "}.
|
||||
{"Public","பொது"}.
|
||||
{"Publish model","மாதிரி வெளியிடு"}.
|
||||
{"Publish-Subscribe","வெளியீட்டு-சந்தா"}.
|
||||
{"PubSub subscriber request","பப்சப் சந்தாதாரர் கோரிக்கை"}.
|
||||
{"Purge all items when the relevant publisher goes offline","தொடர்புடைய வெளியீட்டாளர் ஆஃப்லைனில் செல்லும்போது எல்லா பொருட்களையும் தூய்மைப்படுத்துங்கள்"}.
|
||||
{"Push record not found","புச் பதிவு கிடைக்கவில்லை"}.
|
||||
{"Queries to the conference members are not allowed in this room","இந்த அறையில் மாநாட்டு உறுப்பினர்களுக்கு வினவல்கள் அனுமதிக்கப்படவில்லை"}.
|
||||
{"Query to another users is forbidden","மற்றொரு பயனர்களுக்கு வினவல் தடைசெய்யப்பட்டுள்ளது"}.
|
||||
{"RAM and disc copy","ராம் மற்றும் வட்டு நகல்"}.
|
||||
{"RAM copy","ரேம் நகல்"}.
|
||||
{"Really delete message of the day?","அன்றைய செய்தியை உண்மையில் நீக்கவா?"}.
|
||||
{"Receive notification from all descendent nodes","அனைத்து வழித்தோன்றல்களிலிருந்தும் அறிவிப்பைப் பெறுங்கள்"}.
|
||||
{"Receive notification from direct child nodes only","நேரடி குழந்தை முனைகளிலிருந்து மட்டுமே அறிவிப்பைப் பெறுங்கள்"}.
|
||||
{"Receive notification of new items only","புதிய பொருட்களின் அறிவிப்பைப் பெறுங்கள்"}.
|
||||
{"Receive notification of new nodes only","புதிய முனைகளின் அறிவிப்பைப் பெறுங்கள்"}.
|
||||
{"Recipient is not in the conference room","பெறுநர் மாநாட்டு அறையில் இல்லை"}.
|
||||
{"Register an XMPP account","எக்ச்எம்பி.பி கணக்கை பதிவு செய்யுங்கள்"}.
|
||||
{"Register","பதிவு செய்யுங்கள்"}.
|
||||
{"Remote copy","தொலை நகல்"}.
|
||||
{"Remove a hat from a user","ஒரு பயனரிடமிருந்து ஒரு தொப்பியை அகற்றவும்"}.
|
||||
{"Remove User","பயனரை அகற்று"}.
|
||||
{"Replaced by new connection","புதிய இணைப்பு மூலம் மாற்றப்பட்டது"}.
|
||||
{"Request has timed out","கோரிக்கை நேரம் முடிந்துவிட்டது"}.
|
||||
{"Request is ignored","கோரிக்கை புறக்கணிக்கப்படுகிறது"}.
|
||||
{"Requested role","கோரப்பட்ட பங்கு"}.
|
||||
{"Resources","வளங்கள்"}.
|
||||
{"Restart Service","சேவையை மறுதொடக்கம் செய்யுங்கள்"}.
|
||||
{"Restore Backup from File at ","கோப்பிலிருந்து காப்புப்பிரதியை மீட்டெடுக்கவும் "}.
|
||||
{"Restore binary backup after next ejabberd restart (requires less memory):","அடுத்த EJABBERD மறுதொடக்கத்திற்குப் பிறகு பைனரி காப்புப்பிரதியை மீட்டமைக்கவும் (குறைவான நினைவகம் தேவை):"}.
|
||||
{"Restore binary backup immediately:","பைனரி காப்புப்பிரதியை உடனடியாக மீட்டமைக்கவும்:"}.
|
||||
{"Restore plain text backup immediately:","எளிய உரை காப்புப்பிரதியை உடனடியாக மீட்டெடுக்கவும்:"}.
|
||||
{"Restore","மீட்டமை"}.
|
||||
{"Roles and Affiliations that May Retrieve Member List","உறுப்பினர் பட்டியலை மீட்டெடுக்கக்கூடிய பாத்திரங்கள் மற்றும் இணைப்புகள்"}.
|
||||
{"Roles for which Presence is Broadcasted","இருப்பு ஒளிபரப்பப்படும் பாத்திரங்கள்"}.
|
||||
{"Roles that May Send Private Messages","தனிப்பட்ட செய்திகளை அனுப்பக்கூடிய பாத்திரங்கள்"}.
|
||||
{"Room Configuration","அறை உள்ளமைவு"}.
|
||||
{"Room creation is denied by service policy","பணி கொள்கையால் அறை உருவாக்கம் மறுக்கப்படுகிறது"}.
|
||||
{"Room description","அறை விளக்கம்"}.
|
||||
{"Room Occupants","அறை குடியிருப்பாளர்கள்"}.
|
||||
{"Room terminates","அறை முடிவடைகிறது"}.
|
||||
{"Room title","அறை தலைப்பு"}.
|
||||
{"Roster groups allowed to subscribe","பட்டியல் குழுக்கள் குழுசேர அனுமதிக்கப்பட்டன"}.
|
||||
{"Roster size","பட்டியல் அளவு"}.
|
||||
{"Running Nodes","இயங்கும் முனைகள்"}.
|
||||
{"~s invites you to the room ~s","~s எச் உங்களை அறைக்கு அழைக்கிறது ~s கள்"}.
|
||||
{"Saturday","காரிக்கிழமை"}.
|
||||
{"Search from the date","தேதியிலிருந்து தேடுங்கள்"}.
|
||||
{"Search Results for ","தேடல் முடிவுகள் "}.
|
||||
{"Search the text","உரையைத் தேடுங்கள்"}.
|
||||
{"Search until the date","தேதி வரை தேடுங்கள்"}.
|
||||
{"Search users in ","பயனர்களைத் தேடுங்கள் "}.
|
||||
{"Send announcement to all online users on all hosts","அனைத்து ஓச்ட்களிலும் அனைத்து நிகழ்நிலை பயனர்களுக்கும் அறிவிப்பை அனுப்பவும்"}.
|
||||
{"Send announcement to all online users","அனைத்து நிகழ்நிலை பயனர்களுக்கும் அறிவிப்பை அனுப்பவும்"}.
|
||||
{"Send announcement to all users on all hosts","அனைத்து ஓச்ட்களிலும் உள்ள அனைத்து பயனர்களுக்கும் அறிவிப்பை அனுப்பவும்"}.
|
||||
{"Send announcement to all users","அனைத்து பயனர்களுக்கும் அறிவிப்பை அனுப்பவும்"}.
|
||||
{"September","ஆ-புரட்டாசி"}.
|
||||
{"Server:","சேவையகம்:"}.
|
||||
{"Service list retrieval timed out","பணி பட்டியல் மீட்டெடுப்பு நேரம் முடிந்தது"}.
|
||||
{"Session state copying timed out","அமர்வு நிலை நகலெடுக்கும் நேரம் முடிந்தது"}.
|
||||
{"Set message of the day and send to online users","அன்றைய செய்தியை அமைத்து நிகழ்நிலை பயனர்களுக்கு அனுப்பவும்"}.
|
||||
{"Set message of the day on all hosts and send to online users","அனைத்து ஓச்ட்களிலும் அன்றைய செய்தியை அமைத்து நிகழ்நிலை பயனர்களுக்கு அனுப்பவும்"}.
|
||||
{"Shared Roster Groups","பகிரப்பட்ட பட்டியல் குழுக்கள்"}.
|
||||
{"Show Integral Table","ஒருங்கிணைந்த அட்டவணையைக் காட்டு"}.
|
||||
{"Show Occupants Join/Leave","காட்டு குடியிருப்பாளர்கள் சேர/விடுகிறார்கள்"}.
|
||||
{"Show Ordinary Table","சாதாரண அட்டவணையைக் காட்டு"}.
|
||||
{"Shut Down Service","சேவையை மூடு"}.
|
||||
{"SOCKS5 Bytestreams","SOCKS5 BYTESTREAMS"}.
|
||||
{"Some XMPP clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","சில எக்ச்எம்பிபி வாடிக்கையாளர்கள் உங்கள் கடவுச்சொல்லை கணினியில் சேமிக்க முடியும், ஆனால் பாதுகாப்பு காரணங்களுக்காக இதை உங்கள் தனிப்பட்ட கணினியில் மட்டுமே செய்ய வேண்டும்."}.
|
||||
{"Sources Specs:","ஆதார விவரக்குறிப்புகள்:"}.
|
||||
{"Specify the access model","அணுகல் மாதிரியைக் குறிப்பிடவும்"}.
|
||||
{"Specify the event message type","நிகழ்வு செய்தி வகையைக் குறிப்பிடவும்"}.
|
||||
{"Specify the publisher model","வெளியீட்டாளர் மாதிரியைக் குறிப்பிடவும்"}.
|
||||
{"Stanza id is not valid","முடிப்பு ஐடி செல்லுபடியாகாது"}.
|
||||
{"Stanza ID","முடிப்பு"}.
|
||||
{"Statically specify a replyto of the node owner(s)","முனை உரிமையாளரின் (கள்) ஒரு பதிலை நிலையான முறையில் குறிப்பிடவும்"}.
|
||||
{"Stopped Nodes","நிறுத்தப்பட்ட முனைகள்"}.
|
||||
{"Store binary backup:","பைனரி காப்புப்பிரதியை சேமிக்கவும்:"}.
|
||||
{"Store plain text backup:","எளிய உரை காப்புப்பிரதியை சேமிக்கவும்:"}.
|
||||
{"Stream management is already enabled","ச்ட்ரீம் மேலாண்மை ஏற்கனவே இயக்கப்பட்டது"}.
|
||||
{"Stream management is not enabled","ச்ட்ரீம் மேலாண்மை இயக்கப்படவில்லை"}.
|
||||
{"Subject","பொருள்"}.
|
||||
{"Submitted","சமர்ப்பிக்கப்பட்டது"}.
|
||||
{"Subscriber Address","சந்தாதாரர் முகவரி"}.
|
||||
{"Subscribers may publish","சந்தாதாரர்கள் வெளியிடலாம்"}.
|
||||
{"Subscription requests must be approved and only subscribers may retrieve items","சந்தா கோரிக்கைகள் அங்கீகரிக்கப்பட வேண்டும் மற்றும் சந்தாதாரர்கள் மட்டுமே உருப்படிகளை மீட்டெடுக்க முடியும்"}.
|
||||
{"Subscriptions are not allowed","சந்தாக்கள் அனுமதிக்கப்படவில்லை"}.
|
||||
{"Sunday","ஞாயிற்றுக்கிழமை"}.
|
||||
{"Text associated with a picture","ஒரு படத்துடன் தொடர்புடைய உரை"}.
|
||||
{"Text associated with a sound","ஒலி ஒரு ஒலியுடன் தொடர்புடையது"}.
|
||||
{"Text associated with a video","வீடியோவுடன் தொடர்புடைய உரை"}.
|
||||
{"Text associated with speech","பேச்சுடன் தொடர்புடைய உரை"}.
|
||||
{"That nickname is already in use by another occupant","அந்த புனைப்பெயர் ஏற்கனவே மற்றொரு குடியிருப்பாளரால் பயன்பாட்டில் உள்ளது"}.
|
||||
{"That nickname is registered by another person","அந்த புனைப்பெயர் மற்றொரு நபரால் பதிவு செய்யப்பட்டுள்ளது"}.
|
||||
{"The account already exists","கணக்கு ஏற்கனவே உள்ளது"}.
|
||||
{"The account was not unregistered","கணக்கு பதிவு செய்யப்படவில்லை"}.
|
||||
{"The body text of the last received message","கடைசியாக பெறப்பட்ட செய்தியின் உடல் உரை"}.
|
||||
{"The CAPTCHA is valid.","கேப்ட்சா செல்லுபடியாகும்."}.
|
||||
{"The CAPTCHA verification has failed","கேப்ட்சா சரிபார்ப்பு தோல்வியுற்றது"}.
|
||||
{"The captcha you entered is wrong","நீங்கள் உள்ளிட்ட கேப்ட்சா தவறு"}.
|
||||
{"The child nodes (leaf or collection) associated with a collection","சேகரிப்புடன் தொடர்புடைய குழந்தை முனைகள் (இலை அல்லது சேகரிப்பு)"}.
|
||||
{"The collections with which a node is affiliated","ஒரு முனை இணைக்கப்பட்ட தொகுப்புகள்"}.
|
||||
{"The DateTime at which a leased subscription will end or has ended","குத்தகைக்கு விடப்பட்ட சந்தா முடிவடையும் அல்லது முடிவடைந்த தேதிநேரம்"}.
|
||||
{"The datetime when the node was created","முனை உருவாக்கப்பட்ட தேதிநேரம்"}.
|
||||
{"The default language of the node","முனையின் இயல்புநிலை மொழி"}.
|
||||
{"The feature requested is not supported by the conference","கோரப்பட்ட நற்பொருத்தம் மாநாட்டால் ஆதரிக்கப்படவில்லை"}.
|
||||
{"The JID of the node creator","முனை படைப்பாளரின் சிட்"}.
|
||||
{"The JIDs of those to contact with questions","கேள்விகளுடன் தொடர்பு கொள்ளுபவர்களின் குழந்தைகள்"}.
|
||||
{"The JIDs of those with an affiliation of owner","உரிமையாளரின் இணைப்பு உள்ளவர்களின் குழந்தைகள்"}.
|
||||
{"The JIDs of those with an affiliation of publisher","வெளியீட்டாளரின் இணைப்பு உள்ளவர்களின் குழந்தைகள்"}.
|
||||
{"The list of all online users","அனைத்து நிகழ்நிலை பயனர்களின் பட்டியல்"}.
|
||||
{"The list of all users","அனைத்து பயனர்களின் பட்டியல்"}.
|
||||
{"The list of JIDs that may associate leaf nodes with a collection","இலை முனைகளை ஒரு தொகுப்போடு தொடர்புபடுத்தக்கூடிய JIDS இன் பட்டியல்"}.
|
||||
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","ஒரு சேகரிப்புடன் தொடர்புடைய அதிகபட்ச குழந்தை முனைகளின் எண்ணிக்கை, அல்லது அதிகபட்சமாக விதிக்கப்பட்ட சேவையகத்தைத் தவிர வேறு எந்த குறிப்பிட்ட வரம்பும் இல்லாமல் `அதிகபட்சம் '"}.
|
||||
{"The minimum number of milliseconds between sending any two notification digests","இரண்டு அறிவிப்பு செரிமானங்களையும் அனுப்புவதற்கு இடையில் குறைந்தபட்ச மில்லி விநாடிகளின் எண்ணிக்கை"}.
|
||||
{"The name of the node","முனையின் பெயர்"}.
|
||||
{"The node is a collection node","முனை ஒரு சேகரிப்பு முனை"}.
|
||||
{"The node is a leaf node (default)","முனை ஒரு இலை முனை (இயல்புநிலை)"}.
|
||||
{"The NodeID of the relevant node","தொடர்புடைய முனையின் நோடிட்"}.
|
||||
{"The number of pending incoming presence subscription requests","நிலுவையில் உள்ள உள்வரும் இருப்பு சந்தா கோரிக்கைகளின் எண்ணிக்கை"}.
|
||||
{"The number of subscribers to the node","முனைக்கு சந்தாதாரர்களின் எண்ணிக்கை"}.
|
||||
{"The number of unread or undelivered messages","படிக்காத அல்லது வழங்கப்படாத செய்திகளின் எண்ணிக்கை"}.
|
||||
{"The password contains unacceptable characters","கடவுச்சொல்லில் ஏற்றுக்கொள்ள முடியாத எழுத்துக்கள் உள்ளன"}.
|
||||
{"The password is too weak","கடவுச்சொல் மிகவும் பலவீனமாக உள்ளது"}.
|
||||
{"the password is","கடவுச்சொல்"}.
|
||||
{"The password of your XMPP account was successfully changed.","உங்கள் எக்ச்எம்பிபி கணக்கின் கடவுச்சொல் வெற்றிகரமாக மாற்றப்பட்டது."}.
|
||||
{"The password was not changed","கடவுச்சொல் மாற்றப்படவில்லை"}.
|
||||
{"The passwords are different","கடவுச்சொற்கள் வேறுபட்டவை"}.
|
||||
{"The presence states for which an entity wants to receive notifications","ஒரு நிறுவனம் அறிவிப்புகளைப் பெற விரும்பும் இருப்பு நிலைகள்"}.
|
||||
{"The query is only allowed from local users","வினவல் உள்ளக பயனர்களிடமிருந்து மட்டுமே அனுமதிக்கப்படுகிறது"}.
|
||||
{"The query must not contain <item/> elements","வினவலில் <பொருள்/> கூறுகள் இருக்கக்கூடாது"}.
|
||||
{"The room subject can be modified by participants","அறை பொருள் பங்கேற்பாளர்களால் மாற்றப்படலாம்"}.
|
||||
{"The semantic type information of data in the node, usually specified by the namespace of the payload (if any)","முனையில் உள்ள தரவின் சொற்பொருள் வகை செய்தி, பொதுவாக பேலோடின் பெயர்வெளியால் குறிப்பிடப்படுகிறது (ஏதேனும் இருந்தால்)"}.
|
||||
{"The sender of the last received message","கடைசியாக பெறப்பட்ட செய்தியை அனுப்பு"}.
|
||||
{"The stanza MUST contain only one <active/> element, one <default/> element, or one <list/> element","ச்டான்சாவில் ஒரே <செயலில்/> உறுப்பு, ஒரு <இயல்புநிலை/> உறுப்பு அல்லது ஒரு <பட்டியல்/> உறுப்பு மட்டுமே இருக்க வேண்டும்"}.
|
||||
{"The subscription identifier associated with the subscription request","சந்தா கோரிக்கையுடன் தொடர்புடைய சந்தா அடையாளங்காட்டி"}.
|
||||
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","பொருத்தமான செய்தி உடல் உறுப்பை உருவாக்குவதற்காக பேலோடுகளுக்கு பயன்படுத்தக்கூடிய எக்ச்எச்எல் மாற்றத்தின் முகவரி."}.
|
||||
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","செல்லுபடியாகும் தரவு படிவங்களை உருவாக்குவதற்காக பேலோட் வடிவத்தில் பயன்படுத்தக்கூடிய ஒரு எக்ச்எச்எல் உருமாற்றத்தின் முகவரி, கிளையன்ட் பொதுவான தரவு படிவங்கள் வழங்குதல் எஞ்சின் பயன்படுத்தி காண்பிக்க முடியும்"}.
|
||||
{"There was an error changing the password: ","கடவுச்சொல்லை மாற்றுவதில் பிழை ஏற்பட்டது: "}.
|
||||
{"There was an error creating the account: ","கணக்கை உருவாக்கும் பிழை இருந்தது: "}.
|
||||
{"There was an error deleting the account: ","கணக்கை நீக்குவதில் பிழை ஏற்பட்டது: "}.
|
||||
{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","இது வழக்கு உணர்வற்றது: மாக்பெத் மற்றும் மாக்பெத் தான்."}.
|
||||
{"This page allows to register an XMPP account in this XMPP server. Your JID (Jabber ID) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","இந்த XMPP சேவையகத்தில் ஒரு XMPP கணக்கை பதிவு செய்ய இந்த பக்கம் அனுமதிக்கிறது. உங்கள் சிட் (சாபர் ஐடி) படிவமாக இருக்கும்: பயனர்பெயர்@சேவையகம். புலங்களை சரியாக நிரப்ப வழிமுறைகளை கவனமாகப் படியுங்கள்."}.
|
||||
{"This page allows to unregister an XMPP account in this XMPP server.","இந்த எக்ச்எம்பி.பி சேவையகத்தில் எக்ச்எம்பி.பி கணக்கை பதிவு செய்ய இந்த பக்கம் அனுமதிக்கிறது."}.
|
||||
{"This room is not anonymous","இந்த அறை அநாமதேயமானது அல்ல"}.
|
||||
{"This service can not process the address: ~s","இந்த பணி முகவரியை செயலாக்க முடியாது: ~s"}.
|
||||
{"Thursday","வியாழக்கிழமை"}.
|
||||
{"Time delay","நேர நேரந்தவறுகை"}.
|
||||
{"Timed out waiting for stream resumption","ச்ட்ரீம் மறுதொடக்கத்திற்காக காத்திருக்கும் நேரம்"}.
|
||||
{"To register, visit ~s","பதிவு செய்ய, ~s பார்வையிடவும்"}.
|
||||
{"To ~ts","~ts K"}.
|
||||
{"Token TTL","கிள்ளாக்கு டி.டி.எல்"}.
|
||||
{"Too many active bytestreams","பல செயலில் உள்ள பைட்டிரீம்கள்"}.
|
||||
{"Too many CAPTCHA requests","பல கேப்ட்சா கோரிக்கைகள்"}.
|
||||
{"Too many child elements","பல குழந்தை கூறுகள்"}.
|
||||
{"Too many <item/> elements","பல <உருப்படி/> கூறுகள்"}.
|
||||
{"Too many <list/> elements","பல <பட்டியல்/> கூறுகள்"}.
|
||||
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","இந்த ஐபி முகவரியிலிருந்து (~p) பல (~s) தோல்வியுற்ற அங்கீகாரங்கள் ~s. முகவரி UTC இல் தடைசெய்யப்படும்"}.
|
||||
{"Too many receiver fields were specified","அதிகமான ரிசீவர் புலங்கள் குறிப்பிடப்பட்டன"}.
|
||||
{"Too many unacked stanzas","பல அறியப்படாத சரணங்கள்"}.
|
||||
{"Too many users in this conference","இந்த மாநாட்டில் அதிகமான பயனர்கள்"}.
|
||||
{"Traffic rate limit is exceeded","போக்குவரத்து வீத வரம்பு மீறப்பட்டது"}.
|
||||
{"~ts's MAM Archive","~ts இன் மாம் காப்பகம்"}.
|
||||
{"~ts's Offline Messages Queue","~ts இன் இணைப்பில்லாத செய்திகள் வரிசை"}.
|
||||
{"Tuesday","செவ்வாய்க்கிழமை"}.
|
||||
{"Unable to generate a CAPTCHA","கேப்ட்சாவை உருவாக்க முடியவில்லை"}.
|
||||
{"Unable to register route on existing local domain","தற்போதுள்ள உள்ளக களத்தில் வழியை பதிவு செய்ய முடியவில்லை"}.
|
||||
{"Unauthorized","அங்கீகரிக்கப்படாதது"}.
|
||||
{"Unexpected action","எதிர்பாராத நடவடிக்கை"}.
|
||||
{"Unexpected error condition: ~p","எதிர்பாராத பிழை நிலை: ~p"}.
|
||||
{"Uninstall","நிறுவல் நீக்க"}.
|
||||
{"Unregister an XMPP account","ஒரு எக்ச்எம்பிபி கணக்கை பதிவு செய்யவும்"}.
|
||||
{"Unregister","பதிவு செய்யப்படாதது"}.
|
||||
{"Unsupported <index/> element","ஆதரிக்கப்படாத <குறியீட்டு/> உறுப்பு"}.
|
||||
{"Unsupported version","ஆதரிக்கப்படாத பதிப்பு"}.
|
||||
{"Update message of the day (don't send)","அன்றைய செய்தியைப் புதுப்பிக்கவும் (அனுப்ப வேண்டாம்)"}.
|
||||
{"Update message of the day on all hosts (don't send)","எல்லா ஓச்ட்களிலும் அன்றைய செய்தியைப் புதுப்பிக்கவும் (அனுப்ப வேண்டாம்)"}.
|
||||
{"Update specs to get modules source, then install desired ones.","தொகுதிகள் மூலத்தைப் பெற விவரக்குறிப்புகளைப் புதுப்பிக்கவும், பின்னர் விரும்பியவற்றை நிறுவவும்."}.
|
||||
{"Update Specs","விவரக்குறிப்புகளைப் புதுப்பிக்கவும்"}.
|
||||
{"Updating the vCard is not supported by the vCard storage backend","VCARD ஐப் புதுப்பிப்பது VCARD சேமிப்பக பின்தளத்தில் ஆதரிக்கப்படவில்லை"}.
|
||||
{"Upgrade","மேம்படுத்தல்"}.
|
||||
{"URL for Archived Discussion Logs","காப்பகப்படுத்தப்பட்ட கலந்துரையாடல் பதிவுகளுக்கான முகவரி"}.
|
||||
{"User already exists","பயனர் ஏற்கனவே உள்ளது"}.
|
||||
{"User (jid)","பயனர் (சிட்)"}.
|
||||
{"User JID","பயனர் சிட்"}.
|
||||
{"User Management","பயனர் மேலாண்மை"}.
|
||||
{"User not allowed to perform an IQ set on another user's vCard.","மற்றொரு பயனரின் VCARD இல் IQ தொகுப்பை செய்ய பயனர் அனுமதிக்கப்படவில்லை."}.
|
||||
{"User removed","பயனர் அகற்றப்பட்டார்"}.
|
||||
{"User session not found","பயனர் அமர்வு காணப்படவில்லை"}.
|
||||
{"User session terminated","பயனர் அமர்வு நிறுத்தப்பட்டது"}.
|
||||
{"User ~ts","பயனர் ~ts"}.
|
||||
{"Username:","பயனர்பெயர்:"}.
|
||||
{"Users are not allowed to register accounts so quickly","பயனர்கள் கணக்குகளை விரைவாக பதிவு செய்ய அனுமதிக்கப்படுவதில்லை"}.
|
||||
{"Users Last Activity","பயனர்கள் கடைசி செயல்பாடு"}.
|
||||
{"Users","பயனர்கள்"}.
|
||||
{"User","பயனர்"}.
|
||||
{"Value 'get' of 'type' attribute is not allowed","'வகை' பண்புக்கூறின் மதிப்பு 'பெறுதல்' அனுமதிக்கப்படவில்லை"}.
|
||||
{"Value of '~s' should be boolean","'~s' மதிப்பு பூலியனாக இருக்க வேண்டும்"}.
|
||||
{"Value of '~s' should be datetime string","'~s' இன் மதிப்பு தேதிநேர சரமாக இருக்க வேண்டும்"}.
|
||||
{"Value of '~s' should be integer","'~s' இன் மதிப்பு முழு எண்ணாக இருக்க வேண்டும்"}.
|
||||
{"Value 'set' of 'type' attribute is not allowed","'வகை' பண்புக்கூறின் 'தொகுப்பு' மதிப்பு அனுமதிக்கப்படவில்லை"}.
|
||||
{"vCard User Search","VCARD பயனர் தேடல்"}.
|
||||
{"View joined MIX channels","கலப்பு சேனல்களில் சேர்ந்தார்"}.
|
||||
{"Virtual Hosts","மெய்நிகர் ஓச்ட்கள்"}.
|
||||
{"Visitors are not allowed to change their nicknames in this room","இந்த அறையில் பார்வையாளர்கள் தங்கள் புனைப்பெயர்களை மாற்ற அனுமதிக்கப்படுவதில்லை"}.
|
||||
{"Visitors are not allowed to send messages to all occupants","பார்வையாளர்கள் அனைத்து குடியிருப்பாளர்களுக்கும் செய்திகளை அனுப்ப அனுமதிக்கப்படுவதில்லை"}.
|
||||
{"Visitor","பார்வையாளர்"}.
|
||||
{"Voice requests are disabled in this conference","இந்த மாநாட்டில் குரல் கோரிக்கைகள் முடக்கப்பட்டுள்ளன"}.
|
||||
{"Voice request","குரல் கோரிக்கை"}.
|
||||
{"Wednesday","புதன்கிழமை"}.
|
||||
{"When a new subscription is processed and whenever a subscriber comes online","புதிய சந்தா செயலாக்கப்படும் போது, சந்தாதாரர் ஆன்லைனில் வரும்போதெல்லாம்"}.
|
||||
{"When a new subscription is processed","புதிய சந்தா செயலாக்கப்படும் போது"}.
|
||||
{"When to send the last published item","கடைசியாக வெளியிடப்பட்ட உருப்படியை எப்போது அனுப்ப வேண்டும்"}.
|
||||
{"Whether an entity wants to receive an XMPP message body in addition to the payload format","ஒரு நிறுவனம் பேலோட் வடிவமைப்பிற்கு கூடுதலாக ஒரு எக்ச்எம்பிபி செய்தி உடலைப் பெற விரும்புகிறதா என்பதை"}.
|
||||
{"Whether an entity wants to receive digests (aggregations) of notifications or all notifications individually","ஒரு நிறுவனம் அறிவிப்புகளின் செரிமானங்களை (திரட்டல்கள்) பெற விரும்புகிறதா அல்லது அனைத்து அறிவிப்புகளையும் தனித்தனியாகப் பெற விரும்புகிறதா"}.
|
||||
{"Whether an entity wants to receive or disable notifications","ஒரு நிறுவனம் அறிவிப்புகளைப் பெற விரும்புகிறதா அல்லது முடக்க விரும்புகிறதா"}.
|
||||
{"Whether owners or publisher should receive replies to items","உரிமையாளர்கள் அல்லது வெளியீட்டாளர் உருப்படிகளுக்கான பதில்களைப் பெற வேண்டுமா"}.
|
||||
{"Whether the node is a leaf (default) or a collection","முனை ஒரு இலை (இயல்புநிலை) அல்லது தொகுப்பாக இருந்தாலும் சரி"}.
|
||||
{"Whether to allow subscriptions","சந்தாக்களை அனுமதிக்க வேண்டுமா"}.
|
||||
{"Whether to make all subscriptions temporary, based on subscriber presence","அனைத்து சந்தாக்களையும் தற்காலிகமாக மாற்றலாமா, சந்தாதாரர் இருப்பின் அடிப்படையில்"}.
|
||||
{"Whether to notify owners about new subscribers and unsubscribes","புதிய சந்தாதாரர்கள் மற்றும் குழுவிலகங்களைப் பற்றி உரிமையாளர்களுக்கு அறிவிக்க வேண்டுமா"}.
|
||||
{"Who can send private messages","தனிப்பட்ட செய்திகளை யார் அனுப்ப முடியும்"}.
|
||||
{"Who may associate leaf nodes with a collection","இலை முனைகளை யார் சேகரிப்புடன் தொடர்புபடுத்தலாம்"}.
|
||||
{"Wrong parameters in the web formulary","வலை சூத்திரத்தில் தவறான அளவுருக்கள்"}.
|
||||
{"Wrong xmlns","தவறான xmlns"}.
|
||||
{"XMPP Account Registration","எக்ச்எம்பிபி கணக்கு பதிவு"}.
|
||||
{"XMPP Domains","எக்ச்எம்பிபி களங்கள்"}.
|
||||
{"XMPP Show Value of Away","எக்ச்எம்பிபி சோ மதிப்பைக் காட்டுகிறது"}.
|
||||
{"XMPP Show Value of Chat","எக்ச்எம்பிபி அரட்டையின் மதிப்பைக் காட்டுகிறது"}.
|
||||
{"XMPP Show Value of DND (Do Not Disturb)","எக்ச்எம்பிபி டி.என்.டி யின் மதிப்பைக் காட்டுகிறது (தொந்தரவு செய்யாதீர்கள்)"}.
|
||||
{"XMPP Show Value of XA (Extended Away)","XMPP XA இன் மதிப்பைக் காட்டுகிறது (நீட்டிக்கப்பட்டது)"}.
|
||||
{"XMPP URI of Associated Publish-Subscribe Node","அசோசியேட்டட் பப்ளிச்-சப்ச்கிரிப்ட் முனையின் எக்ச்எம்பிபி யுஆர்ஐ"}.
|
||||
{"You are being removed from the room because of a system shutdown","கணினி பணிநிறுத்தம் காரணமாக நீங்கள் அறையிலிருந்து அகற்றப்படுகிறீர்கள்"}.
|
||||
{"You are not allowed to send private messages","தனிப்பட்ட செய்திகளை அனுப்ப உங்களுக்கு இசைவு இல்லை"}.
|
||||
{"You are not joined to the channel","நீங்கள் சேனலுடன் சேரவில்லை"}.
|
||||
{"You can later change your password using an XMPP client.","எக்ச்எம்பிபி கிளையண்டைப் பயன்படுத்தி உங்கள் கடவுச்சொல்லை பின்னர் மாற்றலாம்."}.
|
||||
{"You have been banned from this room","இந்த அறையிலிருந்து நீங்கள் தடை செய்யப்பட்டுள்ளீர்கள்"}.
|
||||
{"You have joined too many conferences","நீங்கள் பல மாநாடுகளில் சேர்ந்துள்ளீர்கள்"}.
|
||||
{"You must fill in field \"Nickname\" in the form","நீங்கள் வடிவத்தில் புலம் \"புனைப்பெயரை\" நிரப்ப வேண்டும்"}.
|
||||
{"You need a client that supports x:data and CAPTCHA to register","எக்ச்: தரவு மற்றும் கேப்ட்சா பதிவு செய்ய உங்களுக்கு ஒரு வாங்கி தேவை"}.
|
||||
{"You need a client that supports x:data to register the nickname","புனைப்பெயரை பதிவு செய்ய எக்ச்: தரவை ஆதரிக்கும் வாங்கி உங்களுக்குத் தேவை"}.
|
||||
{"You need an x:data capable client to search","தேட உங்களுக்கு ஒரு ஃச் தேவை: தேட தரவு திறன் கொண்ட வாங்கி"}.
|
||||
{"Your active privacy list has denied the routing of this stanza.","உங்கள் செயலில் உள்ள தனியுரிமை பட்டியல் இந்த சரணத்தை வழிநடத்துவதை மறுத்துள்ளது."}.
|
||||
{"Your contact offline message queue is full. The message has been discarded.","உங்கள் தொடர்பு இணைப்பில்லாத செய்தி வரிசை நிரம்பியுள்ளது. செய்தி நிராகரிக்கப்பட்டுள்ளது."}.
|
||||
{"Your subscription request and/or messages to ~s have been blocked. To unblock your subscription request, visit ~s","உங்கள் சந்தா கோரிக்கை மற்றும்/அல்லது செய்திகளுக்கான செய்திகள் தடுக்கப்பட்டுள்ளன ~s. உங்கள் சந்தா கோரிக்கையைத் தடுக்க, ~s கள் பார்வையிடவும்"}.
|
||||
{"Your XMPP account was successfully registered.","உங்கள் எக்ச்எம்பிபி கணக்கு வெற்றிகரமாக பதிவு செய்யப்பட்டது."}.
|
||||
{"Your XMPP account was successfully unregistered.","உங்கள் எக்ச்எம்பிபி கணக்கு வெற்றிகரமாக பதிவு செய்யப்படவில்லை."}.
|
||||
{"You're not allowed to create nodes","முனைகளை உருவாக்க உங்களுக்கு இசைவு இல்லை"}.
|
||||
@@ -46,7 +46,9 @@
|
||||
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","Будь-хто, хто має підписку на отримання інформації про присутність в обох випадках або може підписуватись та отримувати матеріали"}.
|
||||
{"Anyone with Voice","Будь-хто, хто має голос"}.
|
||||
{"Anyone","Будь-хто"}.
|
||||
{"API Commands","Команди API"}.
|
||||
{"April","Квітень"}.
|
||||
{"Arguments","Аргументи"}.
|
||||
{"Attribute 'channel' is required for this request","Атрибут \"канал\" є обов'язковим для цього запиту"}.
|
||||
{"Attribute 'id' is mandatory for MIX messages","Атрибут 'id' обов'язковий для MIX повідомлень"}.
|
||||
{"Attribute 'jid' is not allowed here","Атрибут 'jid' заборонений"}.
|
||||
@@ -86,6 +88,7 @@
|
||||
{"Choose whether to approve this entity's subscription.","Виберіть, чи підтверджувати підписку."}.
|
||||
{"City","Місто"}.
|
||||
{"Client acknowledged more stanzas than sent by server","Клієнт підтвердив більше повідомлень, ніж було відправлено сервером"}.
|
||||
{"Clustering","Кластеризація"}.
|
||||
{"Commands","Команди"}.
|
||||
{"Conference room does not exist","Кімната для переговорів відсутня"}.
|
||||
{"Configuration of room ~s","Конфігурація кімнати ~s"}.
|
||||
@@ -108,6 +111,7 @@
|
||||
{"Dump Backup to Text File at ","Копіювання в текстовий файл на "}.
|
||||
{"Dump to Text File","Копіювання в текстовий файл"}.
|
||||
{"Duplicated groups are not allowed by RFC6121","RFC6121 забороняє дублювати групи"}.
|
||||
{"Dynamically specify a replyto of the item publisher","Динамічно вказуйте відповідь видавця елемента"}.
|
||||
{"Edit Properties","Змінити параметри"}.
|
||||
{"Either approve or decline the voice request.","Підтвердіть або відхиліть голосовий запит."}.
|
||||
{"ejabberd HTTP Upload service","Служба відвантаження по HTTP для ejabberd"}.
|
||||
@@ -123,6 +127,7 @@
|
||||
{"Enable hats","Увімкнути капелюхи"}.
|
||||
{"Enable logging","Увімкнути журнал роботи"}.
|
||||
{"Enable message archiving","Ввімкнути архівацію повідомлень"}.
|
||||
{"Enabling push without 'node' attribute is not supported","Увімкнення push без атрибута node не підтримується"}.
|
||||
{"End User Session","Закінчити Сеанс Користувача"}.
|
||||
{"Enter nickname you want to register","Введіть псевдонім, який ви хочете зареєструвати"}.
|
||||
{"Enter path to backup file","Введіть шлях до резервного файла"}.
|
||||
@@ -166,6 +171,7 @@
|
||||
{"has been kicked because of an affiliation change","вигнано з кімнати внаслідок зміни рангу"}.
|
||||
{"has been kicked because the room has been changed to members-only","вигнано з кімнати тому, що вона стала тільки для учасників"}.
|
||||
{"has been kicked","вигнали з кімнати"}.
|
||||
{"Hash of the vCard-temp avatar of this room","Хеш тимчасового аватара vCard цієї кімнати"}.
|
||||
{"Hat title","Назва кімнати"}.
|
||||
{"Hat URI","Назва URI"}.
|
||||
{"Hats limit exceeded","Перевищено швидкість передачі інформації"}.
|
||||
@@ -206,6 +212,8 @@
|
||||
{"January","січня"}.
|
||||
{"JID normalization denied by service policy","Створювати конференцію заборонено політикою служби"}.
|
||||
{"JID normalization failed","Помилка нормалізації JID"}.
|
||||
{"Joined MIX channels of ~ts","Приєднався до каналів MIX ~ts"}.
|
||||
{"Joined MIX channels:","Приєднався до каналів MIX:"}.
|
||||
{"joins the room","увійшов(ла) в кімнату"}.
|
||||
{"July","липня"}.
|
||||
{"June","червня"}.
|
||||
@@ -219,6 +227,7 @@
|
||||
{"leaves the room","вийшов(ла) з кімнати"}.
|
||||
{"List of users with hats","Список користувачів із капелюхами"}.
|
||||
{"List users with hats","Список користувачів із капелюхами"}.
|
||||
{"Logged Out","Вийшов із системи"}.
|
||||
{"Logging","Журналювання"}.
|
||||
{"Make participants list public","Зробити список учасників видимим всім"}.
|
||||
{"Make room CAPTCHA protected","Зробити кімнату захищеною капчею"}.
|
||||
@@ -382,12 +391,19 @@
|
||||
{"RAM copy","Копія оперативної пам'яті"}.
|
||||
{"Really delete message of the day?","Дійсно видалити повідомлення дня?"}.
|
||||
{"Receive notification from all descendent nodes","Отримувати сповіщення від усіх підпорядкованих вузлів"}.
|
||||
{"Receive notification from direct child nodes only","Отримувати сповіщення лише від прямих дочірніх вузлів"}.
|
||||
{"Receive notification of new items only","Отримувати сповіщення лише про нові товари"}.
|
||||
{"Receive notification of new nodes only","Отримувати сповіщення лише про нові вузли"}.
|
||||
{"Recipient is not in the conference room","Адресата немає в конференції"}.
|
||||
{"Register an XMPP account","Зареєструвати XMPP-запис"}.
|
||||
{"Register","Реєстрація"}.
|
||||
{"Remote copy","не зберігаеться локально"}.
|
||||
{"Remove a hat from a user","Зняти шапку з користувача"}.
|
||||
{"Remove User","Видалити користувача"}.
|
||||
{"Replaced by new connection","Замінено новим з'єднанням"}.
|
||||
{"Request has timed out","Час очікування запиту минув"}.
|
||||
{"Request is ignored","Запит ігнорується"}.
|
||||
{"Requested role","Запитана роль"}.
|
||||
{"Resources","Ресурси"}.
|
||||
{"Restart Service","Перезапустити Сервіс"}.
|
||||
{"Restore Backup from File at ","Відновлення з резервної копії на "}.
|
||||
@@ -395,6 +411,8 @@
|
||||
{"Restore binary backup immediately:","Відновити з бінарної резервної копії негайно:"}.
|
||||
{"Restore plain text backup immediately:","Відновити з текстової резервної копії негайно:"}.
|
||||
{"Restore","Відновлення з резервної копії"}.
|
||||
{"Result","Результат"}.
|
||||
{"Roles and Affiliations that May Retrieve Member List","Ролі та зв’язки, які можуть отримати список учасників"}.
|
||||
{"Roles for which Presence is Broadcasted","Ролі для яких поширюється наявність"}.
|
||||
{"Roles that May Send Private Messages","Ролі, що можуть надсилати приватні повідомлення"}.
|
||||
{"Room Configuration","Конфігурація кімнати"}.
|
||||
@@ -408,7 +426,10 @@
|
||||
{"Running Nodes","Працюючі вузли"}.
|
||||
{"~s invites you to the room ~s","~s запрошує вас до кімнати ~s"}.
|
||||
{"Saturday","Субота"}.
|
||||
{"Search from the date","Пошук від дати"}.
|
||||
{"Search Results for ","Результати пошуку в "}.
|
||||
{"Search the text","Знайдіть текст"}.
|
||||
{"Search until the date","Пошук до дати"}.
|
||||
{"Search users in ","Пошук користувачів в "}.
|
||||
{"Send announcement to all online users on all hosts","Надіслати сповіщення всім підключеним користувачам на всіх віртуальних серверах"}.
|
||||
{"Send announcement to all online users","Надіслати сповіщення всім підключеним користувачам"}.
|
||||
@@ -416,42 +437,94 @@
|
||||
{"Send announcement to all users","Надіслати сповіщення всім користувачам"}.
|
||||
{"September","вересня"}.
|
||||
{"Server:","Сервер:"}.
|
||||
{"Service list retrieval timed out","Час очікування отримання списку послуг минув"}.
|
||||
{"Session state copying timed out","Час очікування копіювання стану сеансу минув"}.
|
||||
{"Set message of the day and send to online users","Встановити повідомлення дня та надіслати його підключеним користувачам"}.
|
||||
{"Set message of the day on all hosts and send to online users","Встановити повідомлення дня на всіх хостах та надійслати його підключеним користувачам"}.
|
||||
{"Shared Roster Groups","Спільні групи контактів"}.
|
||||
{"Show Integral Table","Показати інтегральну таблицю"}.
|
||||
{"Show Occupants Join/Leave","Показати мешканцям приєднатися/вийти"}.
|
||||
{"Show Ordinary Table","Показати звичайну таблицю"}.
|
||||
{"Shut Down Service","Вимкнути Сервіс"}.
|
||||
{"SOCKS5 Bytestreams","Потоки байтів SOCKS5"}.
|
||||
{"Some XMPP clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Деякі клієнти XMPP можуть зберігати ваш пароль на комп’ютері, але ви повинні робити це лише на своєму персональному комп’ютері з міркувань безпеки."}.
|
||||
{"Sources Specs:","Специфікації джерел:"}.
|
||||
{"Specify the access model","Визначити модель доступу"}.
|
||||
{"Specify the event message type","Вкажіть тип повідомлень зі сповіщеннями про події"}.
|
||||
{"Specify the publisher model","Умови публікації"}.
|
||||
{"Stanza id is not valid","Ідентифікатор строфи недійсний"}.
|
||||
{"Stanza ID","ID кімнати"}.
|
||||
{"Statically specify a replyto of the node owner(s)","Статично вкажіть відповідь власника(ів) вузла"}.
|
||||
{"Stopped Nodes","Зупинені вузли"}.
|
||||
{"Store binary backup:","Зберегти бінарну резервну копію:"}.
|
||||
{"Store plain text backup:","Зберегти текстову резервну копію:"}.
|
||||
{"Stream management is already enabled","Керування потоком уже ввімкнено"}.
|
||||
{"Stream management is not enabled","Керування потоком не ввімкнено"}.
|
||||
{"Subject","Тема"}.
|
||||
{"Submitted","Відправлено"}.
|
||||
{"Subscriber Address","Адреса абонента"}.
|
||||
{"Subscribers may publish","Підписники можуть публікувати"}.
|
||||
{"Subscription requests must be approved and only subscribers may retrieve items","Запити на підписку мають бути схвалені, і лише передплатники можуть отримувати елементи"}.
|
||||
{"Subscriptions are not allowed","Підписка заборонена"}.
|
||||
{"Sunday","Неділя"}.
|
||||
{"Text associated with a picture","Текст, пов'язаний із зображенням"}.
|
||||
{"Text associated with a sound","Текст, пов'язаний зі звуком"}.
|
||||
{"Text associated with a video","Текст, пов’язаний із відео"}.
|
||||
{"Text associated with speech","Текст, пов'язаний з мовленням"}.
|
||||
{"That nickname is already in use by another occupant","Псевдонім зайнято кимось з присутніх"}.
|
||||
{"That nickname is registered by another person","Псевдонім зареєстровано кимось іншим"}.
|
||||
{"The account already exists","Обліковий запис уже існує"}.
|
||||
{"The account was not unregistered","Обліковий запис не було видалено"}.
|
||||
{"The body text of the last received message","Основний текст останнього отриманого повідомлення"}.
|
||||
{"The CAPTCHA is valid.","Перевірку CAPTCHA успішно завершено."}.
|
||||
{"The CAPTCHA verification has failed","Перевірку капчею не пройдено"}.
|
||||
{"The captcha you entered is wrong","Captcha, яку ви ввели, неправильна"}.
|
||||
{"The child nodes (leaf or collection) associated with a collection","Дочірні вузли (лист або колекція), пов’язані з колекцією"}.
|
||||
{"The collections with which a node is affiliated","Колекція, до якої входить вузол"}.
|
||||
{"The DateTime at which a leased subscription will end or has ended","DateTime, коли орендована підписка закінчиться або закінчилася"}.
|
||||
{"The datetime when the node was created","Дата і час створення вузла"}.
|
||||
{"The default language of the node","Мова вузла за замовчуванням"}.
|
||||
{"The feature requested is not supported by the conference","Запитана функція не підтримується конференцією"}.
|
||||
{"The JID of the node creator","JID творця вузла"}.
|
||||
{"The JIDs of those to contact with questions","JID тих, до кого можна звернутися із запитаннями"}.
|
||||
{"The JIDs of those with an affiliation of owner","JID тих, хто є афілійованим власником"}.
|
||||
{"The JIDs of those with an affiliation of publisher","JID тих, хто пов’язаний із видавцем"}.
|
||||
{"The list of all online users","Список усіх онлайн-користувачів"}.
|
||||
{"The list of all users","Список усіх користувачів"}.
|
||||
{"The list of JIDs that may associate leaf nodes with a collection","Список JID, які можуть пов’язувати листові вузли з колекцією"}.
|
||||
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","Максимальна кількість дочірніх вузлів, які можна пов’язати з колекцією, або `max` для відсутності конкретного обмеження, окрім максимального накладеного сервером"}.
|
||||
{"The minimum number of milliseconds between sending any two notification digests","Мінімальна кількість мілісекунд між надсиланням будь-яких двох дайджестів сповіщень"}.
|
||||
{"The name of the node","Ім'я вузла"}.
|
||||
{"The node is a collection node","Вузол є вузлом колекції"}.
|
||||
{"The node is a leaf node (default)","Вузол є листовим вузлом (за замовчуванням)"}.
|
||||
{"The NodeID of the relevant node","NodeID відповідного вузла"}.
|
||||
{"The number of pending incoming presence subscription requests","Кількість вхідних запитів на підписку про присутність, що очікують на розгляд"}.
|
||||
{"The number of subscribers to the node","Кількість передплатників вузла"}.
|
||||
{"The number of unread or undelivered messages","Кількість непрочитаних або недоставлених повідомлень"}.
|
||||
{"The password contains unacceptable characters","Пароль містить неприйнятні символи"}.
|
||||
{"The password is too weak","Пароль надто простий"}.
|
||||
{"the password is","паролем є"}.
|
||||
{"The password of your XMPP account was successfully changed.","Пароль вашого облікового запису XMPP успішно змінено."}.
|
||||
{"The password was not changed","Пароль не змінено"}.
|
||||
{"The passwords are different","Паролі різні"}.
|
||||
{"The presence states for which an entity wants to receive notifications","Стан присутності, для якого сутність хоче отримувати сповіщення"}.
|
||||
{"The query is only allowed from local users","Запит дозволено лише від локальних користувачів"}.
|
||||
{"The query must not contain <item/> elements","Запит не повинен містити елементів <item/>"}.
|
||||
{"The room subject can be modified by participants","Тема кімнати може бути змінена учасниками"}.
|
||||
{"The semantic type information of data in the node, usually specified by the namespace of the payload (if any)","Інформація про семантичний тип даних у вузлі, зазвичай визначена простором імен корисного навантаження (якщо є)"}.
|
||||
{"The sender of the last received message","Відправник останнього отриманого повідомлення"}.
|
||||
{"The stanza MUST contain only one <active/> element, one <default/> element, or one <list/> element","Строфа ПОВИННА містити лише один елемент <active/>, один елемент <default/> або один елемент <list/>"}.
|
||||
{"The subscription identifier associated with the subscription request","Ідентифікатор підписки, пов’язаний із запитом на підписку"}.
|
||||
{"The URL of an XSL transformation which can be applied to payloads in order to generate an appropriate message body element.","URL-адреса перетворення XSL, яке можна застосувати до корисних даних, щоб створити відповідний елемент тіла повідомлення."}.
|
||||
{"The URL of an XSL transformation which can be applied to the payload format in order to generate a valid Data Forms result that the client could display using a generic Data Forms rendering engine","URL-адреса трансформації XSL, яку можна застосувати до формату корисного навантаження, щоб створити дійсний результат форм даних, який клієнт міг би відобразити за допомогою загального механізму візуалізації форм даних"}.
|
||||
{"There was an error changing the password: ","Помилка при зміні пароля: "}.
|
||||
{"There was an error creating the account: ","Помилка при створенні облікового запису: "}.
|
||||
{"There was an error deleting the account: ","Помилка при видаленні акаунту: "}.
|
||||
{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Тут не враховується регістр: Макбет – це те саме, що Макбет і Макбет."}.
|
||||
{"This page allows to register an XMPP account in this XMPP server. Your JID (Jabber ID) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Ця сторінка дозволяє зареєструвати обліковий запис XMPP на цьому сервері XMPP. Ваш JID (Jabber ID) матиме такий вигляд: ім’я користувача@сервер. Уважно прочитайте інструкції, щоб правильно заповнити поля."}.
|
||||
{"This page allows to unregister an XMPP account in this XMPP server.","Ця сторінка дозволяє видалити свій обліковий запис з XMPP-сервера."}.
|
||||
{"This room is not anonymous","Ця кімната не анонімна"}.
|
||||
{"This service can not process the address: ~s","Ця служба не може обробити адресу: ~s"}.
|
||||
{"Thursday","Четвер"}.
|
||||
{"Time delay","Час затримки"}.
|
||||
{"Timed out waiting for stream resumption","Час очікування на відновлення потоку закінчився"}.
|
||||
@@ -468,6 +541,7 @@
|
||||
{"Too many unacked stanzas","Занадто багато пакетів без відповідей"}.
|
||||
{"Too many users in this conference","Надто багато користувачів у цій конференції"}.
|
||||
{"Traffic rate limit is exceeded","Швидкість передачі інформації було перевищено"}.
|
||||
{"~ts's MAM Archive","Архів МАМ ~ts"}.
|
||||
{"~ts's Offline Messages Queue","Черга автономних повідомлень ~ts"}.
|
||||
{"Tuesday","Вівторок"}.
|
||||
{"Unable to generate a CAPTCHA","Нема можливості згенерувати капчу"}.
|
||||
@@ -475,17 +549,23 @@
|
||||
{"Unauthorized","Не авторизовано"}.
|
||||
{"Unexpected action","Несподівана дія"}.
|
||||
{"Unexpected error condition: ~p","Умова несподіваної помилки: ~p"}.
|
||||
{"Uninstall","Видалити"}.
|
||||
{"Unregister an XMPP account","Видалити обліковий запис XMPP"}.
|
||||
{"Unregister","Видалити"}.
|
||||
{"Unsupported <index/> element","Непідтримуваний елемент <index/>"}.
|
||||
{"Unsupported version","Непідтримувана версія"}.
|
||||
{"Update message of the day (don't send)","Оновити повідомлення дня (не надсилати)"}.
|
||||
{"Update message of the day on all hosts (don't send)","Оновити повідомлення дня на всіх хостах (не надсилати)"}.
|
||||
{"Update specs to get modules source, then install desired ones.","Оновіть специфікації, щоб отримати джерело модулів, а потім встановіть потрібні."}.
|
||||
{"Update Specs","Оновити характеристики"}.
|
||||
{"Updating the vCard is not supported by the vCard storage backend","Оновлення vCard не підтримується системою зберігання vCard"}.
|
||||
{"Upgrade","Оновлення"}.
|
||||
{"URL for Archived Discussion Logs","URL-адреса для журналів архівних обговорень"}.
|
||||
{"User already exists","Користувач уже існує"}.
|
||||
{"User JID","JID Користувача"}.
|
||||
{"User (jid)","Користувач (jid)"}.
|
||||
{"User Management","Управління Користувачами"}.
|
||||
{"User not allowed to perform an IQ set on another user's vCard.","Користувачеві заборонено виконувати тест IQ на vCard іншого користувача."}.
|
||||
{"User removed","Користувача видалено"}.
|
||||
{"User session not found","Сеанс користувача не знайдено"}.
|
||||
{"User session terminated","Сеанс користувача припинено"}.
|
||||
@@ -495,31 +575,45 @@
|
||||
{"Users Last Activity","Статистика останнього підключення користувачів"}.
|
||||
{"Users","Користувачі"}.
|
||||
{"User","Користувач"}.
|
||||
{"Value 'get' of 'type' attribute is not allowed","Значення 'get' атрибута 'type' не дозволене"}.
|
||||
{"Value of '~s' should be boolean","Значення \"~s\" має бути логічним"}.
|
||||
{"Value of '~s' should be datetime string","Значення \"~s\" має бути рядком дати і часу"}.
|
||||
{"Value of '~s' should be integer","Значення \"~s\" має бути цілим числом"}.
|
||||
{"Value 'set' of 'type' attribute is not allowed","Значення 'set' атрибута 'type' не допускається"}.
|
||||
{"vCard User Search","Пошук користувачів по vCard"}.
|
||||
{"View joined MIX channels","Перегляд приєднаних каналів MIX"}.
|
||||
{"Virtual Hosts","віртуальні хости"}.
|
||||
{"Visitors are not allowed to change their nicknames in this room","Відвідувачам не дозволяється змінювати псевдонім в цій кімнаті"}.
|
||||
{"Visitors are not allowed to send messages to all occupants","Відвідувачам не дозволяється надсилати повідомлення всім присутнім"}.
|
||||
{"Visitor","Відвідувач"}.
|
||||
{"Voice requests are disabled in this conference","Голосові запити відключені в цій конференції"}.
|
||||
{"Voice request","Голосовий запит"}.
|
||||
{"Web client which allows to join the room anonymously","Веб-клієнт, який дозволяє анонімно приєднатися до кімнати"}.
|
||||
{"Wednesday","Середа"}.
|
||||
{"When a new subscription is processed and whenever a subscriber comes online","Коли обробляється нова підписка та щоразу, коли абонент виходить в Інтернет"}.
|
||||
{"When a new subscription is processed","Під час обробки нової підписки"}.
|
||||
{"When to send the last published item","Коли надсилати останній опублікований елемент"}.
|
||||
{"Whether an entity wants to receive an XMPP message body in addition to the payload format","Чи бажає суб’єкт отримувати тіло повідомлення XMPP на додаток до формату корисного навантаження"}.
|
||||
{"Whether an entity wants to receive digests (aggregations) of notifications or all notifications individually","Чи бажає організація отримувати дайджести (агрегації) сповіщень чи всі сповіщення окремо"}.
|
||||
{"Whether an entity wants to receive or disable notifications","Чи бажає суб’єкт отримувати або вимикати сповіщення"}.
|
||||
{"Whether owners or publisher should receive replies to items","Чи повинні власники або видавець отримувати відповіді на елементи"}.
|
||||
{"Whether the node is a leaf (default) or a collection","Чи є вузол листом (типово) чи колекцією"}.
|
||||
{"Whether to allow subscriptions","Дозволяти підписку"}.
|
||||
{"Whether to make all subscriptions temporary, based on subscriber presence","Чи робити всі підписки тимчасовими, залежно від присутності читача"}.
|
||||
{"Whether to notify owners about new subscribers and unsubscribes","Чи повідомляти власників про нових читачів та їх втрату"}.
|
||||
{"Who can send private messages","Хто може надсилати приватні повідомлення"}.
|
||||
{"Who may associate leaf nodes with a collection","Хто може пов’язувати листові вузли з колекцією"}.
|
||||
{"Wrong parameters in the web formulary","Неправильні параметри у веб-формі"}.
|
||||
{"Wrong xmlns","Неправильний xmlns"}.
|
||||
{"XMPP Account Registration","Реєстрація облікового запису XMPP"}.
|
||||
{"XMPP Domains","Домени XMPP"}.
|
||||
{"XMPP Show Value of Away","XMPP Показати значення Away"}.
|
||||
{"XMPP Show Value of Chat","XMPP Показати значення чату"}.
|
||||
{"XMPP Show Value of DND (Do Not Disturb)","XMPP Показати значення DND (Не турбувати)"}.
|
||||
{"XMPP Show Value of XA (Extended Away)","XMPP Показати значення XA (розширено)"}.
|
||||
{"XMPP URI of Associated Publish-Subscribe Node","XMPP URI-адреса асоційованого вузла публікацій-підписок"}.
|
||||
{"You are being removed from the room because of a system shutdown","Ви будете видалені з кімнати через завершення роботи системи"}.
|
||||
{"You are not allowed to send private messages","Ви не можете надсилати приватні повідомлення"}.
|
||||
{"You are not joined to the channel","Ви не приєднані до каналу"}.
|
||||
{"You can later change your password using an XMPP client.","Пізніше ви можете змінити пароль за допомогою XMPP-клієнта."}.
|
||||
{"You have been banned from this room","Вам заборонено входити в цю конференцію"}.
|
||||
|
||||
+159
-155
@@ -4,11 +4,11 @@
|
||||
%% https://docs.ejabberd.im/developer/extending-ejabberd/localization/
|
||||
|
||||
{" (Add * to the end of field to match substring)"," (在字段末尾添加 * 以匹配子字符串)"}.
|
||||
{" has set the subject to: "," 已将话题设置为: "}.
|
||||
{" has set the subject to: "," 已将主题设置为: "}.
|
||||
{"# participants","# 参与者"}.
|
||||
{"A description of the node","节点的描述"}.
|
||||
{"A friendly name for the node","节点的易记名称"}.
|
||||
{"A password is required to enter this room","进入此群聊需要密码"}.
|
||||
{"A friendly name for the node","节点的友好名称"}.
|
||||
{"A password is required to enter this room","需要密码才能进入此房间"}.
|
||||
{"A Web Page","网页"}.
|
||||
{"Accept","接受"}.
|
||||
{"Access denied by service policy","服务策略拒绝访问"}.
|
||||
@@ -23,30 +23,32 @@
|
||||
{"All activity","所有活动"}.
|
||||
{"All Users","所有用户"}.
|
||||
{"Allow subscription","允许订阅"}.
|
||||
{"Allow this Jabber ID to subscribe to this pubsub node?","允许此 Jabber ID 订阅此 pubsub 节点?"}.
|
||||
{"Allow this person to register with the room?","允许此用户注册此群聊?"}.
|
||||
{"Allow users to change the subject","允许用户更改话题"}.
|
||||
{"Allow this Jabber ID to subscribe to this pubsub node?","是否允许此 Jabber ID 订阅此 pubsub 节点?"}.
|
||||
{"Allow this person to register with the room?","是否允许此用户在房间注册?"}.
|
||||
{"Allow users to change the subject","允许用户更改主题"}.
|
||||
{"Allow users to query other users","允许用户查询其他用户"}.
|
||||
{"Allow users to send invites","允许用户发送邀请"}.
|
||||
{"Allow users to send private messages","允许用户发送私信"}.
|
||||
{"Allow visitors to change nickname","允许访客更改昵称"}.
|
||||
{"Allow visitors to send private messages to","允许访客发送私信至"}.
|
||||
{"Allow visitors to send status text in presence updates","允许访客在在线状态更新中发送状态文本"}.
|
||||
{"Allow visitors to send voice requests","允许访客发送发言请求"}.
|
||||
{"An associated LDAP group that defines room membership; this should be an LDAP Distinguished Name according to an implementation-specific or deployment-specific definition of a group.","与定义群聊成员资格相关联的 LDAP 组;根据组的特定实施或特定部署的定义,使用 LDAP 专有名称。"}.
|
||||
{"Allow visitors to change nickname","允许参观者更改昵称"}.
|
||||
{"Allow visitors to send private messages to","允许参观者发送私信至"}.
|
||||
{"Allow visitors to send status text in presence updates","允许参观者在在线状态更新中发送状态文本"}.
|
||||
{"Allow visitors to send voice requests","允许参观者发送发言权请求"}.
|
||||
{"An associated LDAP group that defines room membership; this should be an LDAP Distinguished Name according to an implementation-specific or deployment-specific definition of a group.","与定义房间成员资格相关联的 LDAP 组;根据组的特定实施或特定部署的定义,使用 LDAP 专有名称。"}.
|
||||
{"Announcements","公告"}.
|
||||
{"Answer associated with a picture","与图片相关的答案"}.
|
||||
{"Answer associated with a video","与视频相关的答案"}.
|
||||
{"Answer associated with speech","与讲话相关的答案"}.
|
||||
{"Answer to a question","问题的答案"}.
|
||||
{"Anyone in the specified roster group(s) may subscribe and retrieve items","指定花名册组中的任何人都可以订阅和检索项目"}.
|
||||
{"Anyone in the specified roster group(s) may subscribe and retrieve items","指定名册组中的任何人都可以订阅和检索项目"}.
|
||||
{"Anyone may associate leaf nodes with the collection","任何人都可以将叶节点与集合关联"}.
|
||||
{"Anyone may publish","任何人都可以发布"}.
|
||||
{"Anyone may subscribe and retrieve items","任何人都可以订阅和检索内容项"}.
|
||||
{"Anyone may subscribe and retrieve items","任何人都可以订阅和检索项目"}.
|
||||
{"Anyone with a presence subscription of both or from may subscribe and retrieve items","任何拥有 both 或 from 的在线状态订阅的用户都可以订阅和检索项目"}.
|
||||
{"Anyone with Voice","任何有发言权的人"}.
|
||||
{"Anyone","任何人"}.
|
||||
{"API Commands","API 命令"}.
|
||||
{"April","四月"}.
|
||||
{"Arguments","参数"}.
|
||||
{"Attribute 'channel' is required for this request","此请求要求“channel”属性"}.
|
||||
{"Attribute 'id' is mandatory for MIX messages","对于 MIX 消息,“id”属性是必需的"}.
|
||||
{"Attribute 'jid' is not allowed here","此处不允许“jid”属性"}.
|
||||
@@ -75,22 +77,23 @@
|
||||
{"Channel JID","频道 JID"}.
|
||||
{"Channels","频道"}.
|
||||
{"Characters not allowed:","不允许字符:"}.
|
||||
{"Chatroom configuration modified","群聊配置已修改"}.
|
||||
{"Chatroom is created","群聊已创建"}.
|
||||
{"Chatroom is destroyed","群聊已解散"}.
|
||||
{"Chatroom is started","群聊已开始"}.
|
||||
{"Chatroom is stopped","群聊已停止"}.
|
||||
{"Chatrooms","群聊"}.
|
||||
{"Chatroom configuration modified","聊天室配置已修改"}.
|
||||
{"Chatroom is created","已创建聊天室"}.
|
||||
{"Chatroom is destroyed","已解散聊天室"}.
|
||||
{"Chatroom is started","已启动聊天室"}.
|
||||
{"Chatroom is stopped","已停止聊天室"}.
|
||||
{"Chatrooms","聊天室"}.
|
||||
{"Choose a username and password to register with this server","请选择要在此服务器中注册的用户名和密码"}.
|
||||
{"Choose storage type of tables","选择表的存储类型"}.
|
||||
{"Choose whether to approve this entity's subscription.","选择是否批准此实体的订阅。"}.
|
||||
{"City","城市"}.
|
||||
{"Client acknowledged more stanzas than sent by server","客户端确认的节数多于服务器发送的节数"}.
|
||||
{"Clustering","集群"}.
|
||||
{"Commands","命令"}.
|
||||
{"Conference room does not exist","群聊不存在"}.
|
||||
{"Configuration of room ~s","群聊 ~s 的配置"}.
|
||||
{"Conference room does not exist","会议室不存在"}.
|
||||
{"Configuration of room ~s","房间 ~s 的配置"}.
|
||||
{"Configuration","配置"}.
|
||||
{"Contact Addresses (normally, room owner or owners)","联系人地址(通常为群聊所有者)"}.
|
||||
{"Contact Addresses (normally, room owner or owners)","联系地址(通常为房间所有者)"}.
|
||||
{"Country","国家/地区"}.
|
||||
{"Current Discussion Topic","当前讨论话题"}.
|
||||
{"Database failure","数据库失败"}.
|
||||
@@ -104,16 +107,16 @@
|
||||
{"Deliver event notifications","传递事件通知"}.
|
||||
{"Deliver payloads with event notifications","用事件通知传递有效负载"}.
|
||||
{"Disc only copy","仅磁盘副本"}.
|
||||
{"Don't tell your password to anybody, not even the administrators of the XMPP server.","不要将密码告诉任何人,甚至是 XMPP 服务的管理员。"}.
|
||||
{"Don't tell your password to anybody, not even the administrators of the XMPP server.","不要将您的密码告诉任何人,甚至是 XMPP 服务器的管理员。"}.
|
||||
{"Dump Backup to Text File at ","将备份转储到位于以下位置的文本文件 "}.
|
||||
{"Dump to Text File","转储到文本文件"}.
|
||||
{"Duplicated groups are not allowed by RFC6121","按照 RFC6121 的规则,不允许重复的组"}.
|
||||
{"Dynamically specify a replyto of the item publisher","动态指定项目发布者的 replyto"}.
|
||||
{"Edit Properties","编辑属性"}.
|
||||
{"Either approve or decline the voice request.","批准或拒绝发言请求。"}.
|
||||
{"Either approve or decline the voice request.","批准或拒绝发言权请求。"}.
|
||||
{"ejabberd HTTP Upload service","ejabberd HTTP 上传服务"}.
|
||||
{"ejabberd MUC module","ejabberd MUC 模块"}.
|
||||
{"ejabberd Multicast service","ejabberd 多重映射服务"}.
|
||||
{"ejabberd Multicast service","ejabberd 多播服务"}.
|
||||
{"ejabberd Publish-Subscribe module","ejabberd 发布–订阅模块"}.
|
||||
{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 字节流模块"}.
|
||||
{"ejabberd vCard module","ejabberd vCard 模块"}.
|
||||
@@ -123,7 +126,7 @@
|
||||
{"Email","电子邮件"}.
|
||||
{"Enable hats","启用头衔"}.
|
||||
{"Enable logging","启用日志记录"}.
|
||||
{"Enable message archiving","启用消息存档"}.
|
||||
{"Enable message archiving","启用消息归档"}.
|
||||
{"Enabling push without 'node' attribute is not supported","不支持没有“node”属性就启用推送"}.
|
||||
{"End User Session","结束用户会话"}.
|
||||
{"Enter nickname you want to register","请输入要注册的昵称"}.
|
||||
@@ -133,26 +136,26 @@
|
||||
{"Enter path to text file","请输入文本文件的路径"}.
|
||||
{"Enter the text you see","请输入您看到的文本"}.
|
||||
{"Erlang XMPP Server","Erlang XMPP 服务器"}.
|
||||
{"Exclude Jabber IDs from CAPTCHA challenge","从验证码挑战中排除 Jabber ID"}.
|
||||
{"Exclude Jabber IDs from CAPTCHA challenge","从验证码挑战中排除的 Jabber ID"}.
|
||||
{"Export all tables as SQL queries to a file:","将所有表以 SQL 查询导出到文件:"}.
|
||||
{"Export data of all users in the server to PIEFXIS files (XEP-0227):","将服务器中所有用户的数据导出到 PIEFXIS 文件(XEP-0227):"}.
|
||||
{"Export data of users in a host to PIEFXIS files (XEP-0227):","将主机中用户的数据导出到 PIEFXIS 文件(XEP-0227):"}.
|
||||
{"External component failure","外部组件故障"}.
|
||||
{"External component timeout","外部组件超时"}.
|
||||
{"Failed to activate bytestream","激活字节流失败"}.
|
||||
{"Failed to extract JID from your voice request approval","无法从发言请求批准中提取 JID"}.
|
||||
{"Failed to map delegated namespace to external component","未能将委托命名空间映射到外部组件"}.
|
||||
{"Failed to parse HTTP response","HTTP 响应解析失败"}.
|
||||
{"Failed to activate bytestream","无法激活字节流"}.
|
||||
{"Failed to extract JID from your voice request approval","无法从您的发言权请求批准中提取 JID"}.
|
||||
{"Failed to map delegated namespace to external component","无法将委托命名空间映射到外部组件"}.
|
||||
{"Failed to parse HTTP response","无法解析 HTTP 响应"}.
|
||||
{"Failed to process option '~s'","无法处理选项“~s”"}.
|
||||
{"Family Name","姓氏"}.
|
||||
{"FAQ Entry","常见问题解答"}.
|
||||
{"FAQ Entry","常见问题条目"}.
|
||||
{"February","二月"}.
|
||||
{"File larger than ~w bytes","文件大于 ~w 字节"}.
|
||||
{"Fill in the form to search for any matching XMPP User","填写表单以搜索任何匹配的 XMPP 用户"}.
|
||||
{"Friday","周五"}.
|
||||
{"From ~ts","来自 ~ts"}.
|
||||
{"Full List of Room Admins","群聊管理员完整列表"}.
|
||||
{"Full List of Room Owners","群聊所有者完整列表"}.
|
||||
{"Full List of Room Admins","房间管理员的完整列表"}.
|
||||
{"Full List of Room Owners","房间所有者的完整列表"}.
|
||||
{"Full Name","全名"}.
|
||||
{"Get List of Online Users","获取在线用户列表"}.
|
||||
{"Get List of Registered Users","获取注册用户列表"}.
|
||||
@@ -161,14 +164,14 @@
|
||||
{"Get Pending","获取待处理"}.
|
||||
{"Get User Last Login Time","获取用户上次登录时间"}.
|
||||
{"Get User Statistics","获取用户统计数据"}.
|
||||
{"Given Name","中间名"}.
|
||||
{"Grant voice to this person?","授予此用户发言权?"}.
|
||||
{"Given Name","名字"}.
|
||||
{"Grant voice to this person?","是否授予此用户发言权?"}.
|
||||
{"has been banned","已被封禁"}.
|
||||
{"has been kicked because of a system shutdown","因系统关闭而被踢出"}.
|
||||
{"has been kicked because of an affiliation change","由于从属关系的更改而被踢出"}.
|
||||
{"has been kicked because the room has been changed to members-only","被踢出,因为群聊已更改为仅成员进入"}.
|
||||
{"has been kicked because the room has been changed to members-only","被踢出,因为房间已更改为仅成员"}.
|
||||
{"has been kicked","已被踢出"}.
|
||||
{"Hash of the vCard-temp avatar of this room","此群聊 vCard-temp 头像的散列值"}.
|
||||
{"Hash of the vCard-temp avatar of this room","此房间的 vCard-temp 头像的散列"}.
|
||||
{"Hat title","头衔标题"}.
|
||||
{"Hat URI","头衔 URI"}.
|
||||
{"Hats limit exceeded","已超过头衔限制"}.
|
||||
@@ -197,135 +200,134 @@
|
||||
{"Insufficient privilege","权限不足"}.
|
||||
{"Internal server error","内部服务器错误"}.
|
||||
{"Invalid 'from' attribute in forwarded message","转发消息中的“from”属性无效"}.
|
||||
{"Invalid node name","无效的节点名称"}.
|
||||
{"Invalid node name","节点名称无效"}.
|
||||
{"Invalid 'previd' value","“previd”值无效"}.
|
||||
{"Invitations are not allowed in this conference","此群聊不允许邀请"}.
|
||||
{"Invitations are not allowed in this conference","此会议不允许邀请"}.
|
||||
{"IP addresses","IP 地址"}.
|
||||
{"is now known as","现在昵称为"}.
|
||||
{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","不允许向此群聊发送错误消息。参与者(~s)发送了错误消息(~s),被踢出了群聊"}.
|
||||
{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","不允许向此房间发送错误消息。参与者(~s)发送了错误消息(~s),被踢出了房间"}.
|
||||
{"It is not allowed to send private messages of type \"groupchat\"","不允许发送“groupchat”类型的私信"}.
|
||||
{"It is not allowed to send private messages to the conference","不允许向群聊发送私信"}.
|
||||
{"It is not allowed to send private messages to the conference","不允许向会议发送私信"}.
|
||||
{"Jabber ID","Jabber ID"}.
|
||||
{"January","一月"}.
|
||||
{"JID normalization denied by service policy","服务策略拒绝 JID 规范化"}.
|
||||
{"JID normalization failed","JID 规范化失败"}.
|
||||
{"Joined MIX channels of ~ts","加入了 ~ts 的 MIX 频道"}.
|
||||
{"Joined MIX channels:","加入了 MIX 频道:"}.
|
||||
{"joins the room","加入群聊"}.
|
||||
{"joins the room","加入房间"}.
|
||||
{"July","七月"}.
|
||||
{"June","六月"}.
|
||||
{"Just created","刚刚创建"}.
|
||||
{"Last Activity","上次活动"}.
|
||||
{"Last login","上次登录"}.
|
||||
{"Last message","最近消息"}.
|
||||
{"Last message","最后一条消息"}.
|
||||
{"Last month","上个月"}.
|
||||
{"Last year","去年"}.
|
||||
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","文本的 SHA-256 哈希的最低有效位应等于十六进制标签"}.
|
||||
{"leaves the room","离开群聊"}.
|
||||
{"List of users with hats","有头衔用户的列表"}.
|
||||
{"List users with hats","有头衔用户列表"}.
|
||||
{"Least significant bits of SHA-256 hash of text should equal hexadecimal label","文本的 SHA-256 散列的最低有效位应等于十六进制标签"}.
|
||||
{"leaves the room","离开房间"}.
|
||||
{"List of users with hats","有头衔的用户列表"}.
|
||||
{"List users with hats","列出有头衔的用户"}.
|
||||
{"Logged Out","已登出"}.
|
||||
{"Logging","日志记录"}.
|
||||
{"Make participants list public","公开参与者列表"}.
|
||||
{"Make room CAPTCHA protected","开启群聊验证码保护"}.
|
||||
{"Make room members-only","仅成员进入的群聊"}.
|
||||
{"Make room moderated","开启群聊发言审核"}.
|
||||
{"Make room password protected","开启群聊密码保护"}.
|
||||
{"Make room persistent","持续存在的群聊"}.
|
||||
{"Make room public searchable","可公开搜索的群聊"}.
|
||||
{"Make room CAPTCHA protected","启用房间验证码保护"}.
|
||||
{"Make room members-only","将房间设为仅成员"}.
|
||||
{"Make room moderated","启用房间发言审核"}.
|
||||
{"Make room password protected","启用房间密码保护"}.
|
||||
{"Make room persistent","将房间设为持久"}.
|
||||
{"Make room public searchable","将房间设为可公开搜索"}.
|
||||
{"Malformed username","用户名格式不正确"}.
|
||||
{"MAM preference modification denied by service policy","服务策略拒绝修改 MAM 首选项"}.
|
||||
{"March","三月"}.
|
||||
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","要持久化的最大项目数 #,或“max”表示除服务器施加的最大值之外没有特定限制"}.
|
||||
{"Max # of items to persist, or `max` for no specific limit other than a server imposed maximum","要保留的最大项目数 #,或 `max` 表示除服务器强制规定的最大值外无其他特定限制"}.
|
||||
{"Max payload size in bytes","最大有效负载大小(字节)"}.
|
||||
{"Maximum file size","最大文件大小"}.
|
||||
{"Maximum Number of History Messages Returned by Room","群聊返回的聊天记录消息的最大值"}.
|
||||
{"Maximum number of items to persist","要持久化的最大项目数"}.
|
||||
{"Maximum Number of Occupants","最大参与者人数"}.
|
||||
{"Maximum Number of History Messages Returned by Room","房间返回的最大历史消息数"}.
|
||||
{"Maximum number of items to persist","要保留的最大项目数"}.
|
||||
{"Maximum Number of Occupants","最大使用者数"}.
|
||||
{"May","五月"}.
|
||||
{"Membership is required to enter this room","进入此群聊需要成员资格"}.
|
||||
{"Memorize your password, or write it in a paper placed in a safe place. In XMPP there isn't an automated way to recover your password if you forget it.","请记住密码,或将密码写在纸上,放在安全的地方。在 XMPP 中,如果您忘记密码,没有自动恢复密码的方法。"}.
|
||||
{"Membership is required to enter this room","进入此房间需要成员资格"}.
|
||||
{"Memorize your password, or write it in a paper placed in a safe place. In XMPP there isn't an automated way to recover your password if you forget it.","请记住您的密码,或写在放在安全地方的纸上。在 XMPP 中,如果您忘记密码,没有自动恢复密码的方法。"}.
|
||||
{"Mere Availability in XMPP (No Show Value)","XMPP 中的可用性(无显示值)"}.
|
||||
{"Message body","消息正文"}.
|
||||
{"Message not found in forwarded payload","在转发的有效负载中找不到消息"}.
|
||||
{"Message not found in forwarded payload","在转发的有效负载中未找到消息"}.
|
||||
{"Messages from strangers are rejected","拒绝来自陌生人的消息"}.
|
||||
{"Messages of type headline","标题类型的消息"}.
|
||||
{"Messages of type normal","普通类型的消息"}.
|
||||
{"Middle Name","中间名"}.
|
||||
{"Minimum interval between voice requests (in seconds)","发言请求之间的最短间隔时间(秒)"}.
|
||||
{"Minimum interval between voice requests (in seconds)","发言权请求的最短间隔时间(秒)"}.
|
||||
{"Moderator privileges required","需要主持人权限"}.
|
||||
{"Moderators Only","仅主持人"}.
|
||||
{"Moderator","主持人"}.
|
||||
{"Module failed to handle the query","模块无法处理查询"}.
|
||||
{"Monday","周一"}.
|
||||
{"Multicast","多重映射"}.
|
||||
{"Multicast","多播"}.
|
||||
{"Multiple <item/> elements are not allowed by RFC6121","按照 RFC6121,多个 <item/> 元素是不允许的"}.
|
||||
{"Multi-User Chat","多用户聊天"}.
|
||||
{"Name","名称"}.
|
||||
{"Natural Language for Room Discussions","群聊讨论的自然语言"}.
|
||||
{"Natural-Language Room Name","自然语言群聊名称"}.
|
||||
{"Natural Language for Room Discussions","房间讨论的自然语言"}.
|
||||
{"Natural-Language Room Name","自然语言房间名称"}.
|
||||
{"Neither 'jid' nor 'nick' attribute found","未找到“jid”和“nick”属性"}.
|
||||
{"Neither 'role' nor 'affiliation' attribute found","未找到“role”或“affiliation”属性"}.
|
||||
{"Never","从不"}.
|
||||
{"New Password:","新密码:"}.
|
||||
{"Nickname can't be empty","昵称不能为空"}.
|
||||
{"Nickname Registration at ","昵称注册于 "}.
|
||||
{"Nickname ~s does not exist in the room","昵称 ~s 不在此群聊"}.
|
||||
{"Nickname ~s does not exist in the room","昵称 ~s 在房间中不存在"}.
|
||||
{"Nickname","昵称"}.
|
||||
{"No address elements found","找不到地址元素"}.
|
||||
{"No addresses element found","找不到地址元素"}.
|
||||
{"No address elements found","未找到地址元素"}.
|
||||
{"No addresses element found","未找到地址元素"}.
|
||||
{"No 'affiliation' attribute found","未找到“affiliation”属性"}.
|
||||
{"No available resource found","找不到可用资源"}.
|
||||
{"No body provided for announce message","没有为公告消息提供正文"}.
|
||||
{"No child elements found","没有找到子元素"}.
|
||||
{"No data form found","没有找到数据表单"}.
|
||||
{"No Data","没有数据"}.
|
||||
{"No features available","没有可用功能"}.
|
||||
{"No available resource found","未找到可用资源"}.
|
||||
{"No body provided for announce message","未提供公告消息正文"}.
|
||||
{"No child elements found","未找到子元素"}.
|
||||
{"No data form found","未找到数据表单"}.
|
||||
{"No Data","无数据"}.
|
||||
{"No features available","无可用功能"}.
|
||||
{"No <forwarded/> element found","未找到 <forwarded/> 元素"}.
|
||||
{"No hook has processed this command","没有钩子处理此命令"}.
|
||||
{"No info about last activity found","未找到有关上次活动的信息"}.
|
||||
{"No 'item' element found","未找到“item”元素"}.
|
||||
{"No items found in this query","在此查询中找不到任何项目"}.
|
||||
{"No limit","没有限制"}.
|
||||
{"No items found in this query","在此查询中未找到任何项目"}.
|
||||
{"No limit","无限制"}.
|
||||
{"No module is handling this query","没有模块正在处理此查询"}.
|
||||
{"No node specified","未指定节点"}.
|
||||
{"No 'password' found in data form","在数据表单中找不到“password”"}.
|
||||
{"No 'password' found in this query","在此查询中找不到“password”"}.
|
||||
{"No 'path' found in data form","在数据表单中找不到“path”"}.
|
||||
{"No 'password' found in data form","在数据表单中未找到“password”"}.
|
||||
{"No 'password' found in this query","在此查询中未找到“password”"}.
|
||||
{"No 'path' found in data form","在数据表单中未找到“path”"}.
|
||||
{"No pending subscriptions found","未找到待处理的订阅"}.
|
||||
{"No privacy list with this name found","未找到具有此名称的隐私列表"}.
|
||||
{"No private data found in this query","在此查询中找不到专用数据"}.
|
||||
{"No <privileged_iq/> element found","未找到 <privileged_iq/> 元素"}.
|
||||
{"No running node found","找不到正在运行的节点"}.
|
||||
{"No private data found in this query","在此查询中未找到专用数据"}.
|
||||
{"No running node found","未找到正在运行的节点"}.
|
||||
{"No services available","无可用服务"}.
|
||||
{"No statistics found for this item","未找到此项目的统计数据"}.
|
||||
{"No 'to' attribute found in the invitation","邀请中未找到“to”属性"}.
|
||||
{"Nobody","没有人"}.
|
||||
{"Node already exists","节点已存在"}.
|
||||
{"Node ID","节点 ID"}.
|
||||
{"Node index not found","没有找到节点索引"}.
|
||||
{"Node not found","没有找到节点"}.
|
||||
{"Node index not found","未找到节点索引"}.
|
||||
{"Node not found","未找到节点"}.
|
||||
{"Node ~p","节点 ~p"}.
|
||||
{"Nodeprep has failed","Nodeprep 已失效"}.
|
||||
{"Nodeprep has failed","Nodeprep 失败了"}.
|
||||
{"Nodes","节点"}.
|
||||
{"Node","节点"}.
|
||||
{"None","无"}.
|
||||
{"Not allowed","不允许"}.
|
||||
{"Not Found","没有找到"}.
|
||||
{"Not Found","未找到"}.
|
||||
{"Not subscribed","未订阅"}.
|
||||
{"Notify subscribers when items are removed from the node","从节点中移除项目时通知订阅者"}.
|
||||
{"Notify subscribers when the node configuration changes","节点配置更改时通知订阅者"}.
|
||||
{"Notify subscribers when the node is deleted","删除节点时通知订阅者"}.
|
||||
{"November","十一月"}.
|
||||
{"Number of answers required","所需答案数量"}.
|
||||
{"Number of occupants","参与者人数"}.
|
||||
{"Number of Offline Messages","离线消息数量"}.
|
||||
{"Number of answers required","所需答案数"}.
|
||||
{"Number of occupants","使用者数"}.
|
||||
{"Number of Offline Messages","离线消息数"}.
|
||||
{"Number of online users","在线用户数"}.
|
||||
{"Number of registered users","注册用户数"}.
|
||||
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","等待多少秒后自动清除项目,“max”表示除服务器施加的最大值外没有特定限制"}.
|
||||
{"Occupants are allowed to invite others","允许参与者邀请别人"}.
|
||||
{"Occupants are allowed to query others","允许参与者查询别人"}.
|
||||
{"Occupants May Change the Subject","参与者可以更改话题"}.
|
||||
{"Number of seconds after which to automatically purge items, or `max` for no specific limit other than a server imposed maximum","自动清除项目前的秒数,`max` 表示除服务器强制规定的最大值外无其他特定限制"}.
|
||||
{"Occupants are allowed to invite others","允许使用者邀请他人"}.
|
||||
{"Occupants are allowed to query others","允许使用者查询他人"}.
|
||||
{"Occupants May Change the Subject","使用者可以更改主题"}.
|
||||
{"October","十月"}.
|
||||
{"OK","确定"}.
|
||||
{"Old Password:","旧密码:"}.
|
||||
@@ -335,13 +337,13 @@
|
||||
{"Only deliver notifications to available users","仅向在线用户发送通知"}.
|
||||
{"Only <enable/> or <disable/> tags are allowed","仅允许 <enable/> 或 <disable/> 标签"}.
|
||||
{"Only <list/> element is allowed in this query","此查询中只允许 <list/> 元素"}.
|
||||
{"Only members may query archives of this room","只有成员才能查询此群聊的存档"}.
|
||||
{"Only moderators and participants are allowed to change the subject in this room","只允许主持人和参与者在此群聊更改话题"}.
|
||||
{"Only moderators are allowed to change the subject in this room","只允许主持人在此群聊更改话题"}.
|
||||
{"Only members may query archives of this room","只有成员才能查询此房间的归档"}.
|
||||
{"Only moderators and participants are allowed to change the subject in this room","只允许主持人和参与者更改此房间的主题"}.
|
||||
{"Only moderators are allowed to change the subject in this room","只允许主持人更改此房间的主题"}.
|
||||
{"Only moderators are allowed to retract messages","只允许主持人撤回消息"}.
|
||||
{"Only moderators can approve voice requests","只有主持人才能批准发言请求"}.
|
||||
{"Only occupants are allowed to send messages to the conference","只允许参与者向群聊发送消息"}.
|
||||
{"Only occupants are allowed to send queries to the conference","只允许参与者向群聊发送查询"}.
|
||||
{"Only moderators can approve voice requests","只有主持人可以批准发言权请求"}.
|
||||
{"Only occupants are allowed to send messages to the conference","只允许使用者向会议发送消息"}.
|
||||
{"Only occupants are allowed to send queries to the conference","只允许使用者向会议发送查询"}.
|
||||
{"Only publishers may publish","只有发布者才能发布"}.
|
||||
{"Only service administrators are allowed to send service messages","只允许服务管理员发送服务消息"}.
|
||||
{"Only those on a whitelist may associate leaf nodes with the collection","只有白名单上的那些可以将叶节点与集合关联"}.
|
||||
@@ -361,17 +363,17 @@
|
||||
{"Path to Dir","目录路径"}.
|
||||
{"Path to File","文件路径"}.
|
||||
{"Payload semantic type information","有效负载语义类型信息"}.
|
||||
{"Period: ","持续时间: "}.
|
||||
{"Persist items to storage","将项目持久化到存储"}.
|
||||
{"Period: ","时段: "}.
|
||||
{"Persist items to storage","将项目保留到存储"}.
|
||||
{"Persistent","持久"}.
|
||||
{"Ping query is incorrect","Ping 查询不正确"}.
|
||||
{"Ping","Ping"}.
|
||||
{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","注意:这些选项只会备份内置的 Mnesia 数据库。如果使用 ODBC 模块,还需要单独备份 SQL 数据库。"}.
|
||||
{"Please, wait for a while before sending new voice request","请稍候,然后再发送新的发言请求"}.
|
||||
{"Please, wait for a while before sending new voice request","请稍候再发送新的发言权请求"}.
|
||||
{"Pong","Pong"}.
|
||||
{"Possessing 'ask' attribute is not allowed by RFC6121","按照 RFC6121, 不允许有“ask”属性"}.
|
||||
{"Present real Jabber IDs to","将用户真实 JID 显示给"}.
|
||||
{"Previous session not found","上一个会话未找到"}.
|
||||
{"Present real Jabber IDs to","将真实 Jabber ID 显示给"}.
|
||||
{"Previous session not found","未找到上一个会话"}.
|
||||
{"Previous session PID has been killed","上一个会话 PID 已终止"}.
|
||||
{"Previous session PID has exited","上一个会话 PID 已退出"}.
|
||||
{"Previous session PID is dead","上一个会话 PID 已失效"}.
|
||||
@@ -382,8 +384,8 @@
|
||||
{"Publish-Subscribe","发布–订阅"}.
|
||||
{"PubSub subscriber request","PubSub 订阅者请求"}.
|
||||
{"Purge all items when the relevant publisher goes offline","相关发布者离线后清除所有项目"}.
|
||||
{"Push record not found","推送记录未找到"}.
|
||||
{"Queries to the conference members are not allowed in this room","不允许在此群聊中查询群聊成员"}.
|
||||
{"Push record not found","未找到推送记录"}.
|
||||
{"Queries to the conference members are not allowed in this room","此房间不允许向会议成员查询"}.
|
||||
{"Query to another users is forbidden","禁止查询其他用户"}.
|
||||
{"RAM and disc copy","RAM 和磁盘副本"}.
|
||||
{"RAM copy","RAM 副本"}.
|
||||
@@ -392,7 +394,7 @@
|
||||
{"Receive notification from direct child nodes only","仅接收直接子节点的通知"}.
|
||||
{"Receive notification of new items only","仅接收新项目的通知"}.
|
||||
{"Receive notification of new nodes only","仅接收新节点的通知"}.
|
||||
{"Recipient is not in the conference room","接收者不在群聊"}.
|
||||
{"Recipient is not in the conference room","接收者不在会议室"}.
|
||||
{"Register an XMPP account","注册 XMPP 账号"}.
|
||||
{"Register","注册"}.
|
||||
{"Remote copy","远程副本"}.
|
||||
@@ -407,21 +409,22 @@
|
||||
{"Restore Backup from File at ","从以下位置的文件恢复备份 "}.
|
||||
{"Restore binary backup after next ejabberd restart (requires less memory):","在下次 ejabberd 重启后恢复二进制备份(所需内存较少):"}.
|
||||
{"Restore binary backup immediately:","立即恢复二进制备份:"}.
|
||||
{"Restore plain text backup immediately:","立即恢复明文备份:"}.
|
||||
{"Restore plain text backup immediately:","立即恢复纯文本备份:"}.
|
||||
{"Restore","恢复"}.
|
||||
{"Result","结果"}.
|
||||
{"Roles and Affiliations that May Retrieve Member List","可以检索成员列表的角色和从属关系"}.
|
||||
{"Roles for which Presence is Broadcasted","广播在线状态的角色"}.
|
||||
{"Roles that May Send Private Messages","可以发送私信的角色"}.
|
||||
{"Room Configuration","群聊配置"}.
|
||||
{"Room creation is denied by service policy","服务策略拒绝群聊创建"}.
|
||||
{"Room description","群聊描述"}.
|
||||
{"Room Occupants","群聊参与者"}.
|
||||
{"Room terminates","群聊终止"}.
|
||||
{"Room title","群聊标题"}.
|
||||
{"Roster groups allowed to subscribe","允许订阅的花名册组"}.
|
||||
{"Roster size","花名册大小"}.
|
||||
{"Room Configuration","房间配置"}.
|
||||
{"Room creation is denied by service policy","服务策略拒绝创建房间"}.
|
||||
{"Room description","房间描述"}.
|
||||
{"Room Occupants","房间使用者"}.
|
||||
{"Room terminates","房间终止"}.
|
||||
{"Room title","房间标题"}.
|
||||
{"Roster groups allowed to subscribe","允许订阅的名册组"}.
|
||||
{"Roster size","名册大小"}.
|
||||
{"Running Nodes","正在运行的节点"}.
|
||||
{"~s invites you to the room ~s","~s 邀请您加入群聊 ~s"}.
|
||||
{"~s invites you to the room ~s","~s 邀请您加入房间 ~s"}.
|
||||
{"Saturday","周六"}.
|
||||
{"Search from the date","从日期搜索"}.
|
||||
{"Search Results for ","搜索结果 "}.
|
||||
@@ -438,9 +441,9 @@
|
||||
{"Session state copying timed out","会话状态复制超时"}.
|
||||
{"Set message of the day and send to online users","设置每日消息并发送给在线用户"}.
|
||||
{"Set message of the day on all hosts and send to online users","在所有主机上设置每日消息并发送给在线用户"}.
|
||||
{"Shared Roster Groups","共享的花名册组"}.
|
||||
{"Shared Roster Groups","共享名册组"}.
|
||||
{"Show Integral Table","显示完整表"}.
|
||||
{"Show Occupants Join/Leave","显示参与者加入/离开"}.
|
||||
{"Show Occupants Join/Leave","显示使用者加入/离开"}.
|
||||
{"Show Ordinary Table","显示普通表"}.
|
||||
{"Shut Down Service","关闭服务"}.
|
||||
{"SOCKS5 Bytestreams","SOCKS5 字节流"}.
|
||||
@@ -454,10 +457,10 @@
|
||||
{"Statically specify a replyto of the node owner(s)","静态指定节点所有者的 replyto"}.
|
||||
{"Stopped Nodes","已停止的节点"}.
|
||||
{"Store binary backup:","存储二进制备份:"}.
|
||||
{"Store plain text backup:","存储明文备份:"}.
|
||||
{"Stream management is already enabled","流管理已启用"}.
|
||||
{"Stream management is not enabled","流管理未启用"}.
|
||||
{"Subject","话题"}.
|
||||
{"Store plain text backup:","存储纯文本备份:"}.
|
||||
{"Stream management is already enabled","已启用流管理"}.
|
||||
{"Stream management is not enabled","未启用流管理"}.
|
||||
{"Subject","主题"}.
|
||||
{"Submitted","已提交"}.
|
||||
{"Subscriber Address","订阅者地址"}.
|
||||
{"Subscribers may publish","订阅者可以发布"}.
|
||||
@@ -468,35 +471,35 @@
|
||||
{"Text associated with a sound","与声音相关的文字"}.
|
||||
{"Text associated with a video","与视频相关的文字"}.
|
||||
{"Text associated with speech","与语音相关的文字"}.
|
||||
{"That nickname is already in use by another occupant","该昵称已被另一参与者使用了"}.
|
||||
{"That nickname is already in use by another occupant","该昵称已被其他使用者使用"}.
|
||||
{"That nickname is registered by another person","该昵称已被另一用户注册了"}.
|
||||
{"The account already exists","此账号已存在"}.
|
||||
{"The account was not unregistered","此账号未注销"}.
|
||||
{"The body text of the last received message","最后收到的消息的正文"}.
|
||||
{"The CAPTCHA is valid.","验证码有效。"}.
|
||||
{"The CAPTCHA verification has failed","验证码检查失败"}.
|
||||
{"The CAPTCHA verification has failed","验证码验证失败"}.
|
||||
{"The captcha you entered is wrong","您输入的验证码错误"}.
|
||||
{"The child nodes (leaf or collection) associated with a collection","与集合关联的子节点(叶或集合)"}.
|
||||
{"The collections with which a node is affiliated","节点所属的集合"}.
|
||||
{"The DateTime at which a leased subscription will end or has ended","租赁订阅将结束或已结束的日期时间"}.
|
||||
{"The datetime when the node was created","创建节点的日期时间"}.
|
||||
{"The default language of the node","节点的默认语言"}.
|
||||
{"The feature requested is not supported by the conference","群聊不支持请求的功能"}.
|
||||
{"The feature requested is not supported by the conference","会议不支持所请求的功能"}.
|
||||
{"The JID of the node creator","节点创建者的 JID"}.
|
||||
{"The JIDs of those to contact with questions","有问题要联系的人的 JID"}.
|
||||
{"The JIDs of those with an affiliation of owner","与所有者的从属关系有关的用户 JID"}.
|
||||
{"The JIDs of those with an affiliation of publisher","与发布者的从属关系有关的用户 JID"}.
|
||||
{"The JIDs of those to contact with questions","有疑问时需联系的人员的 JID"}.
|
||||
{"The JIDs of those with an affiliation of owner","有所有者从属关系的人员的 JID"}.
|
||||
{"The JIDs of those with an affiliation of publisher","有发布者从属关系的人员的 JID"}.
|
||||
{"The list of all online users","所有在线用户的列表"}.
|
||||
{"The list of all users","所有用户的列表"}.
|
||||
{"The list of JIDs that may associate leaf nodes with a collection","可以将叶节点与集合关联的 JID 列表"}.
|
||||
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","可以与集合关联的子节点的最大数量,或“max”表示除服务器施加的最大值外没有特定限制"}.
|
||||
{"The maximum number of child nodes that can be associated with a collection, or `max` for no specific limit other than a server imposed maximum","可以与集合关联的子节点的最大数量,或 `max` 表示除服务器强制规定的最大值外无其他特定限制"}.
|
||||
{"The minimum number of milliseconds between sending any two notification digests","发送任意两个通知摘要之间的最小毫秒数"}.
|
||||
{"The name of the node","节点的名称"}.
|
||||
{"The node is a collection node","节点是集合节点"}.
|
||||
{"The node is a leaf node (default)","节点是叶节点(默认)"}.
|
||||
{"The NodeID of the relevant node","相关节点的 NodeID"}.
|
||||
{"The number of pending incoming presence subscription requests","待处理的传入在线状态订阅请求数"}.
|
||||
{"The number of subscribers to the node","节点的订阅者数量"}.
|
||||
{"The number of subscribers to the node","节点的订阅者数"}.
|
||||
{"The number of unread or undelivered messages","未读或未传递的消息数"}.
|
||||
{"The password contains unacceptable characters","密码包含不可接受的字符"}.
|
||||
{"The password is too weak","密码太弱"}.
|
||||
@@ -505,9 +508,9 @@
|
||||
{"The password was not changed","密码未更改"}.
|
||||
{"The passwords are different","密码不同"}.
|
||||
{"The presence states for which an entity wants to receive notifications","实体要接收通知的在线状态"}.
|
||||
{"The query is only allowed from local users","仅允许本地用户查询"}.
|
||||
{"The query is only allowed from local users","仅允许来自本地用户的查询"}.
|
||||
{"The query must not contain <item/> elements","查询不能包含 <item/> 元素"}.
|
||||
{"The room subject can be modified by participants","群聊话题可由参与者修改"}.
|
||||
{"The room subject can be modified by participants","参与者可以修改房间主题"}.
|
||||
{"The semantic type information of data in the node, usually specified by the namespace of the payload (if any)","节点中数据的语义类型信息,通常由有效负载的命名空间指定(如果有)"}.
|
||||
{"The sender of the last received message","最后收到的消息的发送者"}.
|
||||
{"The stanza MUST contain only one <active/> element, one <default/> element, or one <list/> element","节必须仅包含一个 <active/> 元素、一个 <default/> 元素或一个 <list/> 元素"}.
|
||||
@@ -520,7 +523,7 @@
|
||||
{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","此处不区分大小写:MacBeth 和 Macbeth 都是 macbeth。"}.
|
||||
{"This page allows to register an XMPP account in this XMPP server. Your JID (Jabber ID) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","本页面允许在此服务器中注册 XMPP 账号,您的 JID(Jabber ID)的格式为:用户名@服务器。请仔细阅读说明以正确填写字段。"}.
|
||||
{"This page allows to unregister an XMPP account in this XMPP server.","本页面允许在此 XMPP 服务器中注销 XMPP 账号。"}.
|
||||
{"This room is not anonymous","此群聊是非匿名的"}.
|
||||
{"This room is not anonymous","此房间是非匿名的"}.
|
||||
{"This service can not process the address: ~s","此服务无法处理地址:~s"}.
|
||||
{"Thursday","周四"}.
|
||||
{"Time delay","时间延迟"}.
|
||||
@@ -530,21 +533,21 @@
|
||||
{"Token TTL","令牌 TTL"}.
|
||||
{"Too many active bytestreams","活动字节流太多"}.
|
||||
{"Too many CAPTCHA requests","验证码请求太多"}.
|
||||
{"Too many child elements","太多子元素"}.
|
||||
{"Too many <item/> elements","太多 <item/> 元素"}.
|
||||
{"Too many <list/> elements","太多 <list/> 元素"}.
|
||||
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","有太多 (~p) 失败的身份验证来自此 IP 地址 (~s),将在 UTC 时间 ~s 解除对该地址的屏蔽"}.
|
||||
{"Too many child elements","子元素太多"}.
|
||||
{"Too many <item/> elements","<item/> 元素太多"}.
|
||||
{"Too many <list/> elements","<list/> 元素太多"}.
|
||||
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","有太多(~p)失败的身份验证来自此 IP 地址(~s),将在 UTC 时间 ~s 取消对该地址的屏蔽"}.
|
||||
{"Too many receiver fields were specified","指定的接收者字段太多"}.
|
||||
{"Too many unacked stanzas","太多未确认的节"}.
|
||||
{"Too many users in this conference","此群聊中的用户太多"}.
|
||||
{"Too many unacked stanzas","未确认的节太多"}.
|
||||
{"Too many users in this conference","此会议中的用户太多"}.
|
||||
{"Traffic rate limit is exceeded","超过流量速率限制"}.
|
||||
{"~ts's MAM Archive","~ts 的 MAM 存档"}.
|
||||
{"~ts's MAM Archive","~ts 的 MAM 归档"}.
|
||||
{"~ts's Offline Messages Queue","~ts 的离线消息队列"}.
|
||||
{"Tuesday","周二"}.
|
||||
{"Unable to generate a CAPTCHA","无法生成验证码"}.
|
||||
{"Unable to register route on existing local domain","无法在现有本地域上注册路由"}.
|
||||
{"Unauthorized","未经授权"}.
|
||||
{"Unexpected action","意外的操作"}.
|
||||
{"Unexpected action","意外操作"}.
|
||||
{"Unexpected error condition: ~p","意外错误条件:~p"}.
|
||||
{"Uninstall","卸载"}.
|
||||
{"Unregister an XMPP account","注销 XMPP 账号"}.
|
||||
@@ -557,14 +560,14 @@
|
||||
{"Update Specs","更新规格"}.
|
||||
{"Updating the vCard is not supported by the vCard storage backend","vCard 存储后端不支持更新 vCard"}.
|
||||
{"Upgrade","升级"}.
|
||||
{"URL for Archived Discussion Logs","存档讨论日志的 URL"}.
|
||||
{"URL for Archived Discussion Logs","已归档的讨论日志 URL"}.
|
||||
{"User already exists","用户已存在"}.
|
||||
{"User (jid)","用户 (jid)"}.
|
||||
{"User JID","用户 JID"}.
|
||||
{"User (jid)","用户(JID)"}.
|
||||
{"User Management","用户管理"}.
|
||||
{"User not allowed to perform an IQ set on another user's vCard.","不允许用户在其他用户的 vCard 上执行 IQ 设置。"}.
|
||||
{"User removed","用户已移除"}.
|
||||
{"User session not found","用户会话未找到"}.
|
||||
{"User session not found","未找到用户会话"}.
|
||||
{"User session terminated","用户会话已终止"}.
|
||||
{"User ~ts","用户 ~ts"}.
|
||||
{"Username:","用户名:"}.
|
||||
@@ -580,11 +583,12 @@
|
||||
{"vCard User Search","vCard 用户搜索"}.
|
||||
{"View joined MIX channels","查看已加入的 MIX 频道"}.
|
||||
{"Virtual Hosts","虚拟主机"}.
|
||||
{"Visitors are not allowed to change their nicknames in this room","不允许访客在此群聊中更改其昵称"}.
|
||||
{"Visitors are not allowed to send messages to all occupants","不允许访客向所有参与者发送消息"}.
|
||||
{"Visitor","访客"}.
|
||||
{"Voice requests are disabled in this conference","此群聊中禁用发言请求"}.
|
||||
{"Voice request","发言请求"}.
|
||||
{"Visitors are not allowed to change their nicknames in this room","不允许参观者在此房间中更改其昵称"}.
|
||||
{"Visitors are not allowed to send messages to all occupants","不允许参观者向所有使用者发送消息"}.
|
||||
{"Visitor","参观者"}.
|
||||
{"Voice requests are disabled in this conference","此会议中禁用了发言权请求"}.
|
||||
{"Voice request","发言权请求"}.
|
||||
{"Web client which allows to join the room anonymously","允许匿名加入房间的 Web 客户端"}.
|
||||
{"Wednesday","周三"}.
|
||||
{"When a new subscription is processed and whenever a subscriber comes online","处理新订阅时和订阅者上线时"}.
|
||||
{"When a new subscription is processed","处理新订阅时"}.
|
||||
@@ -599,7 +603,7 @@
|
||||
{"Whether to notify owners about new subscribers and unsubscribes","是否通知所有者新的订阅者和退订者"}.
|
||||
{"Who can send private messages","谁可以发送私信"}.
|
||||
{"Who may associate leaf nodes with a collection","谁可以将叶节点与集合关联"}.
|
||||
{"Wrong parameters in the web formulary","web 公式中的参数错误"}.
|
||||
{"Wrong parameters in the web formulary","Web 表单集中的参数错误"}.
|
||||
{"Wrong xmlns","错误的 xmlns"}.
|
||||
{"XMPP Account Registration","XMPP 账号注册"}.
|
||||
{"XMPP Domains","XMPP 域"}.
|
||||
@@ -608,19 +612,19 @@
|
||||
{"XMPP Show Value of DND (Do Not Disturb)","XMPP 的 DND(请勿打扰)显示值"}.
|
||||
{"XMPP Show Value of XA (Extended Away)","XMPP 的 XA(延长离开)显示值"}.
|
||||
{"XMPP URI of Associated Publish-Subscribe Node","关联发布–订阅节点的 XMPP URI"}.
|
||||
{"You are being removed from the room because of a system shutdown","由于系统关闭,您将会从群聊中移除"}.
|
||||
{"You are being removed from the room because of a system shutdown","由于系统关闭,您将被移出房间"}.
|
||||
{"You are not allowed to send private messages","不允许您发送私信"}.
|
||||
{"You are not joined to the channel","您未加入频道"}.
|
||||
{"You can later change your password using an XMPP client.","您之后可以使用 XMPP 客户端更改密码。"}.
|
||||
{"You have been banned from this room","禁止您进入此群聊"}.
|
||||
{"You have joined too many conferences","您加入了太多群聊"}.
|
||||
{"You have been banned from this room","禁止您进入此房间"}.
|
||||
{"You have joined too many conferences","您加入了太多会议"}.
|
||||
{"You must fill in field \"Nickname\" in the form","您必须在表单中填写“昵称”字段"}.
|
||||
{"You need a client that supports x:data and CAPTCHA to register","您需要支持 x:data 和验证码的客户端来注册"}.
|
||||
{"You need a client that supports x:data to register the nickname","您需要支持 x:data 的客户端来注册昵称"}.
|
||||
{"You need an x:data capable client to search","您需要支持 x:data 的客户端来搜索"}.
|
||||
{"Your active privacy list has denied the routing of this stanza.","您的活动隐私列表已拒绝路由此节。"}.
|
||||
{"Your contact offline message queue is full. The message has been discarded.","您的联系人离线消息队列已满。消息已被丢弃。"}.
|
||||
{"Your subscription request and/or messages to ~s have been blocked. To unblock your subscription request, visit ~s","您对 ~s 的订阅请求和/或消息已被屏蔽。若要解除屏蔽您的订阅请求,请访问 ~s"}.
|
||||
{"Your subscription request and/or messages to ~s have been blocked. To unblock your subscription request, visit ~s","您发给 ~s 的订阅请求和/或消息已被屏蔽。若要取消屏蔽您的订阅请求,请访问 ~s"}.
|
||||
{"Your XMPP account was successfully registered.","您的 XMPP 账号注册成功。"}.
|
||||
{"Your XMPP account was successfully unregistered.","您的 XMPP 账号注销成功。"}.
|
||||
{"You're not allowed to create nodes","不允许您创建节点"}.
|
||||
|
||||
+20
-20
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -26,8 +26,8 @@
|
||||
{if_version_below, "24",
|
||||
{base64url, "~> 1.0", {git, "https://github.com/dvv/base64url", {tag, "1.0.1"}}}
|
||||
}},
|
||||
{cache_tab, "~> 1.0.30", {git, "https://github.com/processone/cache_tab", {tag, "1.0.31"}}},
|
||||
{eimp, "~> 1.0.22", {git, "https://github.com/processone/eimp", {tag, "1.0.23"}}},
|
||||
{cache_tab, "~> 1.0.31", {git, "https://github.com/processone/cache_tab", {tag, "1.0.31"}}},
|
||||
{eimp, "~> 1.0.24", {git, "https://github.com/processone/eimp", {tag, "1.0.24"}}},
|
||||
{if_var_true, pam,
|
||||
{epam, "~> 1.0.14", {git, "https://github.com/processone/epam", {tag, "1.0.14"}}}},
|
||||
{if_var_true, redis,
|
||||
@@ -41,12 +41,12 @@
|
||||
{eredis, "~> 1.7.1", {git, "https://github.com/Nordix/eredis/", {tag, "v1.7.1"}}}
|
||||
}}},
|
||||
{if_var_true, sip,
|
||||
{esip, "~> 1.0.52", {git, "https://github.com/processone/esip", {tag, "1.0.56"}}}},
|
||||
{esip, "~> 1.0.57", {git, "https://github.com/processone/esip", {tag, "1.0.57"}}}},
|
||||
{if_var_true, zlib,
|
||||
{ezlib, "~> 1.0.12", {git, "https://github.com/processone/ezlib", {tag, "1.0.13"}}}},
|
||||
{fast_tls, "~> 1.1.19", {git, "https://github.com/processone/fast_tls", {tag, "1.1.22"}}},
|
||||
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.55"}}},
|
||||
{fast_yaml, "~> 1.0.36", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.37"}}},
|
||||
{ezlib, "~> 1.0.13", {git, "https://github.com/processone/ezlib", {tag, "1.0.13"}}}},
|
||||
{fast_tls, "~> 1.1.22", {git, "https://github.com/processone/fast_tls", {tag, "1.1.22"}}},
|
||||
{fast_xml, "~> 1.1.55", {git, "https://github.com/processone/fast_xml", {tag, "1.1.55"}}},
|
||||
{fast_yaml, "~> 1.0.37", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.37"}}},
|
||||
{idna, "~> 6.0", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
|
||||
{if_version_below, "27",
|
||||
{jiffy, "~> 1.1.1", {git, "https://github.com/davisp/jiffy", {tag, "1.1.1"}}}
|
||||
@@ -63,22 +63,22 @@
|
||||
{luerl, "1.0.0", {git, "https://github.com/rvirding/luerl", {tag, "1.0"}}},
|
||||
{luerl, "~> 1.2.0", {git, "https://github.com/rvirding/luerl", {tag, "1.2"}}}
|
||||
}},
|
||||
{mqtree, "~> 1.0.16", {git, "https://github.com/processone/mqtree", {tag, "1.0.17"}}},
|
||||
{p1_acme, "~> 1.0.23", {git, "https://github.com/processone/p1_acme", {tag, "1.0.25"}}},
|
||||
{mqtree, "~> 1.0.17", {git, "https://github.com/processone/mqtree", {tag, "1.0.17"}}},
|
||||
{p1_acme, "~> 1.0.25", {git, "https://github.com/processone/p1_acme", {tag, "1.0.25"}}},
|
||||
{if_var_true, mysql,
|
||||
{p1_mysql, "~> 1.0.24", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.25"}}}},
|
||||
{p1_mysql, "~> 1.0.26", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.26"}}}},
|
||||
{p1_oauth2, "~> 0.6.14", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.14"}}},
|
||||
{if_var_true, pgsql,
|
||||
{p1_pgsql, "~> 1.1.26", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.29"}}}},
|
||||
{p1_utils, "~> 1.0.25", {git, "https://github.com/processone/p1_utils", {tag, "1.0.26"}}},
|
||||
{p1_pgsql, "~> 1.1.32", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.32"}}}},
|
||||
{p1_utils, "~> 1.0.27", {git, "https://github.com/processone/p1_utils", {tag, "1.0.27"}}},
|
||||
{pkix, "~> 1.0.10", {git, "https://github.com/processone/pkix", {tag, "1.0.10"}}},
|
||||
{if_var_true, sqlite,
|
||||
{sqlite3, "~> 1.1.14", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.15"}}}},
|
||||
{stringprep, "~> 1.0.29", {git, "https://github.com/processone/stringprep", {tag, "1.0.30"}}},
|
||||
{sqlite3, "~> 1.1.15", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.15"}}}},
|
||||
{stringprep, "~> 1.0.31", {git, "https://github.com/processone/stringprep", {tag, "1.0.31"}}},
|
||||
{if_var_true, stun,
|
||||
{stun, "~> 1.2.12", {git, "https://github.com/processone/stun", {tag, "1.2.15"}}}},
|
||||
{xmpp, "~> 1.9.1", {git, "https://github.com/processone/xmpp", {tag, "1.9.1"}}},
|
||||
{yconf, "~> 1.0.17", {git, "https://github.com/processone/yconf", {tag, "1.0.17"}}}
|
||||
{stun, "~> 1.2.17", {git, "https://github.com/processone/stun", {tag, "1.2.17"}}}},
|
||||
{xmpp, "~> 1.10.0", {git, "https://github.com/processone/xmpp", {tag, "1.10.0"}}},
|
||||
{yconf, "~> 1.0.18", {git, "https://github.com/processone/yconf", {tag, "1.0.18"}}}
|
||||
]}.
|
||||
|
||||
{gitonly_deps, [ejabberd_po]}.
|
||||
@@ -140,6 +140,7 @@
|
||||
{if_version_below, "25", {d, 'OTP_BELOW_25'}},
|
||||
{if_version_below, "26", {d, 'OTP_BELOW_26'}},
|
||||
{if_version_below, "27", {d, 'OTP_BELOW_27'}},
|
||||
{if_version_below, "28", {d, 'OTP_BELOW_28'}},
|
||||
{if_var_false, debug, no_debug_info},
|
||||
{if_var_true, debug, debug_info},
|
||||
{if_var_true, elixir, {d, 'ELIXIR_ENABLED'}},
|
||||
@@ -147,14 +148,13 @@
|
||||
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATEWAY_WORKAROUND'}},
|
||||
{if_var_true, sip, {d, 'SIP'}},
|
||||
{if_var_true, stun, {d, 'STUN'}},
|
||||
{if_type_exported, {odbc, {opaque, connection_reference, 0}}, {d, 'ODBC_HAS_TYPES'}},
|
||||
{src_dirs, [src,
|
||||
{if_rebar3, sql},
|
||||
{if_var_true, tools, tools}]}]}.
|
||||
|
||||
{if_rebar3, {plugins, [{if_version_below, "21", {rebar3_hex, "7.0.7"}},
|
||||
{if_version_above, "20", {rebar3_hex, "~> 7.0.8"}},
|
||||
{provider_asn1, "0.2.0"},
|
||||
{provider_asn1, "0.4.1"},
|
||||
%% Protocol consolidation doesn't work correctly in upstream rebar_mix, see
|
||||
%% https://github.com/Supersonido/rebar_mix/issues/27#issuecomment-894873335
|
||||
%% Let's use this fixed rebar_mix fork, see its PR:
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+27
-27
@@ -1,10 +1,10 @@
|
||||
{"1.2.0",
|
||||
[{<<"base64url">>,{pkg,<<"base64url">>,<<"1.0.1">>},1},
|
||||
{<<"cache_tab">>,{pkg,<<"cache_tab">>,<<"1.0.31">>},0},
|
||||
{<<"eimp">>,{pkg,<<"eimp">>,<<"1.0.23">>},0},
|
||||
{<<"eimp">>,{pkg,<<"eimp">>,<<"1.0.24">>},0},
|
||||
{<<"epam">>,{pkg,<<"epam">>,<<"1.0.14">>},0},
|
||||
{<<"eredis">>,{pkg,<<"eredis">>,<<"1.7.1">>},0},
|
||||
{<<"esip">>,{pkg,<<"esip">>,<<"1.0.56">>},0},
|
||||
{<<"esip">>,{pkg,<<"esip">>,<<"1.0.57">>},0},
|
||||
{<<"ezlib">>,{pkg,<<"ezlib">>,<<"1.0.13">>},0},
|
||||
{<<"fast_tls">>,{pkg,<<"fast_tls">>,<<"1.1.22">>},0},
|
||||
{<<"fast_xml">>,{pkg,<<"fast_xml">>,<<"1.1.55">>},0},
|
||||
@@ -15,25 +15,25 @@
|
||||
{<<"luerl">>,{pkg,<<"luerl">>,<<"1.2.3">>},0},
|
||||
{<<"mqtree">>,{pkg,<<"mqtree">>,<<"1.0.17">>},0},
|
||||
{<<"p1_acme">>,{pkg,<<"p1_acme">>,<<"1.0.25">>},0},
|
||||
{<<"p1_mysql">>,{pkg,<<"p1_mysql">>,<<"1.0.25">>},0},
|
||||
{<<"p1_mysql">>,{pkg,<<"p1_mysql">>,<<"1.0.26">>},0},
|
||||
{<<"p1_oauth2">>,{pkg,<<"p1_oauth2">>,<<"0.6.14">>},0},
|
||||
{<<"p1_pgsql">>,{pkg,<<"p1_pgsql">>,<<"1.1.29">>},0},
|
||||
{<<"p1_utils">>,{pkg,<<"p1_utils">>,<<"1.0.26">>},0},
|
||||
{<<"p1_pgsql">>,{pkg,<<"p1_pgsql">>,<<"1.1.32">>},0},
|
||||
{<<"p1_utils">>,{pkg,<<"p1_utils">>,<<"1.0.27">>},0},
|
||||
{<<"pkix">>,{pkg,<<"pkix">>,<<"1.0.10">>},0},
|
||||
{<<"sqlite3">>,{pkg,<<"sqlite3">>,<<"1.1.15">>},0},
|
||||
{<<"stringprep">>,{pkg,<<"stringprep">>,<<"1.0.30">>},0},
|
||||
{<<"stun">>,{pkg,<<"stun">>,<<"1.2.15">>},0},
|
||||
{<<"stringprep">>,{pkg,<<"stringprep">>,<<"1.0.31">>},0},
|
||||
{<<"stun">>,{pkg,<<"stun">>,<<"1.2.17">>},0},
|
||||
{<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},1},
|
||||
{<<"xmpp">>,{pkg,<<"xmpp">>,<<"1.9.1">>},0},
|
||||
{<<"yconf">>,{pkg,<<"yconf">>,<<"1.0.17">>},0}]}.
|
||||
{<<"xmpp">>,{pkg,<<"xmpp">>,<<"1.10.0">>},0},
|
||||
{<<"yconf">>,{pkg,<<"yconf">>,<<"1.0.18">>},0}]}.
|
||||
[
|
||||
{pkg_hash,[
|
||||
{<<"base64url">>, <<"F8C7F2DA04CA9A5D0F5F50258F055E1D699F0E8BF4CFDB30B750865368403CF6">>},
|
||||
{<<"cache_tab">>, <<"E4097B50A6F373AB1E0A5F01BAB0BEF6626771A4CD6C93404ED6D54810E11FBC">>},
|
||||
{<<"eimp">>, <<"AAF32EFAB061143403DADBAA63E699EF8E81702FBFA96FD436D5E9BE4D6A8D3A">>},
|
||||
{<<"eimp">>, <<"853DB317BA394D479D2F1181E0B0135A3CD3C2C7EB48FF6CFB035A28DD354B14">>},
|
||||
{<<"epam">>, <<"AA0B85D27F4EF3A756AE995179DF952A0721237E83C6B79D644347B75016681A">>},
|
||||
{<<"eredis">>, <<"39E31AA02ADCD651C657F39AAFD4D31A9B2F63C6C700DC9CECE98D4BC3C897AB">>},
|
||||
{<<"esip">>, <<"63C0FDC667BE751714E1E5C14621A9334F21B60AC1BB68BE889454CA9CA021B7">>},
|
||||
{<<"esip">>, <<"4B14E4832D08B9FFC10D855B5D10B3083232B1D53DEB4C046679496CE85569C4">>},
|
||||
{<<"ezlib">>, <<"3C7F62862850A241159C10B218ECF580BCE54D0890601B65144DACC2633BE2B0">>},
|
||||
{<<"fast_tls">>, <<"44356B256AFAD4399C2FC5059A3066669DAFD8BD4E4E796C9C1CF8910DDD265E">>},
|
||||
{<<"fast_xml">>, <<"ACE020F2521F2A484AC8467D2822AF85534A346E2AAE03FFCBC34F29318BEFAF">>},
|
||||
@@ -44,24 +44,24 @@
|
||||
{<<"luerl">>, <<"DF25F41944E57A7C4D9EF09D238BC3E850276C46039CFC12B8BB42ECCF36FCB1">>},
|
||||
{<<"mqtree">>, <<"82F54B8F2D22B4445DB1D6CCCB7FE9EAD049D61410C29E32475F3CEB3EE62A89">>},
|
||||
{<<"p1_acme">>, <<"DB91F0D6C193CD1D5C0B0FA3939A898DBF56A6075DB4347CDE26E802715DE50C">>},
|
||||
{<<"p1_mysql">>, <<"875D4CBDC7C9990270DF3292CCE2514E4C18A9FDFD19BEF258CB4D0C45B4F243">>},
|
||||
{<<"p1_mysql">>, <<"574D07C9936C53B1EC3556DB3CF064CC14A6C39039835B3D940471BFA5AC8E2B">>},
|
||||
{<<"p1_oauth2">>, <<"1C5F82535574DE87E2059695AC4B91F8F9AEBACBC1C80287DAE6F02552D47AEA">>},
|
||||
{<<"p1_pgsql">>, <<"FAE0C90CBC5931865958150F1B667FB0D20B063F6A46A17770A4E5232DED632C">>},
|
||||
{<<"p1_utils">>, <<"67B0C4AC9FA3BA3EF563B31AA111B0A004439A37FAC85E027F1C3617E1C7EC6C">>},
|
||||
{<<"p1_pgsql">>, <<"3F95D7E3413FC8F0BE80ABB4BE1A0D7F67066A36905085CD5A423145598B0CB0">>},
|
||||
{<<"p1_utils">>, <<"F468D84C6FFA6E4B12A6160826DCF2D015527189D57865568A78B49C5ED972A1">>},
|
||||
{<<"pkix">>, <<"D3BFADF7B7CFE2A3636F1B256C9CCE5F646A07CE31E57EE527668502850765A0">>},
|
||||
{<<"sqlite3">>, <<"E819DEFD280145C328457D7AF897D2E45E8E5270E18812EE30B607C99CDD21AF">>},
|
||||
{<<"stringprep">>, <<"46CF0FF631B3E7328F61F20B454D59428D87738F25D709798B5DCBB9B83C23F1">>},
|
||||
{<<"stun">>, <<"EEC510AF6509201FF97F1F2C87B7977C833BF29C04E985383370EC21F04E4CCF">>},
|
||||
{<<"stringprep">>, <<"FA1688C156DD271722AA18C423A4163E710D2F4F475AD0BC220910DF669B53AF">>},
|
||||
{<<"stun">>, <<"C54614A592812EA125A2E6827AAC5A438571B591616426EC1419BA9B48252F54">>},
|
||||
{<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>},
|
||||
{<<"xmpp">>, <<"A1642D93CDBDF947F32344B0E05FCC8EFCFB9F11C32832ACC9BD826B52ADBE48">>},
|
||||
{<<"yconf">>, <<"DCF242E27F3FC5D0743D6B8175DD39BC14A1F4ED7E6EA986366A44A6FF3B2A3A">>}]},
|
||||
{<<"xmpp">>, <<"68A6DFF8DB8987C4592B2D5DD71D3F947B4EBD15209C9ACACA5909A642670630">>},
|
||||
{<<"yconf">>, <<"E565EDC8AABB8164C3BEBC86969095D296AD315DCBB46AF65DCCBC6C71EAE0F6">>}]},
|
||||
{pkg_hash_ext,[
|
||||
{<<"base64url">>, <<"F9B3ADD4731A02A9B0410398B475B33E7566A695365237A6BDEE1BB447719F5C">>},
|
||||
{<<"cache_tab">>, <<"8582B60A4A09B247EF86355BA9E07FCE9E11EDC0345A775C9171F971C72B6351">>},
|
||||
{<<"eimp">>, <<"907C780023CB2893E4FC4BDBE6A4F02C355913862AC67F0ECC26605E816B628A">>},
|
||||
{<<"eimp">>, <<"7D61432EB8A45659C0BE475F44E75EEB651743AA64A1DE8ADF785CDAD81961AD">>},
|
||||
{<<"epam">>, <<"2F3449E72885A72A6C2A843F561ADD0FC2F70D7A21F61456930A547473D4D989">>},
|
||||
{<<"eredis">>, <<"7C2B54C566FED55FEEF3341CA79B0100A6348FD3F162184B7ED5118D258C3CC1">>},
|
||||
{<<"esip">>, <<"9EF3660CEF93B623F7368DCD5C79F4E704358631909E6DD464E335378815DA1F">>},
|
||||
{<<"esip">>, <<"19C357E1817B1E04792EF359BF900400F3E6D0E5ADE929FD72F88EA9B44AF2ED">>},
|
||||
{<<"ezlib">>, <<"9EE62AB3F8ED55A0FD11A9569FCB8E458683F95575417272192B069F092ABFBB">>},
|
||||
{<<"fast_tls">>, <<"E65779AEFB7AB15C4755230FEF8077E687D20CC5A3984A5974F9F657E8E2485B">>},
|
||||
{<<"fast_xml">>, <<"83F3E23A780ED5F567CDEC73953F06C95B838D709DBFA86B59A98A8D23C99F85">>},
|
||||
@@ -72,15 +72,15 @@
|
||||
{<<"luerl">>, <<"1B4B9D0CA5D7D280D1D2787A6A5EE9F5A212641B62BFF91556BAA53805DF3AED">>},
|
||||
{<<"mqtree">>, <<"5FE8B7CF8FBC4783D0FCEB94654AC2BBF3242A58CD0397D249DED8AE021BE2A3">>},
|
||||
{<<"p1_acme">>, <<"A7B55B47495DDB4F98A15E65451EC3AD43F4637B955C74CD695D98E6A645D08C">>},
|
||||
{<<"p1_mysql">>, <<"E6187FFAE95B726098E88F3EE6F2344AC259CE2C26E0EE403B05FEEF341AE434">>},
|
||||
{<<"p1_mysql">>, <<"EA138083F2C54719B9CF549DBF5802A288B0019EA3E5449B354C74CC03FAFDEC">>},
|
||||
{<<"p1_oauth2">>, <<"1FD3AC474E43722D9D5A87C6DF8D36F698ED87AF7BB81CBBB66361451D99AE8F">>},
|
||||
{<<"p1_pgsql">>, <<"A6FF58E8B174993F3895DA3EA6211A9F9D0C54D1A6E28BB321DA3B3CD68B38C1">>},
|
||||
{<<"p1_utils">>, <<"D0379E8C1156B98BD64F8129C1DE022FCCA4F2FDB7486CE73BF0ED2C3376B04C">>},
|
||||
{<<"p1_pgsql">>, <<"268B01E8F4EB75C211A31495A25C2815C549AECCE2F0DF1A161C6E0A2CDE061E">>},
|
||||
{<<"p1_utils">>, <<"F1AF942B0A62BCFA0D59FBE30679BE4FFEB5E241A0C49ED5F094DB2F5B80F5E0">>},
|
||||
{<<"pkix">>, <<"E02164F83094CB124C41B1AB28988A615D54B9ADC38575F00F19A597A3AC5D0E">>},
|
||||
{<<"sqlite3">>, <<"3C0BA4E13322C2AD49DE4E2DDD28311366ADDE54BEAE8DBA9D9E3888F69D2857">>},
|
||||
{<<"stringprep">>, <<"F6FC9B3384A03877830F89B2F38580CAF3F4A27448A4A333D6A8C3975C220B9A">>},
|
||||
{<<"stun">>, <<"F6D8A541A29FD13F2CE658B676C0CC661262B96E045B52DEF1644B75EBC0EDEF">>},
|
||||
{<<"stringprep">>, <<"E9699C88E8DB16B3A41F0E45AC6874A4DA81A6E4854A77D76EDE6D09B08E3530">>},
|
||||
{<<"stun">>, <<"6B318244C21E8524A9AAE3AC9A05CD8234EE994C1C2C815DE68D306086AD768D">>},
|
||||
{<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>},
|
||||
{<<"xmpp">>, <<"D2B1431AF6E4C1A4C8BF90CAF0CC11CDEB047B8323B87E9D7E4826D4913275DC">>},
|
||||
{<<"yconf">>, <<"DD2892923241449A46CC8457B9EC0FB14030700735A5885955677C735C341A25">>}]}
|
||||
{<<"xmpp">>, <<"CEEAE43B8FE97649D8F8546B3F7F2B38ECFC931C0CDD5C7445FFB3F80FCB7D85">>},
|
||||
{<<"yconf">>, <<"FA950EC6503F92D6417FB8CC1D982403F041697E8E1BBF4D4588FB919B9562EA">>}]}
|
||||
].
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeniy Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% @copyright (C) 2013-2024, Evgeniy Khramtsov
|
||||
%%% @copyright (C) 2013-2025, Evgeniy Khramtsov
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
@@ -38,11 +38,12 @@ Vars = case file:consult(filename:join([TopDir, "vars.config"])) of
|
||||
|
||||
RequiredOTPApps = [sasl, crypto, public_key, ssl,
|
||||
mnesia, inets, compiler, asn1,
|
||||
observer, tools,
|
||||
syntax_tools, os_mon, xmerl],
|
||||
|
||||
ConfiguredOTPApps = lists:flatmap(
|
||||
fun({tools, true}) ->
|
||||
[tools, runtime_tools];
|
||||
[runtime_tools];
|
||||
({odbc, true}) ->
|
||||
[odbc];
|
||||
(_) ->
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
-- ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
@@ -18,13 +18,14 @@
|
||||
|
||||
CREATE TABLE users (
|
||||
username text NOT NULL,
|
||||
type smallint,
|
||||
server_host text NOT NULL,
|
||||
password text NOT NULL,
|
||||
serverkey text NOT NULL DEFAULT '',
|
||||
salt text NOT NULL DEFAULT '',
|
||||
iterationcount integer NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (server_host, username)
|
||||
PRIMARY KEY (server_host, username, type)
|
||||
);
|
||||
|
||||
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
-- ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
@@ -17,12 +17,14 @@
|
||||
--
|
||||
|
||||
CREATE TABLE users (
|
||||
username text PRIMARY KEY,
|
||||
username text,
|
||||
type smallint,
|
||||
password text NOT NULL,
|
||||
serverkey text NOT NULL DEFAULT '',
|
||||
salt text NOT NULL DEFAULT '',
|
||||
iterationcount integer NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
primary key (username, type)
|
||||
);
|
||||
|
||||
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
-- ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
@@ -403,6 +403,7 @@ WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW
|
||||
CREATE TABLE [dbo].[users] (
|
||||
[username] [varchar] (250) NOT NULL,
|
||||
[server_host] [varchar] (250) NOT NULL,
|
||||
[type] [smallint] NOT NULL,
|
||||
[password] [text] NOT NULL,
|
||||
[serverkey] [text] NOT NULL DEFAULT '',
|
||||
[salt] [text] NOT NULL DEFAULT '',
|
||||
@@ -411,7 +412,8 @@ CREATE TABLE [dbo].[users] (
|
||||
CONSTRAINT [users_PRIMARY] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[server_host] ASC,
|
||||
[username] ASC
|
||||
[username] ASC,
|
||||
[type] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
|
||||
) TEXTIMAGE_ON [PRIMARY];
|
||||
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
-- ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
@@ -379,6 +379,7 @@ WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW
|
||||
|
||||
CREATE TABLE [dbo].[users] (
|
||||
[username] [varchar] (250) NOT NULL,
|
||||
[type] [smallint] NOT NULL,
|
||||
[password] [text] NOT NULL,
|
||||
[serverkey] [text] NOT NULL DEFAULT '',
|
||||
[salt] [text] NOT NULL DEFAULT '',
|
||||
@@ -386,7 +387,8 @@ CREATE TABLE [dbo].[users] (
|
||||
[created_at] [datetime] NOT NULL DEFAULT GETDATE(),
|
||||
CONSTRAINT [users_PRIMARY] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[username] ASC
|
||||
[username] ASC,
|
||||
[type] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
|
||||
) TEXTIMAGE_ON [PRIMARY];
|
||||
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
-- ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
@@ -18,13 +18,14 @@
|
||||
|
||||
CREATE TABLE users (
|
||||
username varchar(191) NOT NULL,
|
||||
type smallint NOT NULL,
|
||||
server_host varchar(191) NOT NULL,
|
||||
password text NOT NULL,
|
||||
serverkey varchar(128) NOT NULL DEFAULT '',
|
||||
salt varchar(128) NOT NULL DEFAULT '',
|
||||
iterationcount integer NOT NULL DEFAULT 0,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (server_host(191), username)
|
||||
PRIMARY KEY (server_host(191), username, type)
|
||||
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- Add support for SCRAM auth to a database created before ejabberd 16.03:
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
-- ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
@@ -17,12 +17,14 @@
|
||||
--
|
||||
|
||||
CREATE TABLE users (
|
||||
username varchar(191) PRIMARY KEY,
|
||||
username varchar(191) NOT NULL,
|
||||
type smallint NOT NULL,,
|
||||
password text NOT NULL,
|
||||
serverkey varchar(128) NOT NULL DEFAULT '',
|
||||
salt varchar(128) NOT NULL DEFAULT '',
|
||||
iterationcount integer NOT NULL DEFAULT 0,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (username, type)
|
||||
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- Add support for SCRAM auth to a database created before ejabberd 16.03:
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
-- ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
@@ -172,12 +172,13 @@
|
||||
CREATE TABLE users (
|
||||
username text NOT NULL,
|
||||
server_host text NOT NULL,
|
||||
"type" smallint NOT NULL,
|
||||
"password" text NOT NULL,
|
||||
serverkey text NOT NULL DEFAULT '',
|
||||
salt text NOT NULL DEFAULT '',
|
||||
iterationcount integer NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (server_host, username)
|
||||
PRIMARY KEY (server_host, username, "type")
|
||||
);
|
||||
|
||||
-- Add support for SCRAM auth to a database created before ejabberd 16.03:
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
-- ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
@@ -17,12 +17,14 @@
|
||||
--
|
||||
|
||||
CREATE TABLE users (
|
||||
username text PRIMARY KEY,
|
||||
username text NOT NULL,
|
||||
"type" smallint NOT NULL
|
||||
"password" text NOT NULL,
|
||||
serverkey text NOT NULL DEFAULT '',
|
||||
salt text NOT NULL DEFAULT '',
|
||||
iterationcount integer NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (username, "type")
|
||||
);
|
||||
|
||||
-- Add support for SCRAM auth to a database created before ejabberd 16.03:
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -106,8 +106,8 @@ match_acl(_Host, {shared_group, {G, H}}, #{usr := {U, S, _}}) ->
|
||||
undefined -> false;
|
||||
Mod -> Mod:is_user_in_group({U, S}, G, H)
|
||||
end;
|
||||
match_acl(Host, {shared_group, G}, Map) ->
|
||||
match_acl(Host, {shared_group, {G, Host}}, Map);
|
||||
match_acl(Host, {shared_group, G}, #{usr := {_, S, _}} = Map) ->
|
||||
match_acl(Host, {shared_group, {G, S}}, Map);
|
||||
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, _}}) ->
|
||||
|
||||
+3
-6
@@ -3,7 +3,7 @@
|
||||
%%% Purpose : Validator for ejabberd configuration options
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -546,13 +546,10 @@ sip_uri() ->
|
||||
-spec host() -> yconf:validator(binary()).
|
||||
host() ->
|
||||
fun(Domain) ->
|
||||
Host = ejabberd_config:get_myname(),
|
||||
Hosts = ejabberd_config:get_option(hosts),
|
||||
Domain1 = (binary())(Domain),
|
||||
Domain2 = misc:expand_keyword(<<"@HOST@">>, Domain1, Host),
|
||||
Domain3 = (domain())(Domain2),
|
||||
Domain3 = (domain())(Domain),
|
||||
case lists:member(Domain3, Hosts) of
|
||||
true -> fail({route_conflict, Domain3});
|
||||
true -> fail({route_conflict, Domain});
|
||||
false -> Domain3
|
||||
end
|
||||
end.
|
||||
|
||||
+2
-3
@@ -5,7 +5,7 @@
|
||||
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -40,9 +40,8 @@
|
||||
-protocol({xep, 368, '1.1.0', '17.09', "complete", ""}).
|
||||
-protocol({xep, 386, '0.3.0', '24.02', "complete", ""}).
|
||||
-protocol({xep, 388, '0.4.0', '24.02', "complete", ""}).
|
||||
-protocol({xep, 424, '0.4.0', '24.02', "complete", ""}).
|
||||
-protocol({xep, 440, '0.4.0', '24.02', "complete", ""}).
|
||||
-protocol({xep, 474, '0.3.0', '24.02', "complete", ""}).
|
||||
-protocol({xep, 474, '0.4.0', '24.02', "complete", "0.4.0 since 25.03"}).
|
||||
-protocol({xep, 485, '0.2.0', '24.02', "complete", "mod_pubsub_serverinfo in ejabberd-contrib.git"}).
|
||||
|
||||
-export([start/0, stop/0, halt/0, start_app/1, start_app/2,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 7 Sep 2016 by Paweł Chmielowski <pawel@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -344,10 +344,20 @@ validator(from) ->
|
||||
fun(L) when is_list(L) ->
|
||||
lists:map(
|
||||
fun({K, V}) -> {(econf:enum([tag]))(K), (econf:binary())(V)};
|
||||
(A) -> (econf:enum([ejabberd_xmlrpc, mod_cron, mod_http_api, ejabberd_ctl, ejabberd_web_admin]))(A)
|
||||
(A) -> (econf:enum([ejabberd_ctl,
|
||||
ejabberd_web_admin,
|
||||
ejabberd_xmlrpc,
|
||||
mod_adhoc_api,
|
||||
mod_cron,
|
||||
mod_http_api]))(A)
|
||||
end, lists:flatten(L));
|
||||
(A) ->
|
||||
[(econf:enum([ejabberd_xmlrpc, mod_cron, mod_http_api, ejabberd_ctl, ejabberd_web_admin]))(A)]
|
||||
[(econf:enum([ejabberd_ctl,
|
||||
ejabberd_web_admin,
|
||||
ejabberd_xmlrpc,
|
||||
mod_adhoc_api,
|
||||
mod_cron,
|
||||
mod_http_api]))(A)]
|
||||
end;
|
||||
validator(what) ->
|
||||
econf:and_then(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+30
-11
@@ -5,7 +5,7 @@
|
||||
%%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -598,8 +598,9 @@ get_commands_spec() ->
|
||||
args = [{node, atom}, {table, binary}, {page, integer}],
|
||||
result = {res, any}},
|
||||
|
||||
#ejabberd_commands{name = mnesia_list_tables, tags = [internal, mnesia],
|
||||
#ejabberd_commands{name = mnesia_list_tables, tags = [mnesia],
|
||||
desc = "List of Mnesia tables",
|
||||
note = "added in 25.03",
|
||||
module = ?MODULE, function = mnesia_list_tables,
|
||||
result = {tables, {list, {table, {tuple, [{name, atom},
|
||||
{storage_type, binary},
|
||||
@@ -615,8 +616,10 @@ get_commands_spec() ->
|
||||
{value, binary}
|
||||
]}}}}},
|
||||
|
||||
#ejabberd_commands{name = mnesia_table_change_storage, tags = [internal, mnesia],
|
||||
desc = "Change storage type of a Mnesia table to: ram_copies, disc_copies, or disc_only_copies.",
|
||||
#ejabberd_commands{name = mnesia_table_change_storage, tags = [mnesia],
|
||||
desc = "Change storage type of a Mnesia table",
|
||||
note = "added in 25.03",
|
||||
longdesc = "Storage type can be: `ram_copies`, `disc_copies`, `disc_only_copies`, `remote_copy`.",
|
||||
module = ?MODULE, function = mnesia_table_change_storage,
|
||||
args = [{table, binary}, {storage_type, binary}],
|
||||
result = {res, restuple}},
|
||||
@@ -663,7 +666,7 @@ status() ->
|
||||
{value, {_, _, Version}} ->
|
||||
{ok, io_lib:format("ejabberd ~s is running in that node", [Version])}
|
||||
end,
|
||||
{Is_running, String1 ++ " " ++String2}.
|
||||
{Is_running, String1 ++ "\n" ++String2}.
|
||||
|
||||
stop() ->
|
||||
_ = supervisor:terminate_child(ejabberd_sup, ejabberd_sm),
|
||||
@@ -931,14 +934,14 @@ get_cluster_node_details(Node, RunningNodes) ->
|
||||
get_cluster_node_details2(Node, lists:member(Node, RunningNodes)).
|
||||
|
||||
get_cluster_node_details2(Node, false) ->
|
||||
{Node, "false", "", -1, -1, -1, "unknown"};
|
||||
{Node, "false", "", -1, -1, -1, unknown};
|
||||
get_cluster_node_details2(Node, true) ->
|
||||
try ejabberd_cluster:call(Node, ejabberd_admin, get_cluster_node_details3, []) of
|
||||
Result -> Result
|
||||
catch
|
||||
E:R ->
|
||||
Status = io_lib:format("~p: ~p", [E, R]),
|
||||
{Node, "true", Status, -1, -1, -1, "unknown"}
|
||||
{Node, "true", Status, -1, -1, -1, unknown}
|
||||
end.
|
||||
|
||||
get_cluster_node_details3() ->
|
||||
@@ -1281,13 +1284,12 @@ is_my_host(Host) ->
|
||||
|
||||
%% @format-begin
|
||||
|
||||
%% mnesia:del_table_copy(Table, Node);
|
||||
%% mnesia:change_table_copy_type(Table, Node, Type);
|
||||
|
||||
mnesia_table_change_storage(STable, SType) ->
|
||||
Table = binary_to_existing_atom(STable, latin1),
|
||||
Type =
|
||||
case SType of
|
||||
<<"remote_copy">> ->
|
||||
remote_copy;
|
||||
<<"ram_copies">> ->
|
||||
ram_copies;
|
||||
<<"disc_copies">> ->
|
||||
@@ -1297,7 +1299,24 @@ mnesia_table_change_storage(STable, SType) ->
|
||||
_ ->
|
||||
false
|
||||
end,
|
||||
mnesia:add_table_copy(Table, node(), Type).
|
||||
Node = node(),
|
||||
Result =
|
||||
case Type of
|
||||
false ->
|
||||
"Nothing to do";
|
||||
remote_copy ->
|
||||
mnesia:del_table_copy(Table, Node),
|
||||
"Deleted table copy";
|
||||
_ ->
|
||||
case mnesia:add_table_copy(Table, Node, Type) of
|
||||
{aborted, _} ->
|
||||
mnesia:change_table_copy_type(Table, Node, Type),
|
||||
"Changed table copy type";
|
||||
_ ->
|
||||
"Added table copy"
|
||||
end
|
||||
end,
|
||||
{ok, Result}.
|
||||
|
||||
mnesia_table_clear(STable) ->
|
||||
Table = binary_to_existing_atom(STable, latin1),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+229
-89
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -48,7 +48,7 @@
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
-export([auth_modules/1, convert_to_scram/1]).
|
||||
-export([auth_modules/1, convert_to_scram/1, drop_password_type/2, set_password_instance/3]).
|
||||
|
||||
-include_lib("xmpp/include/scram.hrl").
|
||||
-include("logger.hrl").
|
||||
@@ -76,26 +76,38 @@
|
||||
-callback store_type(binary()) -> plain | external | scram.
|
||||
-callback set_password(binary(), binary(), password()) ->
|
||||
{ets_cache:tag(), {ok, password()} | {error, db_failure | not_allowed}}.
|
||||
-callback set_password_multiple(binary(), binary(), [password()]) ->
|
||||
{ets_cache:tag(), {ok, [password()]} | {error, db_failure | not_allowed}}.
|
||||
-callback set_password_instance(binary(), binary(), password()) ->
|
||||
ok | {error, db_failure | not_allowed}.
|
||||
-callback remove_user(binary(), binary()) -> ok | {error, db_failure | not_allowed}.
|
||||
-callback user_exists(binary(), binary()) -> {ets_cache:tag(), boolean() | {error, db_failure}}.
|
||||
-callback check_password(binary(), binary(), binary(), binary()) -> {ets_cache:tag(), boolean() | {stop, boolean()}}.
|
||||
-callback try_register(binary(), binary(), password()) ->
|
||||
{ets_cache:tag(), {ok, password()} | {error, exists | db_failure | not_allowed}}.
|
||||
-callback try_register_multiple(binary(), binary(), [password()]) ->
|
||||
{ets_cache:tag(), {ok, [password()]} | {error, exists | db_failure | not_allowed}}.
|
||||
-callback get_users(binary(), opts()) -> [{binary(), binary()}].
|
||||
-callback count_users(binary(), opts()) -> number().
|
||||
-callback get_password(binary(), binary()) -> {ets_cache:tag(), {ok, password()} | error}.
|
||||
-callback get_password(binary(), binary()) -> {ets_cache:tag(), {ok, password() | [password()]} | error}.
|
||||
-callback drop_password_type(binary(), atom()) ->
|
||||
ok | {error, db_failure | not_allowed}.
|
||||
-callback use_cache(binary()) -> boolean().
|
||||
-callback cache_nodes(binary()) -> boolean().
|
||||
|
||||
-optional_callbacks([reload/1,
|
||||
set_password/3,
|
||||
set_password_multiple/3,
|
||||
set_password_instance/3,
|
||||
remove_user/2,
|
||||
user_exists/2,
|
||||
check_password/4,
|
||||
try_register/3,
|
||||
try_register_multiple/3,
|
||||
get_users/2,
|
||||
count_users/2,
|
||||
get_password/2,
|
||||
drop_password_type/2,
|
||||
use_cache/1,
|
||||
cache_nodes/1]).
|
||||
|
||||
@@ -265,15 +277,41 @@ check_password_with_authmodule(User, AuthzId, Server, Password, Digest, DigestGe
|
||||
false
|
||||
end.
|
||||
|
||||
convert_password_for_storage(_Server, #scram{} = Password) ->
|
||||
{Password, [Password]};
|
||||
convert_password_for_storage(Server, Password) ->
|
||||
P = case ejabberd_option:auth_stored_password_types(Server) of
|
||||
[] ->
|
||||
case ejabberd_option:auth_password_format(Server) of
|
||||
plain ->
|
||||
[Password];
|
||||
_ ->
|
||||
[password_to_scram(Server, Password)]
|
||||
end;
|
||||
M ->
|
||||
lists:sort(lists:map(
|
||||
fun(scram_sha1) ->
|
||||
password_to_scram(Server, Password, sha, ?SCRAM_DEFAULT_ITERATION_COUNT);
|
||||
(scram_sha256) ->
|
||||
password_to_scram(Server, Password, sha256, ?SCRAM_DEFAULT_ITERATION_COUNT);
|
||||
(scram_sha512) ->
|
||||
password_to_scram(Server, Password, sha512, ?SCRAM_DEFAULT_ITERATION_COUNT);
|
||||
(plain) ->
|
||||
Password
|
||||
end, M))
|
||||
end,
|
||||
{Password, P}.
|
||||
|
||||
-spec set_password(binary(), binary(), password()) -> ok | {error,
|
||||
db_failure | not_allowed |
|
||||
invalid_jid | invalid_password}.
|
||||
set_password(User, Server, Password) ->
|
||||
case validate_credentials(User, Server, Password) of
|
||||
{ok, LUser, LServer} ->
|
||||
{Plain, Passwords} = convert_password_for_storage(Server, Password),
|
||||
lists:foldl(
|
||||
fun(M, {error, _}) ->
|
||||
db_set_password(LUser, LServer, Password, M);
|
||||
db_set_password(LUser, LServer, Plain, Passwords, M);
|
||||
(_, ok) ->
|
||||
ok
|
||||
end, {error, not_allowed}, auth_modules(LServer));
|
||||
@@ -281,6 +319,32 @@ set_password(User, Server, Password) ->
|
||||
Err
|
||||
end.
|
||||
|
||||
set_password_instance(User, Server, Password) ->
|
||||
case validate_credentials(User, Server, Password) of
|
||||
{ok, LUser, LServer} ->
|
||||
lists:foldl(
|
||||
fun(Mod, {error, _} = Acc) ->
|
||||
case erlang:function_exported(Mod, set_password_instance, 3) of
|
||||
true ->
|
||||
R = Mod:set_password_instance(LUser, LServer, Password),
|
||||
case use_cache(Mod, LServer) of
|
||||
true ->
|
||||
ets_cache:delete(cache_tab(Mod), {LUser, LServer},
|
||||
cache_nodes(Mod, LServer));
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
R;
|
||||
_ ->
|
||||
Acc
|
||||
end;
|
||||
(_, ok) ->
|
||||
ok
|
||||
end, {error, not_allowed}, auth_modules(LServer));
|
||||
Err ->
|
||||
Err
|
||||
end.
|
||||
|
||||
-spec try_register(binary(), binary(), password()) -> ok | {error,
|
||||
db_failure | not_allowed | exists |
|
||||
invalid_jid | invalid_password}.
|
||||
@@ -293,22 +357,23 @@ try_register(User, Server, Password) ->
|
||||
false ->
|
||||
case ejabberd_router:is_my_host(LServer) of
|
||||
true ->
|
||||
case ejabberd_hooks:run_fold(check_register_user, LServer, true, [User, Server, Password]) of
|
||||
case ejabberd_hooks:run_fold(check_register_user, LServer, true,
|
||||
[User, Server, Password]) of
|
||||
true ->
|
||||
case lists:foldl(
|
||||
fun(_, ok) ->
|
||||
ok;
|
||||
(Mod, _) ->
|
||||
db_try_register(
|
||||
LUser, LServer, Password, Mod)
|
||||
end, {error, not_allowed},
|
||||
auth_modules(LServer)) of
|
||||
ok ->
|
||||
ejabberd_hooks:run(
|
||||
register_user, LServer, [LUser, LServer]);
|
||||
{error, _} = Err ->
|
||||
Err
|
||||
end;
|
||||
{Plain, Passwords} = convert_password_for_storage(Server, Password),
|
||||
case lists:foldl(
|
||||
fun(_, ok) ->
|
||||
ok;
|
||||
(Mod, _) ->
|
||||
db_try_register(
|
||||
LUser, LServer, Plain, Passwords, Mod)
|
||||
end, {error, not_allowed}, auth_modules(LServer)) of
|
||||
ok ->
|
||||
ejabberd_hooks:run(
|
||||
register_user, LServer, [LUser, LServer]);
|
||||
{error, _} = Err ->
|
||||
Err
|
||||
end;
|
||||
false ->
|
||||
{error, not_allowed}
|
||||
end;
|
||||
@@ -356,32 +421,27 @@ count_users(Server, Opts) ->
|
||||
auth_modules(LServer)))
|
||||
end.
|
||||
|
||||
-spec get_password(binary(), binary()) -> false | password().
|
||||
-spec get_password(binary(), binary()) -> false | [password()].
|
||||
get_password(User, Server) ->
|
||||
case validate_credentials(User, Server) of
|
||||
{ok, LUser, LServer} ->
|
||||
case lists:foldl(
|
||||
fun(M, error) -> db_get_password(LUser, LServer, M);
|
||||
(_M, Acc) -> Acc
|
||||
end, error, auth_modules(LServer)) of
|
||||
{ok, Password} ->
|
||||
Password;
|
||||
error ->
|
||||
false
|
||||
end;
|
||||
_ ->
|
||||
false
|
||||
case get_password_with_authmodule(User, Server) of
|
||||
{Passwords, _} -> Passwords
|
||||
end.
|
||||
|
||||
-spec get_password_s(binary(), binary()) -> password().
|
||||
get_password_s(User, Server) ->
|
||||
case get_password(User, Server) of
|
||||
false -> <<"">>;
|
||||
Password -> Password
|
||||
Passwords ->
|
||||
{_, Pass} = lists:foldl(
|
||||
fun(Plain, _) when is_binary(Plain) -> {true, Plain};
|
||||
(Pass, {false, _}) -> {true, Pass};
|
||||
(_, Acc) -> Acc
|
||||
end, {false, <<"">>}, Passwords),
|
||||
Pass
|
||||
end.
|
||||
|
||||
-spec get_password_with_authmodule(binary(), binary()) ->
|
||||
{false | {false, atom(), binary()} | password(), module()}.
|
||||
{false | {false, atom(), binary()} | [password()], module()}.
|
||||
get_password_with_authmodule(User, Server) ->
|
||||
case validate_credentials(User, Server) of
|
||||
{ok, LUser, LServer} ->
|
||||
@@ -395,8 +455,10 @@ get_password_with_authmodule(User, Server) ->
|
||||
(_M, Acc) ->
|
||||
Acc
|
||||
end, {error, undefined}, auth_modules(LServer)) of
|
||||
{{ok, Password}, Module} ->
|
||||
{{ok, Password}, Module} when is_list(Password) ->
|
||||
{Password, Module};
|
||||
{{ok, Password}, Module} ->
|
||||
{[Password], Module};
|
||||
{error, Module} ->
|
||||
{false, Module}
|
||||
end
|
||||
@@ -455,6 +517,30 @@ user_exists_in_other_modules_loop([AuthModule | AuthModules], User, Server) ->
|
||||
maybe_exists
|
||||
end.
|
||||
|
||||
drop_password_type(LServer, Type) ->
|
||||
Hash = case Type of
|
||||
plain -> plain;
|
||||
scram_sha1 -> sha;
|
||||
scram_sha256 -> sha256;
|
||||
scram_sha512 -> sha512
|
||||
end,
|
||||
lists:foreach(
|
||||
fun(M) ->
|
||||
case erlang:function_exported(M, drop_password_type, 2) of
|
||||
true ->
|
||||
M:drop_password_type(LServer, Hash),
|
||||
case use_cache(M, LServer) of
|
||||
true ->
|
||||
ets_cache:clear(cache_tab(M),
|
||||
cache_nodes(M, LServer));
|
||||
false ->
|
||||
ok
|
||||
end;
|
||||
_ ->
|
||||
ok
|
||||
end
|
||||
end, auth_modules(LServer)).
|
||||
|
||||
-spec which_users_exists(list({binary(), binary()})) -> list({binary(), binary()}).
|
||||
which_users_exists(USPairs) ->
|
||||
ByServer = lists:foldl(
|
||||
@@ -592,54 +678,86 @@ get_is_banned(User, Server) ->
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Backend calls
|
||||
%%%----------------------------------------------------------------------
|
||||
-spec db_try_register(binary(), binary(), password(), module()) -> ok | {error, exists | db_failure | not_allowed}.
|
||||
db_try_register(User, Server, Password, Mod) ->
|
||||
case erlang:function_exported(Mod, try_register, 3) of
|
||||
-spec db_try_register(binary(), binary(), binary(), [password()], module()) -> ok | {error, exists | db_failure | not_allowed}.
|
||||
db_try_register(User, Server, PlainPassword, Passwords, Mod) ->
|
||||
Ret = case erlang:function_exported(Mod, try_register_multiple, 3) of
|
||||
true ->
|
||||
Password1 = case Mod:store_type(Server) of
|
||||
scram -> password_to_scram(Server, Password);
|
||||
_ -> Password
|
||||
end,
|
||||
Ret = case use_cache(Mod, Server) of
|
||||
true ->
|
||||
ets_cache:update(
|
||||
cache_tab(Mod), {User, Server}, {ok, Password},
|
||||
fun() -> Mod:try_register(User, Server, Password1) end,
|
||||
cache_nodes(Mod, Server));
|
||||
false ->
|
||||
ets_cache:untag(Mod:try_register(User, Server, Password1))
|
||||
end,
|
||||
case Ret of
|
||||
{ok, _} -> ok;
|
||||
{error, _} = Err -> Err
|
||||
case use_cache(Mod, Server) of
|
||||
true ->
|
||||
ets_cache:update(
|
||||
cache_tab(Mod), {User, Server}, {ok, Passwords},
|
||||
fun() -> Mod:try_register_multiple(User, Server, Passwords) end,
|
||||
cache_nodes(Mod, Server));
|
||||
false ->
|
||||
ets_cache:untag(Mod:try_register_multiple(User, Server, Passwords))
|
||||
end;
|
||||
false ->
|
||||
{error, not_allowed}
|
||||
_ ->
|
||||
case erlang:function_exported(Mod, try_register, 3) of
|
||||
true ->
|
||||
case use_cache(Mod, Server) of
|
||||
true ->
|
||||
ets_cache:update(
|
||||
cache_tab(Mod), {User, Server}, {ok, [PlainPassword]},
|
||||
fun() ->
|
||||
case Mod:try_register(User, Server, PlainPassword) of
|
||||
{Tag, {ok, Pass}} -> {Tag, {ok, [Pass]}};
|
||||
Other -> Other
|
||||
end
|
||||
end, cache_nodes(Mod, Server));
|
||||
false ->
|
||||
case Mod:try_register(User, Server, PlainPassword) of
|
||||
{_, {ok, Pass}} -> {ok, [Pass]};
|
||||
V -> ets_cache:untag(V)
|
||||
end
|
||||
end;
|
||||
false ->
|
||||
{error, not_allowed}
|
||||
end
|
||||
end,
|
||||
case Ret of
|
||||
{ok, _} -> ok;
|
||||
{error, _} = Err -> Err
|
||||
end.
|
||||
|
||||
-spec db_set_password(binary(), binary(), password(), module()) -> ok | {error, db_failure | not_allowed}.
|
||||
db_set_password(User, Server, Password, Mod) ->
|
||||
case erlang:function_exported(Mod, set_password, 3) of
|
||||
true ->
|
||||
Password1 = case Mod:store_type(Server) of
|
||||
scram -> password_to_scram(Server, Password);
|
||||
_ -> Password
|
||||
end,
|
||||
Ret = case use_cache(Mod, Server) of
|
||||
-spec db_set_password(binary(), binary(), binary(), [password()], module()) -> ok | {error, db_failure | not_allowed}.
|
||||
db_set_password(User, Server, PlainPassword, Passwords, Mod) ->
|
||||
Ret = case erlang:function_exported(Mod, set_password_multiple, 3) of
|
||||
true ->
|
||||
case use_cache(Mod, Server) of
|
||||
true ->
|
||||
ets_cache:update(
|
||||
cache_tab(Mod), {User, Server}, {ok, Password},
|
||||
fun() -> Mod:set_password(User, Server, Password1) end,
|
||||
cache_nodes(Mod, Server));
|
||||
cache_tab(Mod), {User, Server}, {ok, Passwords},
|
||||
fun() -> Mod:set_password_multiple(User, Server, Passwords) end,
|
||||
cache_nodes(Mod, Server));
|
||||
false ->
|
||||
ets_cache:untag(Mod:set_password(User, Server, Password1))
|
||||
end,
|
||||
case Ret of
|
||||
{ok, _} -> ok;
|
||||
{error, _} = Err -> Err
|
||||
end;
|
||||
false ->
|
||||
{error, not_allowed}
|
||||
ets_cache:untag(Mod:set_password_multiple(User, Server, Passwords))
|
||||
end;
|
||||
_ ->
|
||||
case erlang:function_exported(Mod, set_password, 3) of
|
||||
true ->
|
||||
case use_cache(Mod, Server) of
|
||||
true ->
|
||||
ets_cache:update(
|
||||
cache_tab(Mod), {User, Server}, {ok, [PlainPassword]},
|
||||
fun() ->
|
||||
case Mod:set_password(User, Server, PlainPassword) of
|
||||
{Tag, {ok, Pass}} -> {Tag, {ok, [Pass]}};
|
||||
Other -> Other
|
||||
end
|
||||
end, cache_nodes(Mod, Server));
|
||||
false ->
|
||||
case Mod:set_password(User, Server, PlainPassword) of
|
||||
{_, {ok, Pass}} -> {ok, [Pass]};
|
||||
V -> ets_cache:untag(V)
|
||||
end
|
||||
end;
|
||||
false ->
|
||||
{error, not_allowed}
|
||||
end
|
||||
end,
|
||||
case Ret of
|
||||
{ok, _} -> ok;
|
||||
{error, _} = Err -> Err
|
||||
end.
|
||||
|
||||
db_get_password(User, Server, Mod) ->
|
||||
@@ -649,16 +767,28 @@ db_get_password(User, Server, Mod) ->
|
||||
case ets_cache:lookup(cache_tab(Mod), {User, Server}) of
|
||||
{ok, exists} -> error;
|
||||
not_found -> error;
|
||||
{ok, List} = V when is_list(List) -> V;
|
||||
{ok, Single} -> {ok, [Single]};
|
||||
Other -> Other
|
||||
end;
|
||||
false ->
|
||||
error;
|
||||
true when UseCache ->
|
||||
ets_cache:lookup(
|
||||
cache_tab(Mod), {User, Server},
|
||||
fun() -> Mod:get_password(User, Server) end);
|
||||
cache_tab(Mod), {User, Server},
|
||||
fun() ->
|
||||
case Mod:get_password(User, Server) of
|
||||
{_, {ok, List}} = V when is_list(List) -> V;
|
||||
{Tag, {ok, Single}} -> {Tag, {ok, [Single]}};
|
||||
Other -> Other
|
||||
end
|
||||
end);
|
||||
true ->
|
||||
ets_cache:untag(Mod:get_password(User, Server))
|
||||
case Mod:get_password(User, Server) of
|
||||
{_, {ok, List}} when is_list(List) -> {ok, List};
|
||||
{_, {ok, Single}} -> {ok, [Single]};
|
||||
Other -> ets_cache:untag(Other)
|
||||
end
|
||||
end.
|
||||
|
||||
db_user_exists(User, Server, Mod) ->
|
||||
@@ -703,8 +833,8 @@ db_user_exists(User, Server, Mod) ->
|
||||
db_check_password(User, AuthzId, Server, ProvidedPassword,
|
||||
Digest, DigestFun, Mod) ->
|
||||
case db_get_password(User, Server, Mod) of
|
||||
{ok, ValidPassword} ->
|
||||
match_passwords(ProvidedPassword, ValidPassword, Digest, DigestFun);
|
||||
{ok, ValidPasswords} ->
|
||||
match_passwords(ProvidedPassword, ValidPasswords, Digest, DigestFun);
|
||||
error ->
|
||||
case {Mod:store_type(Server), use_cache(Mod, Server)} of
|
||||
{external, true} ->
|
||||
@@ -809,7 +939,9 @@ password_to_scram(Host, Password) ->
|
||||
password_to_scram(_Host, #scram{} = Password, _IterationCount) ->
|
||||
Password;
|
||||
password_to_scram(Host, Password, IterationCount) ->
|
||||
Hash = ejabberd_option:auth_scram_hash(Host),
|
||||
password_to_scram(Host, Password, ejabberd_option:auth_scram_hash(Host), IterationCount).
|
||||
|
||||
password_to_scram(_Host, Password, Hash, IterationCount) ->
|
||||
Salt = p1_rand:bytes(?SALT_LENGTH),
|
||||
SaltedPassword = scram:salted_password(Hash, Password, Salt, IterationCount),
|
||||
StoredKey = scram:stored_key(Hash, scram:client_key(Hash, SaltedPassword)),
|
||||
@@ -897,11 +1029,19 @@ auth_modules(Server) ->
|
||||
misc:atom_to_binary(M)])
|
||||
|| M <- Methods].
|
||||
|
||||
-spec match_passwords(password(), password(),
|
||||
-spec match_passwords(password(), [password()],
|
||||
binary(), digest_fun() | undefined) -> boolean().
|
||||
match_passwords(Password, #scram{} = Scram, <<"">>, undefined) ->
|
||||
match_passwords(Provided, Passwords, Digest, DigestFun) ->
|
||||
lists:any(
|
||||
fun(Pass) ->
|
||||
match_password(Provided, Pass, Digest, DigestFun)
|
||||
end, Passwords).
|
||||
|
||||
-spec match_password(password(), password(),
|
||||
binary(), digest_fun() | undefined) -> boolean().
|
||||
match_password(Password, #scram{} = Scram, <<"">>, undefined) ->
|
||||
is_password_scram_valid(Password, Scram);
|
||||
match_passwords(Password, #scram{} = Scram, Digest, DigestFun) ->
|
||||
match_password(Password, #scram{} = Scram, Digest, DigestFun) ->
|
||||
StoredKey = base64:decode(Scram#scram.storedkey),
|
||||
DigRes = if Digest /= <<"">> ->
|
||||
Digest == DigestFun(StoredKey);
|
||||
@@ -912,9 +1052,9 @@ match_passwords(Password, #scram{} = Scram, Digest, DigestFun) ->
|
||||
true ->
|
||||
StoredKey == Password andalso Password /= <<"">>
|
||||
end;
|
||||
match_passwords(ProvidedPassword, ValidPassword, <<"">>, undefined) ->
|
||||
match_password(ProvidedPassword, ValidPassword, <<"">>, undefined) ->
|
||||
ProvidedPassword == ValidPassword andalso ProvidedPassword /= <<"">>;
|
||||
match_passwords(ProvidedPassword, ValidPassword, Digest, DigestFun) ->
|
||||
match_password(ProvidedPassword, ValidPassword, Digest, DigestFun) ->
|
||||
DigRes = if Digest /= <<"">> ->
|
||||
Digest == DigestFun(ValidPassword);
|
||||
true -> false
|
||||
@@ -983,7 +1123,7 @@ convert_to_scram(Server) ->
|
||||
lists:foreach(
|
||||
fun({U, S}) ->
|
||||
case get_password(U, S) of
|
||||
Pass when is_binary(Pass) ->
|
||||
[Pass] when is_binary(Pass) ->
|
||||
SPass = password_to_scram(Server, Pass),
|
||||
set_password(U, S, SPass);
|
||||
_ ->
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 17 Feb 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 16 Mar 2019 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+104
-88
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -29,11 +29,11 @@
|
||||
|
||||
-behaviour(ejabberd_auth).
|
||||
|
||||
-export([start/1, stop/1, set_password/3, try_register/3,
|
||||
-export([start/1, stop/1, set_password_multiple/3, try_register_multiple/3,
|
||||
get_users/2, init_db/0,
|
||||
count_users/2, get_password/2,
|
||||
remove_user/2, store_type/1, import/2,
|
||||
plain_password_required/1, use_cache/1]).
|
||||
plain_password_required/1, use_cache/1, drop_password_type/2, set_password_instance/3]).
|
||||
-export([need_transform/1, transform/1]).
|
||||
|
||||
-include("logger.hrl").
|
||||
@@ -86,30 +86,58 @@ plain_password_required(Server) ->
|
||||
store_type(Server) ->
|
||||
ejabberd_auth:password_format(Server).
|
||||
|
||||
set_password(User, Server, Password) ->
|
||||
US = {User, Server},
|
||||
F = fun () ->
|
||||
mnesia:write(#passwd{us = US, password = Password})
|
||||
set_password_multiple(User, Server, Passwords) ->
|
||||
F = fun() ->
|
||||
lists:foreach(
|
||||
fun(#scram{hash = Hash} = Password) ->
|
||||
mnesia:write(#passwd{us = {User, Server, Hash}, password = Password});
|
||||
(Plain) ->
|
||||
mnesia:write(#passwd{us = {User, Server, plain}, password = Plain})
|
||||
end, Passwords)
|
||||
end,
|
||||
case mnesia:transaction(F) of
|
||||
{atomic, ok} ->
|
||||
{cache, {ok, Password}};
|
||||
{cache, {ok, Passwords}};
|
||||
{aborted, Reason} ->
|
||||
?ERROR_MSG("Mnesia transaction failed: ~p", [Reason]),
|
||||
{nocache, {error, db_failure}}
|
||||
end.
|
||||
|
||||
try_register(User, Server, Password) ->
|
||||
US = {User, Server},
|
||||
F = fun () ->
|
||||
case mnesia:read({passwd, US}) of
|
||||
[] ->
|
||||
mnesia:write(#passwd{us = US, password = Password}),
|
||||
mnesia:dirty_update_counter(reg_users_counter, Server, 1),
|
||||
{ok, Password};
|
||||
[_] ->
|
||||
{error, exists}
|
||||
end
|
||||
set_password_instance(User, Server, Password) ->
|
||||
F = fun() ->
|
||||
case Password of
|
||||
#scram{hash = Hash} = Password ->
|
||||
mnesia:write(#passwd{us = {User, Server, Hash}, password = Password});
|
||||
Plain ->
|
||||
mnesia:write(#passwd{us = {User, Server, plain}, password = Plain})
|
||||
end
|
||||
end,
|
||||
case mnesia:transaction(F) of
|
||||
{atomic, ok} ->
|
||||
ok;
|
||||
{aborted, Reason} ->
|
||||
?ERROR_MSG("Mnesia transaction failed: ~p", [Reason]),
|
||||
{error, db_failure}
|
||||
end.
|
||||
|
||||
try_register_multiple(User, Server, Passwords) ->
|
||||
F = fun() ->
|
||||
case mnesia:select(passwd, [{{'_', {'$1', '$2', '_'}, '$3'},
|
||||
[{'==', '$1', User},
|
||||
{'==', '$2', Server}],
|
||||
['$3']}]) of
|
||||
[] ->
|
||||
lists:foreach(
|
||||
fun(#scram{hash = Hash} = Password) ->
|
||||
mnesia:write(#passwd{us = {User, Server, Hash}, password = Password});
|
||||
(Plain) ->
|
||||
mnesia:write(#passwd{us = {User, Server, plain}, password = Plain})
|
||||
end, Passwords),
|
||||
mnesia:dirty_update_counter(reg_users_counter, Server, 1),
|
||||
{ok, Passwords};
|
||||
[_] ->
|
||||
{error, exists}
|
||||
end
|
||||
end,
|
||||
case mnesia:transaction(F) of
|
||||
{atomic, Res} ->
|
||||
@@ -120,9 +148,16 @@ try_register(User, Server, Password) ->
|
||||
end.
|
||||
|
||||
get_users(Server, []) ->
|
||||
mnesia:dirty_select(passwd,
|
||||
Users = mnesia:dirty_select(passwd,
|
||||
[{#passwd{us = '$1', _ = '_'},
|
||||
[{'==', {element, 2, '$1'}, Server}], ['$1']}]);
|
||||
[{'==', {element, 2, '$1'}, Server}], ['$1']}]),
|
||||
{_, Res} = lists:foldl(
|
||||
fun({U, S, _}, {{U2, S2}, _} = Acc) when U == U2 andalso S == S2 ->
|
||||
Acc;
|
||||
({U, S, _}, {_, Res}) ->
|
||||
{{U, S}, [{U, S} | Res]}
|
||||
end, {{none, none}, []}, Users),
|
||||
Res;
|
||||
get_users(Server, [{from, Start}, {to, End}])
|
||||
when is_integer(Start) and is_integer(End) ->
|
||||
get_users(Server, [{limit, End - Start + 1}, {offset, Start}]);
|
||||
@@ -179,22 +214,48 @@ count_users(Server, _) ->
|
||||
count_users(Server, []).
|
||||
|
||||
get_password(User, Server) ->
|
||||
case mnesia:dirty_read(passwd, {User, Server}) of
|
||||
[{passwd, _, {scram, SK, SEK, Salt, IC}}] ->
|
||||
{cache, {ok, #scram{storedkey = SK, serverkey = SEK,
|
||||
salt = Salt, hash = sha, iterationcount = IC}}};
|
||||
[#passwd{password = Password}] ->
|
||||
{cache, {ok, Password}};
|
||||
case mnesia:dirty_select(passwd, [{{'_', {'$1', '$2', '_'}, '$3'},
|
||||
[{'==', '$1', User},
|
||||
{'==', '$2', Server}],
|
||||
['$3']}]) of
|
||||
[_|_] = List ->
|
||||
List2 = lists:map(
|
||||
fun({scram, SK, SEK, Salt, IC}) ->
|
||||
#scram{storedkey = SK, serverkey = SEK,
|
||||
salt = Salt, hash = sha, iterationcount = IC};
|
||||
(Other) -> Other
|
||||
end, List),
|
||||
{cache, {ok, List2}};
|
||||
_ ->
|
||||
{cache, error}
|
||||
end.
|
||||
|
||||
drop_password_type(Server, Hash) ->
|
||||
F = fun() ->
|
||||
Keys = mnesia:select(passwd, [{{'_', '$1', '_'},
|
||||
[{'==', {element, 3, '$1'}, Hash},
|
||||
{'==', {element, 2, '$1'}, Server}],
|
||||
['$1']}]),
|
||||
lists:foreach(fun(Key) -> mnesia:delete({passwd, Key}) end, Keys),
|
||||
ok
|
||||
end,
|
||||
case mnesia:transaction(F) of
|
||||
{atomic, ok} ->
|
||||
ok;
|
||||
{aborted, Reason} ->
|
||||
?ERROR_MSG("Mnesia transaction failed: ~p", [Reason]),
|
||||
{error, db_failure}
|
||||
end.
|
||||
|
||||
remove_user(User, Server) ->
|
||||
US = {User, Server},
|
||||
F = fun () ->
|
||||
mnesia:delete({passwd, US}),
|
||||
mnesia:dirty_update_counter(reg_users_counter, Server, -1),
|
||||
ok
|
||||
Keys = mnesia:select(passwd, [{{'_', '$1', '_'},
|
||||
[{'==', {element, 1, '$1'}, User},
|
||||
{'==', {element, 2, '$1'}, Server}],
|
||||
['$1']}]),
|
||||
lists:foreach(fun(Key) -> mnesia:delete({passwd, Key}) end, Keys),
|
||||
mnesia:dirty_update_counter(reg_users_counter, Server, -1),
|
||||
ok
|
||||
end,
|
||||
case mnesia:transaction(F) of
|
||||
{atomic, ok} ->
|
||||
@@ -206,45 +267,10 @@ remove_user(User, Server) ->
|
||||
|
||||
need_transform(#reg_users_counter{}) ->
|
||||
false;
|
||||
need_transform({passwd, {U, S}, Pass}) ->
|
||||
case Pass of
|
||||
_ when is_binary(Pass) ->
|
||||
case store_type(S) of
|
||||
scram ->
|
||||
?INFO_MSG("Passwords in Mnesia table 'passwd' "
|
||||
"will be SCRAM'ed", []),
|
||||
true;
|
||||
plain ->
|
||||
false
|
||||
end;
|
||||
{scram, _, _, _, _} ->
|
||||
case store_type(S) of
|
||||
scram ->
|
||||
false;
|
||||
plain ->
|
||||
?WARNING_MSG("Some passwords were stored in the database "
|
||||
"as SCRAM, but 'auth_password_format' "
|
||||
"is not configured as 'scram': some "
|
||||
"authentication mechanisms such as DIGEST-MD5 "
|
||||
"would *fail*", []),
|
||||
false
|
||||
end;
|
||||
#scram{} ->
|
||||
case store_type(S) of
|
||||
scram ->
|
||||
false;
|
||||
plain ->
|
||||
?WARNING_MSG("Some passwords were stored in the database "
|
||||
"as SCRAM, but 'auth_password_format' "
|
||||
"is not configured as 'scram': some "
|
||||
"authentication mechanisms such as DIGEST-MD5 "
|
||||
"would *fail*", []),
|
||||
false
|
||||
end;
|
||||
_ when is_list(U) orelse is_list(S) orelse is_list(Pass) ->
|
||||
?INFO_MSG("Mnesia table 'passwd' will be converted to binary", []),
|
||||
true
|
||||
end.
|
||||
need_transform({passwd, {_U, _S, _T}, _Pass}) ->
|
||||
false;
|
||||
need_transform({passwd, {_U, _S}, _Pass}) ->
|
||||
true.
|
||||
|
||||
transform({passwd, {U, S}, Pass})
|
||||
when is_list(U) orelse is_list(S) orelse is_list(Pass) ->
|
||||
@@ -263,24 +289,14 @@ transform({passwd, {U, S}, Pass})
|
||||
transform(#passwd{us = NewUS, password = NewPass});
|
||||
transform(#passwd{us = {U, S}, password = Password} = P)
|
||||
when is_binary(Password) ->
|
||||
case store_type(S) of
|
||||
scram ->
|
||||
case jid:resourceprep(Password) of
|
||||
error ->
|
||||
?ERROR_MSG("SASLprep failed for password of user ~ts@~ts",
|
||||
[U, S]),
|
||||
P;
|
||||
_ ->
|
||||
Scram = ejabberd_auth:password_to_scram(S, Password),
|
||||
P#passwd{password = Scram}
|
||||
end;
|
||||
plain ->
|
||||
P
|
||||
end;
|
||||
transform({passwd, _, {scram, _, _, _, _}} = P) ->
|
||||
P;
|
||||
transform(#passwd{password = #scram{}} = P) ->
|
||||
P.
|
||||
P#passwd{us = {U, S, plain}, password = Password};
|
||||
transform({passwd, {U, S}, {scram, SK, SEK, Salt, IC}}) ->
|
||||
#passwd{us = {U, S, sha},
|
||||
password = #scram{storedkey = SK, serverkey = SEK,
|
||||
salt = Salt, hash = sha, iterationcount = IC}};
|
||||
transform(#passwd{us = {U, S}, password = #scram{hash = Hash}} = P) ->
|
||||
P#passwd{us = {U, S, Hash}};
|
||||
transform(Other) -> Other.
|
||||
|
||||
import(LServer, [LUser, Password, _TimeStamp]) ->
|
||||
mnesia:dirty_write(
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 5 Jul 2007 by Evgeniy Khramtsov <xram@jabber.ru>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+166
-74
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -30,10 +30,10 @@
|
||||
|
||||
-behaviour(ejabberd_auth).
|
||||
|
||||
-export([start/1, stop/1, set_password/3, try_register/3,
|
||||
-export([start/1, stop/1, set_password_multiple/3, try_register_multiple/3,
|
||||
get_users/2, count_users/2, get_password/2,
|
||||
remove_user/2, store_type/1, plain_password_required/1,
|
||||
export/1, which_users_exists/2]).
|
||||
export/1, which_users_exists/2, drop_password_type/2, set_password_instance/3]).
|
||||
-export([sql_schemas/0]).
|
||||
|
||||
-include_lib("xmpp/include/scram.hrl").
|
||||
@@ -49,7 +49,34 @@ start(Host) ->
|
||||
ok.
|
||||
|
||||
sql_schemas() ->
|
||||
[#sql_schema{
|
||||
[
|
||||
#sql_schema{
|
||||
version = 2,
|
||||
tables =
|
||||
[#sql_table{
|
||||
name = <<"users">>,
|
||||
columns =
|
||||
[#sql_column{name = <<"username">>, type = text},
|
||||
#sql_column{name = <<"server_host">>, type = text},
|
||||
#sql_column{name = <<"type">>, type = smallint},
|
||||
#sql_column{name = <<"password">>, type = text},
|
||||
#sql_column{name = <<"serverkey">>, type = {text, 128},
|
||||
default = true},
|
||||
#sql_column{name = <<"salt">>, type = {text, 128},
|
||||
default = true},
|
||||
#sql_column{name = <<"iterationcount">>, type = integer,
|
||||
default = true},
|
||||
#sql_column{name = <<"created_at">>, type = timestamp,
|
||||
default = true}],
|
||||
indices = [#sql_index{
|
||||
columns = [<<"server_host">>, <<"username">>, <<"type">>],
|
||||
unique = true}]}],
|
||||
update = [
|
||||
{add_column, <<"users">>, <<"type">>},
|
||||
{update_primary_key,<<"users">>,
|
||||
[<<"server_host">>, <<"username">>, <<"type">>]}
|
||||
]},
|
||||
#sql_schema{
|
||||
version = 1,
|
||||
tables =
|
||||
[#sql_table{
|
||||
@@ -78,42 +105,87 @@ plain_password_required(Server) ->
|
||||
store_type(Server) ->
|
||||
ejabberd_auth:password_format(Server).
|
||||
|
||||
set_password(User, Server, Password) ->
|
||||
hash_to_num(plain) -> 1;
|
||||
hash_to_num(sha) -> 2;
|
||||
hash_to_num(sha256) -> 3;
|
||||
hash_to_num(sha512) -> 4.
|
||||
|
||||
num_to_hash(2) -> sha;
|
||||
num_to_hash(3) -> sha256;
|
||||
num_to_hash(4) -> sha512.
|
||||
|
||||
set_password_instance(User, Server, #scram{hash = Hash, storedkey = SK, serverkey = SEK,
|
||||
salt = Salt, iterationcount = IC}) ->
|
||||
F = fun() ->
|
||||
set_password_scram_t(User, Server, Hash,
|
||||
SK, SEK, Salt, IC)
|
||||
end,
|
||||
case ejabberd_sql:sql_transaction(Server, F) of
|
||||
{atomic, _} ->
|
||||
ok;
|
||||
{aborted, _} ->
|
||||
{error, db_failure}
|
||||
end;
|
||||
set_password_instance(User, Server, Plain) ->
|
||||
F = fun() ->
|
||||
set_password_t(User, Server, Plain)
|
||||
end,
|
||||
case ejabberd_sql:sql_transaction(Server, F) of
|
||||
{atomic, _} ->
|
||||
ok;
|
||||
{aborted, _} ->
|
||||
{error, db_failure}
|
||||
end.
|
||||
|
||||
set_password_multiple(User, Server, Passwords) ->
|
||||
F =
|
||||
fun() ->
|
||||
case Password of
|
||||
#scram{hash = Hash, storedkey = SK, serverkey = SEK,
|
||||
salt = Salt, iterationcount = IC} ->
|
||||
SK2 = scram_hash_encode(Hash, SK),
|
||||
ejabberd_sql:sql_query_t(
|
||||
?SQL("delete from users where username=%(User)s and %(Server)H")),
|
||||
lists:foreach(
|
||||
fun(#scram{hash = Hash, storedkey = SK, serverkey = SEK,
|
||||
salt = Salt, iterationcount = IC}) ->
|
||||
set_password_scram_t(
|
||||
User, Server,
|
||||
SK2, SEK, Salt, IC);
|
||||
_ ->
|
||||
set_password_t(User, Server, Password)
|
||||
end
|
||||
User, Server, Hash,
|
||||
SK, SEK, Salt, IC);
|
||||
(Plain) ->
|
||||
set_password_t(User, Server, Plain)
|
||||
end, Passwords)
|
||||
end,
|
||||
case ejabberd_sql:sql_transaction(Server, F) of
|
||||
{atomic, _} ->
|
||||
{cache, {ok, Password}};
|
||||
{cache, {ok, Passwords}};
|
||||
{aborted, _} ->
|
||||
{nocache, {error, db_failure}}
|
||||
end.
|
||||
|
||||
try_register(User, Server, Password) ->
|
||||
Res =
|
||||
case Password of
|
||||
#scram{hash = Hash, storedkey = SK, serverkey = SEK,
|
||||
salt = Salt, iterationcount = IC} ->
|
||||
SK2 = scram_hash_encode(Hash, SK),
|
||||
add_user_scram(
|
||||
Server, User,
|
||||
SK2, SEK, Salt, IC);
|
||||
_ ->
|
||||
add_user(Server, User, Password)
|
||||
end,
|
||||
case Res of
|
||||
{updated, 1} -> {cache, {ok, Password}};
|
||||
_ -> {nocache, {error, exists}}
|
||||
try_register_multiple(User, Server, Passwords) ->
|
||||
F =
|
||||
fun() ->
|
||||
case ejabberd_sql:sql_query_t(
|
||||
?SQL("select @(count(*))d from users where username=%(User)s and %(Server)H")) of
|
||||
{selected, [{0}]} ->
|
||||
lists:foreach(
|
||||
fun(#scram{hash = Hash, storedkey = SK, serverkey = SEK,
|
||||
salt = Salt, iterationcount = IC}) ->
|
||||
set_password_scram_t(
|
||||
User, Server, Hash,
|
||||
SK, SEK, Salt, IC);
|
||||
(Plain) ->
|
||||
set_password_t(User, Server, Plain)
|
||||
end, Passwords),
|
||||
{cache, {ok, Passwords}};
|
||||
{selected, _} ->
|
||||
{nocache, {error, exists}};
|
||||
_ ->
|
||||
{nocache, {error, db_failure}}
|
||||
end
|
||||
end,
|
||||
case ejabberd_sql:sql_transaction(Server, F) of
|
||||
{atomic, Res} ->
|
||||
Res;
|
||||
{aborted, _} ->
|
||||
{nocache, {error, db_failure}}
|
||||
end.
|
||||
|
||||
get_users(Server, Opts) ->
|
||||
@@ -132,21 +204,41 @@ count_users(Server, Opts) ->
|
||||
|
||||
get_password(User, Server) ->
|
||||
case get_password_scram(Server, User) of
|
||||
{selected, [{Password, <<>>, <<>>, 0}]} ->
|
||||
{cache, {ok, Password}};
|
||||
{selected, [{StoredKey, ServerKey, Salt, IterationCount}]} ->
|
||||
{Hash, SK} = case StoredKey of
|
||||
<<"sha256:", Rest/binary>> -> {sha256, Rest};
|
||||
<<"sha512:", Rest/binary>> -> {sha512, Rest};
|
||||
Other -> {sha, Other}
|
||||
end,
|
||||
{cache, {ok, #scram{storedkey = SK,
|
||||
serverkey = ServerKey,
|
||||
salt = Salt,
|
||||
hash = Hash,
|
||||
iterationcount = IterationCount}}};
|
||||
{selected, []} ->
|
||||
{cache, error};
|
||||
{selected, Passwords} ->
|
||||
Converted = lists:map(
|
||||
fun({0, Password, <<>>, <<>>, 0}) ->
|
||||
update_password_type(User, Server, 1),
|
||||
Password;
|
||||
({_, Password, <<>>, <<>>, 0}) ->
|
||||
Password;
|
||||
({0, StoredKey, ServerKey, Salt, IterationCount}) ->
|
||||
{Hash, SK} = case StoredKey of
|
||||
<<"sha256:", Rest/binary>> ->
|
||||
update_password_type(User, Server, 3, Rest),
|
||||
{sha256, Rest};
|
||||
<<"sha512:", Rest/binary>> ->
|
||||
update_password_type(User, Server, 4, Rest),
|
||||
{sha512, Rest};
|
||||
Other ->
|
||||
update_password_type(User, Server, 2),
|
||||
{sha, Other}
|
||||
end,
|
||||
#scram{storedkey = SK,
|
||||
serverkey = ServerKey,
|
||||
salt = Salt,
|
||||
hash = Hash,
|
||||
iterationcount = IterationCount};
|
||||
({Type, StoredKey, ServerKey, Salt, IterationCount}) ->
|
||||
Hash = num_to_hash(Type),
|
||||
#scram{storedkey = StoredKey,
|
||||
serverkey = ServerKey,
|
||||
salt = Salt,
|
||||
hash = Hash,
|
||||
iterationcount = IterationCount}
|
||||
end, Passwords),
|
||||
{cache, {ok, Converted}};
|
||||
_ ->
|
||||
{nocache, error}
|
||||
end.
|
||||
@@ -159,6 +251,13 @@ remove_user(User, Server) ->
|
||||
{error, db_failure}
|
||||
end.
|
||||
|
||||
drop_password_type(LServer, Hash) ->
|
||||
Type = hash_to_num(Hash),
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("delete from users"
|
||||
" where type=%(Type)d and %(LServer)H")).
|
||||
|
||||
scram_hash_encode(Hash, StoreKey) ->
|
||||
case Hash of
|
||||
sha -> StoreKey;
|
||||
@@ -166,12 +265,14 @@ scram_hash_encode(Hash, StoreKey) ->
|
||||
sha512 -> <<"sha512:", StoreKey/binary>>
|
||||
end.
|
||||
|
||||
set_password_scram_t(LUser, LServer,
|
||||
set_password_scram_t(LUser, LServer, Hash,
|
||||
StoredKey, ServerKey, Salt, IterationCount) ->
|
||||
Type = hash_to_num(Hash),
|
||||
?SQL_UPSERT_T(
|
||||
"users",
|
||||
["!username=%(LUser)s",
|
||||
"!server_host=%(LServer)s",
|
||||
"!type=%(Type)d",
|
||||
"password=%(StoredKey)s",
|
||||
"serverkey=%(ServerKey)s",
|
||||
"salt=%(Salt)s",
|
||||
@@ -182,40 +283,31 @@ set_password_t(LUser, LServer, Password) ->
|
||||
"users",
|
||||
["!username=%(LUser)s",
|
||||
"!server_host=%(LServer)s",
|
||||
"!type=1",
|
||||
"password=%(Password)s",
|
||||
"serverkey=''",
|
||||
"salt=''",
|
||||
"iterationcount=0"]).
|
||||
|
||||
update_password_type(LUser, LServer, Type, Password) ->
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("update users set type=%(Type)d, password=%(Password)s"
|
||||
" where username=%(LUser)s and type=0 and %(LServer)H")).
|
||||
|
||||
update_password_type(LUser, LServer, Type) ->
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("update users set type=%(Type)d"
|
||||
" where username=%(LUser)s and type=0 and %(LServer)H")).
|
||||
|
||||
get_password_scram(LServer, LUser) ->
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("select @(password)s, @(serverkey)s, @(salt)s, @(iterationcount)d"
|
||||
?SQL("select @(type)d, @(password)s, @(serverkey)s, @(salt)s, @(iterationcount)d"
|
||||
" from users"
|
||||
" where username=%(LUser)s and %(LServer)H")).
|
||||
|
||||
add_user_scram(LServer, LUser,
|
||||
StoredKey, ServerKey, Salt, IterationCount) ->
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL_INSERT(
|
||||
"users",
|
||||
["username=%(LUser)s",
|
||||
"server_host=%(LServer)s",
|
||||
"password=%(StoredKey)s",
|
||||
"serverkey=%(ServerKey)s",
|
||||
"salt=%(Salt)s",
|
||||
"iterationcount=%(IterationCount)d"])).
|
||||
|
||||
add_user(LServer, LUser, Password) ->
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL_INSERT(
|
||||
"users",
|
||||
["username=%(LUser)s",
|
||||
"server_host=%(LServer)s",
|
||||
"password=%(Password)s"])).
|
||||
|
||||
del_user(LServer, LUser) ->
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
@@ -224,7 +316,7 @@ del_user(LServer, LUser) ->
|
||||
list_users(LServer, []) ->
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("select @(username)s from users where %(LServer)H"));
|
||||
?SQL("select @(distinct username)s from users where %(LServer)H"));
|
||||
list_users(LServer, [{from, Start}, {to, End}])
|
||||
when is_integer(Start) and is_integer(End) ->
|
||||
list_users(LServer,
|
||||
@@ -240,7 +332,7 @@ list_users(LServer, [{limit, Limit}, {offset, Offset}])
|
||||
when is_integer(Limit) and is_integer(Offset) ->
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("select @(username)s from users "
|
||||
?SQL("select @(distinct username)s from users "
|
||||
"where %(LServer)H "
|
||||
"order by username "
|
||||
"limit %(Limit)d offset %(Offset)d"));
|
||||
@@ -252,7 +344,7 @@ list_users(LServer,
|
||||
SPrefix2 = <<SPrefix/binary, $%>>,
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("select @(username)s from users "
|
||||
?SQL("select @(distinct username)s from users "
|
||||
"where username like %(SPrefix2)s %ESCAPE and %(LServer)H "
|
||||
"order by username "
|
||||
"limit %(Limit)d offset %(Offset)d")).
|
||||
@@ -269,11 +361,11 @@ users_number(LServer) ->
|
||||
" where oid = 'users'::regclass::oid"));
|
||||
_ ->
|
||||
ejabberd_sql:sql_query_t(
|
||||
?SQL("select @(count(*))d from users where %(LServer)H"))
|
||||
?SQL("select @(count(distinct username))d from users where %(LServer)H"))
|
||||
end;
|
||||
(_Type, _) ->
|
||||
ejabberd_sql:sql_query_t(
|
||||
?SQL("select @(count(*))d from users where %(LServer)H"))
|
||||
?SQL("select @(count(distinct username))d from users where %(LServer)H"))
|
||||
end).
|
||||
|
||||
users_number(LServer, [{prefix, Prefix}])
|
||||
@@ -282,7 +374,7 @@ users_number(LServer, [{prefix, Prefix}])
|
||||
SPrefix2 = <<SPrefix/binary, $%>>,
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("select @(count(*))d from users "
|
||||
?SQL("select @(count(distinct username))d from users "
|
||||
"where username like %(SPrefix2)s %ESCAPE and %(LServer)H"));
|
||||
users_number(LServer, []) ->
|
||||
users_number(LServer).
|
||||
@@ -290,7 +382,7 @@ users_number(LServer, []) ->
|
||||
which_users_exists(LServer, LUsers) when length(LUsers) =< 100 ->
|
||||
try ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("select @(username)s from users where username in %(LUsers)ls")) of
|
||||
?SQL("select @(distinct username)s from users where username in %(LUsers)ls")) of
|
||||
{selected, Matching} ->
|
||||
[U || {U} <- Matching];
|
||||
{error, _} = E ->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%%% Created : 24 Feb 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 mar 2022 by Paweł Chmielowski <pawel@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 20 Jul 2011 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
+81
-35
@@ -2,7 +2,7 @@
|
||||
%%% Created : 8 Dec 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -49,8 +49,9 @@
|
||||
get_fast_tokens_fun/2, fast_mechanisms/1]).
|
||||
%% Hooks
|
||||
-export([handle_unexpected_cast/2, handle_unexpected_call/3,
|
||||
process_auth_result/3, reject_unauthenticated_packet/2,
|
||||
process_closed/2, process_terminated/2, process_info/2]).
|
||||
process_auth_result/3, c2s_handle_bind/1,
|
||||
reject_unauthenticated_packet/2, 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_async/1,
|
||||
@@ -165,6 +166,7 @@ host_up(Host) ->
|
||||
ejabberd_hooks:add(c2s_closed, Host, ?MODULE, process_closed, 100),
|
||||
ejabberd_hooks:add(c2s_terminated, Host, ?MODULE,
|
||||
process_terminated, 100),
|
||||
ejabberd_hooks:add(c2s_handle_bind, Host, ?MODULE, c2s_handle_bind, 100),
|
||||
ejabberd_hooks:add(c2s_unauthenticated_packet, Host, ?MODULE,
|
||||
reject_unauthenticated_packet, 100),
|
||||
ejabberd_hooks:add(c2s_handle_info, Host, ?MODULE,
|
||||
@@ -181,6 +183,7 @@ host_down(Host) ->
|
||||
ejabberd_hooks:delete(c2s_closed, Host, ?MODULE, process_closed, 100),
|
||||
ejabberd_hooks:delete(c2s_terminated, Host, ?MODULE,
|
||||
process_terminated, 100),
|
||||
ejabberd_hooks:delete(c2s_handle_bind, Host, ?MODULE, c2s_handle_bind, 100),
|
||||
ejabberd_hooks:delete(c2s_unauthenticated_packet, Host, ?MODULE,
|
||||
reject_unauthenticated_packet, 100),
|
||||
ejabberd_hooks:delete(c2s_handle_info, Host, ?MODULE,
|
||||
@@ -285,6 +288,11 @@ handle_unexpected_cast(State, Msg) ->
|
||||
?WARNING_MSG("Unexpected cast: ~p", [Msg]),
|
||||
State.
|
||||
|
||||
c2s_handle_bind({<<"">>, {ok, State}}) ->
|
||||
{new_uniq_id(), {ok, State}};
|
||||
c2s_handle_bind(Acc) ->
|
||||
Acc.
|
||||
|
||||
reject_unauthenticated_packet(State, _Pkt) ->
|
||||
Err = xmpp:serr_not_authorized(),
|
||||
send(State, Err).
|
||||
@@ -415,16 +423,27 @@ sasl_mechanisms(Mechs, #{lserver := LServer, stream_encrypted := Encrypted} = St
|
||||
Type = ejabberd_auth:store_type(LServer),
|
||||
Mechs1 = ejabberd_option:disable_sasl_mechanisms(LServer),
|
||||
|
||||
ScramHash = ejabberd_option:auth_scram_hash(LServer),
|
||||
ShaAv = Type == plain orelse (Type == scram andalso ScramHash == sha),
|
||||
Sha256Av = Type == plain orelse (Type == scram andalso ScramHash == sha256),
|
||||
Sha512Av = Type == plain orelse (Type == scram andalso ScramHash == sha512),
|
||||
{Digest, ShaAv, Sha256Av, Sha512Av} =
|
||||
case ejabberd_option:auth_stored_password_types(LServer) of
|
||||
[] ->
|
||||
ScramHash = ejabberd_option:auth_scram_hash(LServer),
|
||||
{Type == plain,
|
||||
Type == plain orelse (Type == scram andalso ScramHash == sha),
|
||||
Type == plain orelse (Type == scram andalso ScramHash == sha256),
|
||||
Type == plain orelse (Type == scram andalso ScramHash == sha512)};
|
||||
Methods ->
|
||||
HasPlain = lists:member(plain, Methods),
|
||||
{HasPlain,
|
||||
HasPlain orelse lists:member(scram_sha1, Methods),
|
||||
HasPlain orelse lists:member(scram_sha256, Methods),
|
||||
HasPlain orelse lists:member(scram_sha512, Methods)}
|
||||
end,
|
||||
%% I re-created it from cyrsasl ets magic, but I think it's wrong
|
||||
%% TODO: need to check before 18.09 release
|
||||
lists:filter(
|
||||
fun(<<"ANONYMOUS">>) ->
|
||||
ejabberd_auth_anonymous:is_sasl_anonymous_enabled(LServer);
|
||||
(<<"DIGEST-MD5">>) -> Type == plain;
|
||||
(<<"DIGEST-MD5">>) -> Digest;
|
||||
(<<"SCRAM-SHA-1">>) -> ShaAv;
|
||||
(<<"SCRAM-SHA-1-PLUS">>) -> ShaAv andalso Encrypted;
|
||||
(<<"SCRAM-SHA-256">>) -> Sha256Av;
|
||||
@@ -480,33 +499,60 @@ fast_mechanisms(#{lserver := LServer}) ->
|
||||
_ -> mod_auth_fast:get_mechanisms(LServer)
|
||||
end.
|
||||
|
||||
bind(<<"">>, State) ->
|
||||
bind(new_uniq_id(), State);
|
||||
bind(R, #{user := U, server := S, access := Access, lang := Lang,
|
||||
lserver := LServer, socket := Socket,
|
||||
ip := IP} = State) ->
|
||||
case resource_conflict_action(U, S, R) of
|
||||
closenew ->
|
||||
{error, xmpp:err_conflict(), State};
|
||||
{accept_resource, Resource} ->
|
||||
JID = jid:make(U, S, Resource),
|
||||
case acl:match_rule(LServer, Access,
|
||||
#{usr => jid:split(JID), ip => IP}) of
|
||||
allow ->
|
||||
State1 = open_session(State#{resource => Resource,
|
||||
sid => ejabberd_sm:make_sid()}),
|
||||
State2 = ejabberd_hooks:run_fold(
|
||||
c2s_session_opened, LServer, State1, []),
|
||||
?INFO_MSG("(~ts) Opened c2s session for ~ts",
|
||||
[xmpp_socket:pp(Socket), jid:encode(JID)]),
|
||||
{ok, State2};
|
||||
deny ->
|
||||
ejabberd_hooks:run(forbidden_session_hook, LServer, [JID]),
|
||||
?WARNING_MSG("(~ts) Forbidden c2s session for ~ts",
|
||||
[xmpp_socket:pp(Socket), jid:encode(JID)]),
|
||||
Txt = ?T("Access denied by service policy"),
|
||||
{error, xmpp:err_not_allowed(Txt, Lang), State}
|
||||
end
|
||||
bind(
|
||||
R,
|
||||
#{
|
||||
user := U,
|
||||
server := S,
|
||||
lserver := LServer,
|
||||
access := Access,
|
||||
lang := Lang,
|
||||
socket := Socket,
|
||||
ip := IP
|
||||
}=State
|
||||
) ->
|
||||
case ejabberd_hooks:run_fold(c2s_handle_bind, LServer, {R, {ok, State}}, []) of
|
||||
{R2, {ok, State2}} ->
|
||||
case resource_conflict_action(U, S, R2) of
|
||||
closenew ->
|
||||
{error, xmpp:err_conflict(), State2};
|
||||
{accept_resource, Resource} ->
|
||||
JID = jid:make(U, S, Resource),
|
||||
case acl:match_rule(LServer, Access, #{usr => jid:split(JID), ip => IP}) of
|
||||
allow ->
|
||||
State3 = open_session(
|
||||
State2#{resource => Resource, sid => ejabberd_sm:make_sid()}
|
||||
),
|
||||
State4 = ejabberd_hooks:run_fold(
|
||||
c2s_session_opened, LServer, State3, []
|
||||
),
|
||||
?INFO_MSG(
|
||||
"(~ts) Opened c2s session for ~ts", [xmpp_socket:pp(Socket), jid:encode(JID)]
|
||||
),
|
||||
{ok, State4};
|
||||
deny ->
|
||||
ejabberd_hooks:run(forbidden_session_hook, LServer, [JID]),
|
||||
?WARNING_MSG(
|
||||
"(~ts) Forbidden c2s session for ~ts",
|
||||
[xmpp_socket:pp(Socket), jid:encode(JID)]
|
||||
),
|
||||
Txt = ?T("Access denied by service policy"),
|
||||
{error, xmpp:err_not_allowed(Txt, Lang), State2}
|
||||
end
|
||||
end;
|
||||
{R2, {error, XmppErr, _State2}=Err} ->
|
||||
case XmppErr of
|
||||
#stanza_error{reason = 'not-allowed'} ->
|
||||
JID = jid:make(U, S, R2),
|
||||
ejabberd_hooks:run(forbidden_session_hook, LServer, [JID]),
|
||||
?WARNING_MSG(
|
||||
"(~ts) Forbidden c2s session for ~ts",
|
||||
[xmpp_socket:pp(Socket), jid:encode(JID)]
|
||||
);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
Err
|
||||
end.
|
||||
|
||||
handle_stream_start(StreamStart, #{lserver := LServer} = State) ->
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%%% Created : 2 Nov 2007 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 26 Apr 2008 by Evgeniy Khramtsov <xramtsov@gmail.com>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
@@ -454,12 +454,15 @@ get_prog_name() ->
|
||||
|
||||
maybe_warning_norequesthandler() ->
|
||||
Host = hd(ejabberd_option:hosts()),
|
||||
URL = get_auto_url(any, ?MODULE, Host),
|
||||
case URL of
|
||||
undefined ->
|
||||
?WARNING_MSG("The option captcha_cmd is configured, "
|
||||
"but there is NO request_handler in listen option "
|
||||
"configured with ejabberd_captcha. Please check "
|
||||
AutoURL = get_auto_url(any, ?MODULE, Host),
|
||||
ManualURL = ejabberd_option:captcha_url(),
|
||||
case (AutoURL == undefined) and not is_binary(ManualURL) of
|
||||
true ->
|
||||
?CRITICAL_MSG("The option captcha_cmd is configured "
|
||||
"and captcha_url is set to auto, "
|
||||
"but I couldn't find a request_handler in listen option "
|
||||
"configured with ejabberd_captcha and integer port. "
|
||||
"Please setup the URL with option captcha_url, see "
|
||||
"https://docs.ejabberd.im/admin/configuration/basic/#captcha",
|
||||
[]);
|
||||
_ ->
|
||||
@@ -523,7 +526,7 @@ find_handler_port_path(Tls, Module) ->
|
||||
fun({{Port, _, _},
|
||||
ejabberd_http,
|
||||
#{tls := ThisTls, request_handlers := Handlers}})
|
||||
when (Tls == any) or (Tls == ThisTls) ->
|
||||
when is_integer(Port) and ((Tls == any) or (Tls == ThisTls)) ->
|
||||
case lists:keyfind(Module, 2, Handlers) of
|
||||
false -> false;
|
||||
{Path, Module} -> {true, {ThisTls, Port, Path}}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
%%% Created : 5 Jul 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 7 Oct 2015 by Christophe Romain <christophe.romain@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2024 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user