diff options
317 files changed, 1233 insertions, 3158 deletions
diff --git a/.travis.yml b/.travis.yml index e93703efc..efe6a63a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: erlang otp_release: - 19.0 - 20.3 - - 21.1 + - 21.2 services: - redis-server diff --git a/.travis/mysql_repo_key.asc b/.travis/mysql_repo_key.asc index 6c9fd8dec..281e134fb 100644 --- a/.travis/mysql_repo_key.asc +++ b/.travis/mysql_repo_key.asc @@ -1,5 +1,5 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.5 (GNU/Linux) +Version: GnuPG v1 mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3 RODjQReyCITRrdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZ @@ -11,9 +11,9 @@ kYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDI QJEXM6FSbi0LLtZciNlYsafwAPEOMDKpMqAK6IyisNtPvaLd8lH0bPAnWqcyefep rv0sxxqUEMcM3o7wwgfN83POkDasDbs3pjwPhxvhz6//62zQJ7Q2TXlTUUwgUmVs ZWFzZSBFbmdpbmVlcmluZyA8bXlzcWwtYnVpbGRAb3NzLm9yYWNsZS5jb20+iGwE -ExECACwCGyMCHgECF4ACGQEGCwkIBwMCBhUKCQgCAwUWAgMBAAUCWKcFIAUJHirJ -FAAKCRCMcY07UHLh9VcFAJ46pUyVd8BZ2r5CppMC1tmyQ3ceRgCfVPwuVsiS0VER -5WUqtAQDt+DoetCIaQQTEQIAKQIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAhkB +ExECACwCGyMCHgECF4ACGQEGCwkIBwMCBhUKCQgCAwUWAgMBAAUCXEBY+wUJI87e +5AAKCRCMcY07UHLh9RZPAJ9uvm0zlzfCN+DHxHVaoFLFjdVYTQCfborsC9tmEZYa +whhogjeBkZkorbyIaQQTEQIAKQIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAhkB BQJTAdRmBQkaZsvLAAoJEIxxjTtQcuH1X4MAoKNLWAbCBUj96637kv6Xa/fJuX5m AJwPtmgDfjUe2iuhXdTrFEPT19SB6ohmBBMRAgAmAhsjBgsJCAcDAgQVAggDBBYC AwECHgECF4AFAk53PioFCRP7AhUACgkQjHGNO1By4fUmzACeJdfqgc9gWTUhgmcM @@ -428,5 +428,5 @@ GoaU9u41oyZTIiXPiFidJoIZCh7fdurP8pn3X+R5HUNXMr7M+ba8lSNxce/F3kmH 0L7rsKqdh9d/aVxhJINJ+inVDnrXWVoXu9GBjT8Nco1iU9SIVAQYEQIADAUCTnc9 7QUJE/sBuAASB2VHUEcAAQEJEIxxjTtQcuH1FJsAmwWK9vmwRJ/y9gTnJ8PWf0BV roUTAKClYAhZuX2nUNwH4vlEJQHDqYa5yQ== -=HfUN +=ghXk -----END PGP PUBLIC KEY BLOCK----- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9d6220841..9ac1c6b2e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -124,7 +124,7 @@ That's it! Thank you for your contribution! ## <a name="cla"></a> Signing the Contributor License Agreement (CLA) -Upon submmitting a Pull Request, we will ask you to sign our CLA if you haven't done +Upon submitting a Pull Request, we will ask you to sign our CLA if you haven't done so before. It's a quick process, we promise, and you will be able to do it all online You can read [ProcessOne Contribution License Agreement][cla] in PDF. @@ -1,4 +1,4 @@ -ejabberd Community Edition +ejabberd Community Edition ========================== [![Build Status](https://travis-ci.org/processone/ejabberd.svg?branch=master)](https://travis-ci.org/processone/ejabberd) [![Hex version](https://img.shields.io/hexpm/v/ejabberd.svg "Hex version")](https://hex.pm/packages/ejabberd) diff --git a/configure.ac b/configure.ac index d23bf9b6b..81f0167ae 100644 --- a/configure.ac +++ b/configure.ac @@ -109,10 +109,10 @@ AC_ARG_ENABLE(mssql, esac],[db_type=generic]) AC_ARG_ENABLE(all, -[AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-stun --enable-sip --enable-debug --enable-tools (useful for Dialyzer checks, default: no)])], +[AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-stun --enable-sip --enable-debug --enable-tools (useful for Dialyzer checks, default: no)])], [case "${enableval}" in - yes) odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true stun=true sip=true debug=true tools=true ;; - no) odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false stun=false sip=false debug=false tools=false ;; + yes) odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true stun=true sip=true debug=true tools=true ;; + no) odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false stun=false sip=false debug=false tools=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) @@ -196,14 +196,6 @@ AC_ARG_ENABLE(elixir, *) AC_MSG_ERROR(bad value ${enableval} for --enable-elixir) ;; esac],[if test "x$elixir" = "x"; then elixir=false; fi]) -AC_ARG_ENABLE(iconv, -[AC_HELP_STRING([--enable-iconv], [enable iconv support (default: no)])], -[case "${enableval}" in - yes) iconv=true ;; - no) iconv=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-iconv) ;; -esac],[if test "x$iconv" = "x"; then iconv=false; fi]) - AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])], [case "${enableval}" in @@ -307,7 +299,6 @@ AC_SUBST(zlib) AC_SUBST(riak) AC_SUBST(redis) AC_SUBST(elixir) -AC_SUBST(iconv) AC_SUBST(stun) AC_SUBST(sip) AC_SUBST(debug) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index 66d65450c..0a38a2b7f 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -46,7 +46,7 @@ define_macro: - "no_sslv2" - "no_sslv3" - # TLS options for client able to use moder ciphers (Windows 7+, Android 5.0+) + # TLS options for client able to use modern ciphers (Windows 7+, Android 5.0+) CIPHERS_MODERN: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256" PROTOCOL_OPTIONS_MODERN: - "no_sslv2" @@ -85,6 +85,11 @@ listen: ciphers: CIPHERS_INTERMEDIATE protocol_options: PROTOCOL_OPTIONS_INTERMEDIATE tls: true + - + port: 5280 + ip: "::" + module: ejabberd_http + web_admin: true s2s_use_starttls: optional @@ -190,6 +195,8 @@ modules: - allow: admin access_create: muc_create access_persistent: muc_create + access_mam: + - allow default_room_options: mam: true mod_muc_admin: {} diff --git a/include/adhoc.hrl b/include/adhoc.hrl index 1f95ea466..9471557d0 100644 --- a/include/adhoc.hrl +++ b/include/adhoc.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/bosh.hrl b/include/bosh.hrl index 906f375bb..57fd644a5 100644 --- a/include/bosh.hrl +++ b/include/bosh.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_auth.hrl b/include/ejabberd_auth.hrl index baf755916..8b9cb47fe 100644 --- a/include/ejabberd_auth.hrl +++ b/include/ejabberd_auth.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_commands.hrl b/include/ejabberd_commands.hrl index ebe8418b6..1e24cc5d5 100644 --- a/include/ejabberd_commands.hrl +++ b/include/ejabberd_commands.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_config.hrl b/include/ejabberd_config.hrl index a4d98c88a..d83e07b3c 100644 --- a/include/ejabberd_config.hrl +++ b/include/ejabberd_config.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_ctl.hrl b/include/ejabberd_ctl.hrl index 009075124..f11e22f3b 100644 --- a/include/ejabberd_ctl.hrl +++ b/include/ejabberd_ctl.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_http.hrl b/include/ejabberd_http.hrl index e0183a531..33c02ca2b 100644 --- a/include/ejabberd_http.hrl +++ b/include/ejabberd_http.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_oauth.hrl b/include/ejabberd_oauth.hrl index f6fd71a8c..51e77636f 100644 --- a/include/ejabberd_oauth.hrl +++ b/include/ejabberd_oauth.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_sm.hrl b/include/ejabberd_sm.hrl index 188ed3f29..0d216e90c 100644 --- a/include/ejabberd_sm.hrl +++ b/include/ejabberd_sm.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_sql_pt.hrl b/include/ejabberd_sql_pt.hrl index e3b27303b..50f902fc6 100644 --- a/include/ejabberd_sql_pt.hrl +++ b/include/ejabberd_sql_pt.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_stacktrace.hrl b/include/ejabberd_stacktrace.hrl new file mode 100644 index 000000000..4fdec33ea --- /dev/null +++ b/include/ejabberd_stacktrace.hrl @@ -0,0 +1,27 @@ +%%%---------------------------------------------------------------------- +%%% +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License along +%%% with this program; if not, write to the Free Software Foundation, Inc., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-ifdef(DEPRECATED_GET_STACKTRACE). +-define(EX_RULE(Class, Reason, Stack), Class:Reason:Stack). +-define(EX_STACK(Stack), Stack). +-else. +-define(EX_RULE(Class, Reason, _), Class:Reason). +-define(EX_STACK(_), erlang:get_stacktrace()). +-endif. diff --git a/include/ejabberd_web_admin.hrl b/include/ejabberd_web_admin.hrl index b9549df05..477ee97a2 100644 --- a/include/ejabberd_web_admin.hrl +++ b/include/ejabberd_web_admin.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/eldap.hrl b/include/eldap.hrl index 995c8d79e..f839aa94f 100644 --- a/include/eldap.hrl +++ b/include/eldap.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/http_bind.hrl b/include/http_bind.hrl index 7e44f429b..457480c22 100644 --- a/include/http_bind.hrl +++ b/include/http_bind.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/logger.hrl b/include/logger.hrl index a407b2e21..2dd23e1ad 100644 --- a/include/logger.hrl +++ b/include/logger.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_announce.hrl b/include/mod_announce.hrl index d7e3bf6b5..5f716655d 100644 --- a/include/mod_announce.hrl +++ b/include/mod_announce.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_caps.hrl b/include/mod_caps.hrl index b875f825c..22dd23b7e 100644 --- a/include/mod_caps.hrl +++ b/include/mod_caps.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_last.hrl b/include/mod_last.hrl index 108278430..8bfec3edd 100644 --- a/include/mod_last.hrl +++ b/include/mod_last.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_mam.hrl b/include/mod_mam.hrl index 52a1481e2..e02b9249d 100644 --- a/include/mod_mam.hrl +++ b/include/mod_mam.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_muc.hrl b/include/mod_muc.hrl index a623e1eab..028662fe0 100644 --- a/include/mod_muc.hrl +++ b/include/mod_muc.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl index 65f3c5479..40b1b9c04 100644 --- a/include/mod_muc_room.hrl +++ b/include/mod_muc_room.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -100,7 +100,7 @@ room = <<"">> :: binary(), host = <<"">> :: binary(), server_host = <<"">> :: binary(), - access = {none,none,none,none} :: {atom(), atom(), atom(), atom()}, + access = {none,none,none,none,none} :: {atom(), atom(), atom(), atom(), atom()}, jid = #jid{} :: jid(), config = #config{} :: config(), users = #{} :: map(), @@ -113,7 +113,7 @@ history :: lqueue(), subject = [] :: [text()], subject_author = <<"">> :: binary(), - just_created = false :: boolean(), + just_created = misc:now_to_usec(now()) :: true | integer(), activity = treap:empty() :: treap:treap(), room_shaper = none :: shaper:shaper(), room_queue :: p1_queue:queue() | undefined diff --git a/include/mod_offline.hrl b/include/mod_offline.hrl index 9641827bf..a705aabe2 100644 --- a/include/mod_offline.hrl +++ b/include/mod_offline.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_privacy.hrl b/include/mod_privacy.hrl index 64507aec8..291970cce 100644 --- a/include/mod_privacy.hrl +++ b/include/mod_privacy.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_private.hrl b/include/mod_private.hrl index a013b24e5..4dddd29ed 100644 --- a/include/mod_private.hrl +++ b/include/mod_private.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_proxy65.hrl b/include/mod_proxy65.hrl index 58f2ac8fd..197d97d7f 100644 --- a/include/mod_proxy65.hrl +++ b/include/mod_proxy65.hrl @@ -2,7 +2,7 @@ %%% RFC 1928 constants. %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_push.hrl b/include/mod_push.hrl index 589cfac00..24f02a3ff 100644 --- a/include/mod_push.hrl +++ b/include/mod_push.hrl @@ -1,5 +1,5 @@ %%%---------------------------------------------------------------------- -%%% ejabberd, Copyright (C) 2017-2018 ProcessOne +%%% ejabberd, Copyright (C) 2017-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_roster.hrl b/include/mod_roster.hrl index 5ddd596d4..c795aabc7 100644 --- a/include/mod_roster.hrl +++ b/include/mod_roster.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_shared_roster.hrl b/include/mod_shared_roster.hrl index 3287b6e0c..d0fbeaa56 100644 --- a/include/mod_shared_roster.hrl +++ b/include/mod_shared_roster.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_vcard.hrl b/include/mod_vcard.hrl index 09e0891ea..94f286bfc 100644 --- a/include/mod_vcard.hrl +++ b/include/mod_vcard.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_vcard_xupdate.hrl b/include/mod_vcard_xupdate.hrl index 95ada7c26..25b73adef 100644 --- a/include/mod_vcard_xupdate.hrl +++ b/include/mod_vcard_xupdate.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/pubsub.hrl b/include/pubsub.hrl index 923f5f5a9..735cfc737 100644 --- a/include/pubsub.hrl +++ b/include/pubsub.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 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,7 +27,7 @@ %% this is currently a hard limit. %% Would be nice to have it configurable. --define(MAX_PAYLOAD_SIZE, 60000). +-define(MAX_PAYLOAD_SIZE, 250000). %% ------------------------------- %% Pubsub types diff --git a/lib/ejabberd/config/config.ex b/lib/ejabberd/config/config.ex index 4d1270bc1..4d1728d16 100644 --- a/lib/ejabberd/config/config.ex +++ b/lib/ejabberd/config/config.ex @@ -23,7 +23,7 @@ defmodule Ejabberd.Config do # Could be also possible to interrupt the compilation&execution by throwing # an exception if necessary. def __before_compile__(_env) do - get_modules_parsed_in_order + get_modules_parsed_in_order() |> EjabberdModule.validate |> EjabberdLogger.log_errors end @@ -48,7 +48,7 @@ defmodule Ejabberd.Config do Returns a list with all the opts, formatted for ejabberd. """ def get_ejabberd_opts do - get_general_opts + get_general_opts() |> Dict.put(:modules, get_modules_parsed_in_order()) |> Dict.put(:listeners, get_listeners_parsed_in_order()) |> Ejabberd.Config.OptsFormatter.format_opts_for_ejabberd diff --git a/lib/ejabberd/config/ejabberd_module.ex b/lib/ejabberd/config/ejabberd_module.ex index 4de9a302e..6a74fe460 100644 --- a/lib/ejabberd/config/ejabberd_module.ex +++ b/lib/ejabberd/config/ejabberd_module.ex @@ -12,7 +12,6 @@ defmodule Ejabberd.Config.EjabberdModule do defstruct [:module, :attrs] alias Ejabberd.Config.EjabberdModule - alias Ejabberd.Config.Attr alias Ejabberd.Config.Validation @doc """ diff --git a/lib/ejabberd/config/logger/ejabberd_logger.ex b/lib/ejabberd/config/logger/ejabberd_logger.ex index 270fbfaa6..90970ba73 100644 --- a/lib/ejabberd/config/logger/ejabberd_logger.ex +++ b/lib/ejabberd/config/logger/ejabberd_logger.ex @@ -21,7 +21,7 @@ defmodule Ejabberd.Config.EjabberdLogger do defp do_log_errors({:attribute, errors}), do: Enum.each errors, &log_attribute_error/1 defp do_log_errors({:dependency, errors}), do: Enum.each errors, &log_dependency_error/1 - defp log_attribute_error({{attr_name, val}, :attr_not_supported}), do: + defp log_attribute_error({{attr_name, _val}, :attr_not_supported}), do: IO.puts "[ WARN ] Annotation @#{attr_name} is not supported." defp log_attribute_error({{attr_name, val}, :type_not_supported}), do: diff --git a/lib/ejabberd/config/validator/validation.ex b/lib/ejabberd/config/validator/validation.ex index 2fe00361a..af582676e 100644 --- a/lib/ejabberd/config/validator/validation.ex +++ b/lib/ejabberd/config/validator/validation.ex @@ -7,9 +7,7 @@ defmodule Ejabberd.Config.Validation do @type mod_validation_result :: {:ok, EjabberdModule.t} | {:error, EjabberdModule.t, map} alias Ejabberd.Config.EjabberdModule - alias Ejabberd.Config.Attr alias Ejabberd.Config.Validator - alias Ejabberd.Config.ValidatorUtility @doc """ Given a module or a list of modules it runs validators on them diff --git a/lib/ejabberd/config/validator/validator_attrs.ex b/lib/ejabberd/config/validator/validator_attrs.ex index 94117ab21..6a85c068d 100644 --- a/lib/ejabberd/config/validator/validator_attrs.ex +++ b/lib/ejabberd/config/validator/validator_attrs.ex @@ -18,7 +18,7 @@ defmodule Ejabberd.Config.Validator.Attrs do def validate({modules, mod, errors}) do errors = Enum.reduce mod.attrs, errors, fn(attr, err) -> case Attr.validate(attr) do - {:ok, attr} -> err + {:ok, _attr} -> err {:error, attr, cause} -> put_error(err, :attribute, {attr, cause}) end end diff --git a/lib/mix/tasks/deps.tree.ex b/lib/mix/tasks/deps.tree.ex index 94cb85a50..9937270cd 100644 --- a/lib/mix/tasks/deps.tree.ex +++ b/lib/mix/tasks/deps.tree.ex @@ -40,7 +40,7 @@ defmodule Mix.Tasks.Ejabberd.Deps.Tree do end end - defp build_dependency_tree(mods, mod, []), do: %{module: mod, dependency: []} + defp build_dependency_tree(_mods, mod, []), do: %{module: mod, dependency: []} defp build_dependency_tree(mods, mod, deps) when is_list(deps) do dependencies = Enum.map deps, fn dep -> dep_deps = get_dependencies_of_mod(mods, dep) @@ -65,7 +65,7 @@ defmodule Mix.Tasks.Ejabberd.Deps.Tree do defp keep_only_mods_not_used_as_dep(mods, mods_used_as_dep) do Enum.filter mods, fn %{module: mod} -> - not mod in mods_used_as_dep + not (mod in mods_used_as_dep) end end diff --git a/lib/mod_presence_demo.ex b/lib/mod_presence_demo.ex index 09bf58405..3ce512c3d 100644 --- a/lib/mod_presence_demo.ex +++ b/lib/mod_presence_demo.ex @@ -17,4 +17,13 @@ defmodule ModPresenceDemo do info('Receive presence for #{user}') :none end + + def depends(_host, _opts) do + [] + end + + def mod_options(_host) do + [] + end + end @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "18.12.0", + version: "18.12.1", description: description(), elixir: "~> 1.4", elixirc_paths: ["lib"], @@ -25,12 +25,12 @@ defmodule Ejabberd.Mixfile do def application do [mod: {:ejabberd_app, []}, - applications: [:ssl, :os_mon], + applications: [:kernel, :stdlib, :sasl, :ssl], included_applications: [:lager, :mnesia, :inets, :p1_utils, :cache_tab, :fast_tls, :stringprep, :fast_xml, :xmpp, :stun, :fast_yaml, :esip, :jiffy, :p1_oauth2, - :eimp, :base64url, :jose, :pkix] - ++ cond_apps()] + :eimp, :base64url, :jose, :pkix, :os_mon] + ++ cond_apps()] end defp if_function_exported(mod, fun, arity, okResult) do @@ -42,10 +42,19 @@ defmodule Ejabberd.Mixfile do end end + defp if_version_above(ver, okResult) do + if :erlang.system_info(:otp_release) > ver do + okResult + else + [] + end + end + defp erlc_options do # Use our own includes + includes from all dependencies includes = ["include"] ++ deps_include(["fast_xml", "xmpp", "p1_utils"]) [:debug_info, {:d, :ELIXIR_ENABLED}] ++ cond_options() ++ Enum.map(includes, fn(path) -> {:i, path} end) ++ + if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++ if_function_exported(:crypto, :strong_rand_bytes, 1, [{:d, :STRONG_RAND_BYTES}]) ++ if_function_exported(:rand, :uniform, 1, [{:d, :RAND_UNIFORM}]) ++ if_function_exported(:gb_sets, :iterator_from, 2, [{:d, :GB_SETS_ITERATOR_FROM}]) ++ @@ -61,7 +70,7 @@ defmodule Ejabberd.Mixfile do [{:lager, "~> 3.6.0"}, {:p1_utils, "~> 1.0"}, {:fast_xml, "~> 1.1"}, - {:xmpp, "~> 1.2"}, + {:xmpp, "~> 1.3.0"}, {:cache_tab, "~> 1.0"}, {:stringprep, "~> 1.0"}, {:fast_yaml, "~> 1.0"}, @@ -72,7 +81,7 @@ defmodule Ejabberd.Mixfile do {:p1_pgsql, "~> 1.1"}, {:jiffy, "~> 0.14.7"}, {:p1_oauth2, "~> 0.6.1"}, - {:distillery, "~> 1.0"}, + {:distillery, "~> 2.0"}, {:pkix, "~> 1.0"}, {:ex_doc, ">= 0.0.0", only: :dev}, {:eimp, "~> 1.0"}, @@ -94,11 +103,8 @@ defmodule Ejabberd.Mixfile do {config(:riak), {:riakc, "~> 2.4"}}, {config(:redis), {:eredis, "~> 1.0"}}, {config(:zlib), {:ezlib, "~> 1.0"}}, - {config(:iconv), {:iconv, "~> 1.0"}}, {config(:pam), {:epam, "~> 1.0"}}, - {config(:tools), {:luerl, "~> 0.3.1"}}, - {config(:tools), {:meck, "~> 0.8.4"}}, - {config(:tools), {:moka, github: "processone/moka", tag: "1.0.5c"}}], do: + {config(:tools), {:luerl, "~> 0.3.1"}}], do: dep end @@ -107,8 +113,7 @@ defmodule Ejabberd.Mixfile do {config(:mysql), :p1_mysql}, {config(:pgsql), :p1_pgsql}, {config(:sqlite), :sqlite3}, - {config(:zlib), :ezlib}, - {config(:iconv), :iconv}], do: + {config(:zlib), :ezlib}], do: app end @@ -126,7 +131,7 @@ defmodule Ejabberd.Mixfile do defp vars do case :file.consult("vars.config") do {:ok,config} -> config - _ -> [zlib: true, iconv: false] + _ -> [zlib: true] end end @@ -1,7 +1,8 @@ %{ + "artificery": {:hex, :artificery, "0.2.6", "f602909757263f7897130cbd006b0e40514a541b148d366ad65b89236b93497a", [:mix], [], "hexpm"}, "base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"}, "cache_tab": {:hex, :cache_tab, "1.0.17", "0020e1036d7074d83a71be28b329ceb3e7f9d41cc5a8529b06c32ce4d8ee4995", [:rebar3], [{:p1_utils, "1.0.13", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"}, - "distillery": {:hex, :distillery, "1.5.5", "c6132d5c0152bdce6850fb6c942d58f1971b169b6965d908dc4e8767cfa51a95", [:mix], [], "hexpm"}, + "distillery": {:hex, :distillery, "2.0.12", "6e78fe042df82610ac3fa50bd7d2d8190ad287d120d3cd1682d83a44e8b34dfb", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.3.0", "17f0c38eaafb4800f746b457313af4b2442a8c2405b49c645768680f900be603", [:mix], [], "hexpm"}, "eimp": {:hex, :eimp, "1.0.9", "daf0d2904be3ef5e4128d946e158113cdb4d52555023746d29b83ce86b531f3c", [:rebar3], [{:p1_utils, "1.0.13", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"}, "epam": {:hex, :epam, "1.0.4", "2a5e40cbf9b2cf41df515782894c3b33c81b8ad32fff2fc847c3f725071dfaed", [:rebar3], [], "hexpm"}, @@ -14,15 +15,12 @@ "fast_yaml": {:hex, :fast_yaml, "1.0.17", "e945ef64e0cb7c311c7b42804dbe32a24e13a2afc0ffe249b7e0f9f9ac08e176", [:rebar3], [{:p1_utils, "1.0.13", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"}, "goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm"}, "hamcrest": {:hex, :basho_hamcrest, "0.4.1", "fb7b2c92d252a1e9db936750b86089addaebeb8f87967fb4bbdda61e8863338e", [:make, :mix, :rebar3], [], "hexpm"}, - "iconv": {:hex, :iconv, "1.0.10", "fc7de75c0a1fbc1e4ed0c68637ae7464a5dd9eee81710fff26321922d144ecea", [:rebar3], [{:p1_utils, "1.0.13", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"}, "jiffy": {:hex, :jiffy, "0.14.13", "225a9a35e26417832c611526567194b4d3adc4f0dfa5f2f7008f4684076f2a01", [:rebar3], [], "hexpm"}, "jose": {:hex, :jose, "1.8.4", "7946d1e5c03a76ac9ef42a6e6a20001d35987afd68c2107bcd8f01a84e75aa73", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm"}, "lager": {:hex, :lager, "3.6.7", "2fbf823944caa0fc10df5ec13f3f047524a249bb32f0d801b7900c9610264286", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm"}, "luerl": {:hex, :luerl, "0.3.1", "5412807630aac1aaf59ffe5a1bc09259c447b4faeb1d3fe2d4ef41b87676cb04", [:rebar3], [], "hexpm"}, "makeup": {:hex, :makeup, "0.5.5", "9e08dfc45280c5684d771ad58159f718a7b5788596099bdfb0284597d368a882", [:mix], [{:nimble_parsec, "~> 0.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, "makeup_elixir": {:hex, :makeup_elixir, "0.10.0", "0f09c2ddf352887a956d84f8f7e702111122ca32fbbc84c2f0569b8b65cbf7fa", [:mix], [{:makeup, "~> 0.5.5", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, - "meck": {:hex, :meck, "0.8.12", "1f7b1a9f5d12c511848fec26bbefd09a21e1432eadb8982d9a8aceb9891a3cf2", [:rebar3], [], "hexpm"}, - "moka": {:git, "https://github.com/processone/moka.git", "3eed3a6dd7dedb70a6cd18f86c7561a18626eb3b", [tag: "1.0.5c"]}, "nimble_parsec": {:hex, :nimble_parsec, "0.4.0", "ee261bb53214943679422be70f1658fff573c5d0b0a1ecd0f18738944f818efe", [:mix], [], "hexpm"}, "p1_mysql": {:hex, :p1_mysql, "1.0.8", "34ed5fe2f0e16a6ee5805c0c6c1d30ffbc4c5c9753197cdf384ee6e82c57b506", [:rebar3], [], "hexpm"}, "p1_oauth2": {:hex, :p1_oauth2, "0.6.3", "fbd91ba86bd7f03d2a4f6e62affa86bab9930abfd6b473d61eefb148f246cd46", [:rebar3], [], "hexpm"}, @@ -31,9 +29,8 @@ "pkix": {:hex, :pkix, "1.0.0", "d88658eccc30227e929efa91c6ca6a4d2b4d40b4db3635ebd6ed9e246ecfcf82", [:rebar3], [], "hexpm"}, "riak_pb": {:hex, :riak_pb, "2.3.2", "48ffbf66dbb3f136ab9a7134bac4e496754baa5ef58c4f50a61326736d996390", [:make, :mix, :rebar3], [{:hamcrest, "~> 0.4.1", [hex: :basho_hamcrest, repo: "hexpm", optional: false]}], "hexpm"}, "riakc": {:hex, :riakc, "2.5.3", "6132d9e687a0dfd314b2b24c4594302ca8b55568a5d733c491d8fb6cd4004763", [:make, :mix, :rebar3], [{:riak_pb, "~> 2.3", [hex: :riak_pb, repo: "hexpm", optional: false]}], "hexpm"}, - "samerlib": {:git, "https://github.com/processone/samerlib", "fbbba035b1548ac4e681df00d61bf609645333a0", [tag: "0.8.0c"]}, "sqlite3": {:hex, :sqlite3, "1.1.6", "4ea71af0b45908b5f02c9b09e4c87177039ef404f20accb35049cd8924cc417c", [:rebar3], [], "hexpm"}, "stringprep": {:hex, :stringprep, "1.0.14", "230a2d1c576bba168749d653fd6681166d02431ef07161a918444f3edb478ad0", [:rebar3], [{:p1_utils, "1.0.13", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"}, "stun": {:hex, :stun, "1.0.26", "87b05229d0519f0db5c6b67b5c25ed3b79766beb96eba83d29bde4cae9e702e4", [:rebar3], [{:fast_tls, "1.0.26", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.13", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"}, - "xmpp": {:hex, :xmpp, "1.2.8", "c506ea4c7e4b8d042654d54b080f4b6b4135c93658d7e156968a073c5b5f99a1", [:rebar3], [{:ezlib, "1.0.4", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.0.26", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.34", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.13", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.14", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm"}, + "xmpp": {:hex, :xmpp, "1.3.0", "29f2192d9d45a40abbb7a3637c81af5e0f08b7e8d6a9e12471dc6095675d7a92", [:rebar3], [{:ezlib, "1.0.4", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.0.26", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.34", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.13", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.14", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm"}, } diff --git a/rebar.config b/rebar.config index 72908852e..39608346d 100644 --- a/rebar.config +++ b/rebar.config @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -24,11 +24,11 @@ {fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.26"}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.14"}}}, {fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.34"}}}, - {xmpp, ".*", {git, "https://github.com/processone/xmpp", "278ddf9"}}, + {xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.3.0"}}}, {fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.17"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.8"}}}, {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.3"}}}, - {pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.0"}}}, + {pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.0"}}}, {jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.8.4"}}}, {eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.9"}}}, {if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.26"}}}}, @@ -51,12 +51,8 @@ %% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin {if_not_rebar3, {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}}, - {if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv", - {tag, "1.0.10"}}}}, {if_var_true, tools, {luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "v0.3"}}}}, - {if_var_true, tools, {meck, "0.8.*", {git, "https://github.com/eproxus/meck", - {tag, "0.8.12"}}}}, {if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.0.8"}}}}]}. @@ -76,8 +72,7 @@ epam, ezlib, eimp, - pkix, - iconv]}}. + pkix]}}. {erl_first_files, ["src/ejabberd_sql_pt.erl", "src/ejabberd_config.erl", "src/gen_mod.erl", "src/mod_muc_room.erl", @@ -92,6 +87,7 @@ {if_var_true, debug, debug_info}, {if_var_true, sip, {d, 'SIP'}}, {if_var_true, stun, {d, 'STUN'}}, + {if_version_above, "20", {d, 'DEPRECATED_GET_STACKTRACE'}}, {if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}}, {if_var_match, db_type, mssql, {d, 'mssql'}}, {if_var_true, elixir, {d, 'ELIXIR_ENABLED'}}, @@ -133,7 +129,6 @@ {if_var_true, riak, "(\"riak_object\":_/_)"}, {if_var_false, zlib, "(\"ezlib\":_/_)"}, {if_var_false, http, "(\"lhttpc\":_/_)"}, - {if_var_false, iconv, "(\"iconv\":_/_)"}, {if_var_false, odbc, "(\"odbc\":_/_)"}, {if_var_false, sqlite, "(\"sqlite3\":_/_)"}, {if_var_false, elixir, "(\"Elixir.*\":_/_)"}, @@ -145,19 +140,18 @@ {i, "deps/fast_xml/include"}, {i, "deps/xmpp/include"}]}. -{if_version_above, "17", {cover_enabled, true}}. +{cover_enabled, true}. {cover_export_enabled, true}. {recursive_cmds, ['configure-deps']}. {post_hook_configure, [{"fast_tls", []}, {"stringprep", []}, {"fast_yaml", []}, - {"eimp", []}, + {"eimp", []}, {if_var_true, sip, {"esip", []}}, {"fast_xml", [{if_var_true, full_xml, "--enable-full-xml"}]}, {if_var_true, pam, {"epam", []}}, - {if_var_true, zlib, {"ezlib", []}}, - {if_var_true, iconv, {"iconv", []}}]}. + {if_var_true, zlib, {"ezlib", []}}]}. %% Local Variables: %% mode: erlang diff --git a/rebar.config.script b/rebar.config.script index 00b32b38e..694d6879f 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/rel/reltool.config.script b/rel/reltool.config.script index 2a8566d54..f0a15012c 100644 --- a/rel/reltool.config.script +++ b/rel/reltool.config.script @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov <ekhramtsov@process-one.net> -%%% @copyright (C) 2013-2017, Evgeniy Khramtsov +%%% @copyright (C) 2013-2019, Evgeniy Khramtsov %%% @doc %%% %%% @end diff --git a/sql/lite.new.sql b/sql/lite.new.sql index 6ec7ea876..ab229c6b1 100644 --- a/sql/lite.new.sql +++ b/sql/lite.new.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2017 ProcessOne +-- ejabberd, Copyright (C) 2002-2019 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/sql/lite.sql b/sql/lite.sql index 177454c7b..8f128c331 100644 --- a/sql/lite.sql +++ b/sql/lite.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2017 ProcessOne +-- ejabberd, Copyright (C) 2002-2019 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/sql/mssql.sql b/sql/mssql.sql index 9393a19c1..7c3713b76 100644 --- a/sql/mssql.sql +++ b/sql/mssql.sql @@ -1,5 +1,5 @@ --
--- ejabberd, Copyright (C) 2002-2017 ProcessOne
+-- ejabberd, Copyright (C) 2002-2019 ProcessOne
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License as
diff --git a/sql/mysql.new.sql b/sql/mysql.new.sql index 832910d2c..65b6d1b78 100644 --- a/sql/mysql.new.sql +++ b/sql/mysql.new.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2017 ProcessOne +-- ejabberd, Copyright (C) 2002-2019 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/sql/mysql.sql b/sql/mysql.sql index 568d2b41c..2dc02bf69 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2017 ProcessOne +-- ejabberd, Copyright (C) 2002-2019 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/sql/pg.new.sql b/sql/pg.new.sql index 721ce1ae9..495441147 100644 --- a/sql/pg.new.sql +++ b/sql/pg.new.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2017 ProcessOne +-- ejabberd, Copyright (C) 2002-2019 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/sql/pg.sql b/sql/pg.sql index b9797b820..250a22d2d 100644 --- a/sql/pg.sql +++ b/sql/pg.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2017 ProcessOne +-- ejabberd, Copyright (C) 2002-2019 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/src/acl.erl b/src/acl.erl index 1bffd8fa9..959faeaf0 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -5,7 +5,7 @@ %%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd.app.src.in b/src/ejabberd.app.src.in index 407fc68e1..f1d08b8c7 100644 --- a/src/ejabberd.app.src.in +++ b/src/ejabberd.app.src.in @@ -5,7 +5,8 @@ {vsn, "@PACKAGE_VERSION@"}, {modules, []}, {registered, []}, - {applications, [kernel, stdlib]}, + {applications, [kernel, stdlib, sasl, ssl]}, + {included_applications, [os_mon, lager, mnesia, inets, p1_utils, fast_yaml, fast_tls, pkix, xmpp, cache_tab, eimp]}, {env, [{enabled_backends, [@enabled_backends@]}]}, {mod, {ejabberd_app, []}}]}. diff --git a/src/ejabberd.erl b/src/ejabberd.erl index 4d08fa5b3..a7de9ab11 100644 --- a/src/ejabberd.erl +++ b/src/ejabberd.erl @@ -5,7 +5,7 @@ %%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -43,12 +43,10 @@ -include("logger.hrl"). start() -> - %%ejabberd_cover:start(), - application:start(ejabberd). + application:ensure_all_started(ejabberd). stop() -> application:stop(ejabberd). - %%ejabberd_cover:stop(). halt() -> application:stop(lager), diff --git a/src/ejabberd_access_permissions.erl b/src/ejabberd_access_permissions.erl index 23dd9446d..0c53795b8 100644 --- a/src/ejabberd_access_permissions.erl +++ b/src/ejabberd_access_permissions.erl @@ -5,7 +5,7 @@ %%% Created : 7 Sep 2016 by Paweł Chmielowski <pawel@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -130,11 +130,12 @@ init([]) -> handle_call({can_access, Cmd, CallerInfo}, _From, State) -> CallerModule = maps:get(caller_module, CallerInfo, none), Host = maps:get(caller_host, CallerInfo, global), + Tag = maps:get(tag, CallerInfo, none), {State2, Defs0} = get_definitions(State), Defs = maps:get(extra_permissions, CallerInfo, []) ++ Defs0, Res = lists:foldl( fun({Name, _} = Def, none) -> - case matches_definition(Def, Cmd, CallerModule, Host, CallerInfo) of + case matches_definition(Def, Cmd, CallerModule, Tag, Host, CallerInfo) of true -> ?DEBUG("Command '~p' execution allowed by rule '~s' (CallerInfo=~p)", [Cmd, Name, CallerInfo]), allow; @@ -261,10 +262,12 @@ get_definitions(#state{definitions = none, fragments_generators = Gens} = State) end, {State#state{definitions = NDefs}, NDefs}. -matches_definition({_Name, {From, Who, What}}, Cmd, Module, Host, CallerInfo) -> +matches_definition({_Name, {From, Who, What}}, Cmd, Module, Tag, Host, CallerInfo) -> case What == all orelse lists:member(Cmd, What) of true -> - case From == [] orelse lists:member(Module, From) of + {Tags, Modules} = lists:partition(fun({tag, _}) -> true; (_) -> false end, From), + case (Modules == [] orelse lists:member(Module, Modules)) andalso + (Tags == [] orelse lists:member({tag, Tag}, Tags)) of true -> Scope = maps:get(oauth_scope, CallerInfo, none), lists:any( @@ -347,13 +350,15 @@ parse_api_permission(Name, Args0) -> parse_from(_Name, Module) when is_atom(Module) -> [Module]; parse_from(Name, Modules) when is_list(Modules) -> - lists:foreach(fun(Module) when is_atom(Module) -> - ok; - (Val) -> - report_error(<<"Invalid value '~p' used inside 'from' section for api_permission '~s'">>, - [Val, Name]) - end, Modules), - Modules; + lists:map( + fun(Module) when is_atom(Module) -> + Module; + ([{tag, Tag}]) when is_binary(Tag) -> + {tag, Tag}; + (Val) -> + report_error(<<"Invalid value '~p' used inside 'from' section for api_permission '~s'">>, + [Val, Name]) + end, Modules); parse_from(Name, Val) -> report_error(<<"Invalid value '~p' used inside 'from' section for api_permission '~s'">>, [Val, Name]). diff --git a/src/ejabberd_acme.erl b/src/ejabberd_acme.erl index bd4f22418..9e25ed4e6 100644 --- a/src/ejabberd_acme.erl +++ b/src/ejabberd_acme.erl @@ -25,6 +25,7 @@ -include("ejabberd_commands.hrl"). -include("ejabberd_acme.hrl"). -include_lib("public_key/include/public_key.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(DEFAULT_CONFIG_CONTACT, <<"mailto:example-admin@example.com">>). -define(DEFAULT_CONFIG_CA_URL, "https://acme-v01.api.letsencrypt.org"). @@ -100,10 +101,10 @@ is_valid_domain_opt(DomainString) -> end. -spec is_valid_revoke_cert(string()) -> boolean(). -is_valid_revoke_cert(DomainOrFile) -> +is_valid_revoke_cert(DomainOrFile) -> lists:prefix("file:", DomainOrFile) orelse lists:prefix("domain:", DomainOrFile). - + %% Commands get_commands_spec() -> [#ejabberd_commands{name = get_certificates, tags = [acme], @@ -142,7 +143,7 @@ get_commands_spec() -> %% -spec get_certificates(domains_opt()) -> string() | {'error', _}. get_certificates(Domains) -> - case is_valid_domain_opt(Domains) of + case is_valid_domain_opt(Domains) of true -> try CAUrl = get_config_ca_url(), @@ -150,9 +151,8 @@ get_certificates(Domains) -> catch throw:Throw -> Throw; - E:R -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, St]), + ?EX_RULE(E, R, St) -> + ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, ?EX_STACK(St)]), {error, get_certificates} end; false -> @@ -171,7 +171,7 @@ retrieve_or_create_account(CAUrl) -> case read_account_persistent() of none -> create_save_new_account(CAUrl); - + {ok, AccId, CAUrl, PrivateKey} -> {ok, AccId, PrivateKey}; {ok, _AccId, _, _PrivateKey} -> @@ -199,7 +199,7 @@ get_certificates2(CAUrl, PrivateKey, Hosts) -> %% Format the result to send back to ejabberdctl format_get_certificates_result(SavedCerts). --spec format_get_certificates_result([{'ok', bitstring(), _} | +-spec format_get_certificates_result([{'ok', bitstring(), _} | {'error', bitstring(), _}]) -> string(). format_get_certificates_result(Certs) -> @@ -211,26 +211,26 @@ format_get_certificates_result(Certs) -> case Cond of true -> Result = io_lib:format("Success:~n~s", [FormattedCerts]), - lists:flatten(Result); + lists:flatten(Result); _ -> Result = io_lib:format("Error with one or more certificates~n~s", [FormattedCerts]), lists:flatten(Result) end. --spec format_get_certificate({'ok', bitstring(), _} | +-spec format_get_certificate({'ok', bitstring(), _} | {'error', bitstring(), _}) -> string(). -format_get_certificate({ok, Domain, saved}) -> +format_get_certificate({ok, Domain, saved}) -> io_lib:format(" Certificate for domain: \"~s\" acquired and saved", [Domain]); -format_get_certificate({ok, Domain, not_found}) -> +format_get_certificate({ok, Domain, not_found}) -> io_lib:format(" Certificate for domain: \"~s\" not found, so it was not renewed", [Domain]); format_get_certificate({ok, Domain, no_expire}) -> io_lib:format(" Certificate for domain: \"~s\" is not close to expiring", [Domain]); format_get_certificate({error, Domain, Reason}) -> io_lib:format(" Error for domain: \"~s\", with reason: \'~s\'", [Domain, Reason]). --spec get_certificate(url(), bitstring(), jose_jwk:key()) -> - {'ok', bitstring(), pem()} | +-spec get_certificate(url(), bitstring(), jose_jwk:key()) -> + {'ok', bitstring(), pem()} | {'error', bitstring(), _}. get_certificate(CAUrl, DomainName, PrivateKey) -> try @@ -243,9 +243,8 @@ get_certificate(CAUrl, DomainName, PrivateKey) -> catch throw:Throw -> Throw; - E:R -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, St]), + ?EX_RULE(E, R, St) -> + ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, ?EX_STACK(St)]), {error, DomainName, get_certificate} end. @@ -267,23 +266,23 @@ create_save_new_account(CAUrl) -> %% TODO: %% Find a way to ask the user if he accepts the TOS --spec create_new_account(url(), bitstring(), jose_jwk:key()) -> {'ok', string()} | +-spec create_new_account(url(), bitstring(), jose_jwk:key()) -> {'ok', string()} | no_return(). create_new_account(CAUrl, Contact, PrivateKey) -> try {ok, Dirs, Nonce0} = ejabberd_acme_comm:directory(CAUrl), Req0 = [{ <<"contact">>, [Contact]}], - {ok, {TOS, Account}, Nonce1} = + {ok, {TOS, Account}, Nonce1} = ejabberd_acme_comm:new_account(Dirs, PrivateKey, Req0, Nonce0), {<<"id">>, AccIdInt} = lists:keyfind(<<"id">>, 1, Account), AccId = integer_to_list(AccIdInt), Req1 = [{ <<"agreement">>, list_to_bitstring(TOS)}], - {ok, _Account2, _Nonce2} = + {ok, _Account2, _Nonce2} = ejabberd_acme_comm:update_account({CAUrl, AccId}, PrivateKey, Req1, Nonce1), {ok, AccId} catch E:R -> - ?ERROR_MSG("Error: ~p creating an account for contact: ~p", + ?ERROR_MSG("Error: ~p creating an account for contact: ~p", [{E,R}, Contact]), throw({error,create_new_account}) end. @@ -298,7 +297,7 @@ create_new_authorization(CAUrl, DomainName, PrivateKey) -> {[{<<"type">>, <<"dns">>}, {<<"value">>, DomainName}]}}, {<<"existing">>, <<"accept">>}], - {ok, {AuthzUrl, Authz}, Nonce1} = + {ok, {AuthzUrl, Authz}, Nonce1} = ejabberd_acme_comm:new_authz(Dirs, PrivateKey, Req0, Nonce0), {ok, AuthzId} = location_to_id(AuthzUrl), @@ -321,7 +320,7 @@ create_new_authorization(CAUrl, DomainName, PrivateKey) -> acme_challenge:unregister_hooks(DomainName) end. --spec create_new_certificate(url(), {bitstring(), [bitstring()]}, jose_jwk:key()) -> +-spec create_new_certificate(url(), {bitstring(), [bitstring()]}, jose_jwk:key()) -> {ok, bitstring(), pem()}. create_new_certificate(CAUrl, {DomainName, AllSubDomains}, PrivateKey) -> try @@ -338,7 +337,7 @@ create_new_certificate(CAUrl, {DomainName, AllSubDomains}, PrivateKey) -> {ok, {IssuerCertLink, Certificate}, _Nonce1} = ejabberd_acme_comm:new_cert(Dirs, PrivateKey, Req, Nonce0), - DecodedCert = public_key:pkix_decode_cert(list_to_binary(Certificate), plain), + DecodedCert = public_key:pkix_decode_cert(list_to_binary(Certificate), plain), PemEntryCert = public_key:pem_entry_encode('Certificate', DecodedCert), {ok, IssuerCert, _Nonce2} = ejabberd_acme_comm:get_issuer_cert(IssuerCertLink), @@ -351,7 +350,7 @@ create_new_certificate(CAUrl, {DomainName, AllSubDomains}, PrivateKey) -> PemCertKey = public_key:pem_encode([PemEntryKey, PemEntryCert, PemEntryIssuerCert]), {ok, DomainName, PemCertKey} - catch + catch E:R -> ?ERROR_MSG("Error: ~p getting an authorization for domain: ~p~n", [{E,R}, DomainName]), @@ -383,9 +382,8 @@ renew_certificates() -> catch throw:Throw -> Throw; - E:R -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, St]), + ?EX_RULE(E, R, St) -> + ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, ?EX_STACK(St)]), {error, get_certificates} end. @@ -406,8 +404,8 @@ renew_certificates0(CAUrl) -> %% Format the result to send back to ejabberdctl format_get_certificates_result(SavedCerts). --spec renew_certificate(url(), {bitstring(), data_cert()}, jose_jwk:key()) -> - {'ok', bitstring(), _} | +-spec renew_certificate(url(), {bitstring(), data_cert()}, jose_jwk:key()) -> + {'ok', bitstring(), _} | {'error', bitstring(), _}. renew_certificate(CAUrl, {DomainName, _} = Cert, PrivateKey) -> case cert_to_expire(Cert) of @@ -449,9 +447,8 @@ list_certificates(Verbose) -> catch throw:Throw -> Throw; - E:R -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, St]), + ?EX_RULE(E, R, St) -> + ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, ?EX_STACK(St)]), {error, list_certificates} end; false -> @@ -492,34 +489,33 @@ format_certificate(DataCert, Verbose) -> format_certificate_verbose(DomainName, SANs, NotAfter, PemCert) end catch - E:R -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, St]), + ?EX_RULE(E, R, St) -> + ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, ?EX_STACK(St)]), fail_format_certificate(DomainName) end. --spec format_certificate_plain(bitstring(), [string()], {expired | ok, string()}, string()) +-spec format_certificate_plain(bitstring(), [string()], {expired | ok, string()}, string()) -> string(). format_certificate_plain(DomainName, SANs, NotAfter, Path) -> Result = lists:flatten(io_lib:format( - " Domain: ~s~n" + " Domain: ~s~n" "~s" - " ~s~n" - " Path: ~s", + " ~s~n" + " Path: ~s", [DomainName, lists:flatten([io_lib:format(" SAN: ~s~n", [SAN]) || SAN <- SANs]), format_validity(NotAfter), Path])), Result. --spec format_certificate_verbose(bitstring(), [string()], {expired | ok, string()}, bitstring()) +-spec format_certificate_verbose(bitstring(), [string()], {expired | ok, string()}, bitstring()) -> string(). format_certificate_verbose(DomainName, SANs, NotAfter, PemCert) -> Result = lists:flatten(io_lib:format( " Domain: ~s~n" - "~s" - " ~s~n" - " Certificate In PEM format: ~n~s", - [DomainName, + "~s" + " ~s~n" + " Certificate In PEM format: ~n~s", + [DomainName, lists:flatten([io_lib:format(" SAN: ~s~n", [SAN]) || SAN <- SANs]), format_validity(NotAfter), PemCert])), Result. @@ -533,8 +529,8 @@ format_validity({ok, NotAfter}) -> -spec fail_format_certificate(bitstring()) -> string(). fail_format_certificate(DomainName) -> Result = lists:flatten(io_lib:format( - " Domain: ~s~n" - " Failed to format Certificate", + " Domain: ~s~n" + " Failed to format Certificate", [DomainName])), Result. @@ -542,7 +538,7 @@ fail_format_certificate(DomainName) -> get_commonName(#'Certificate'{tbsCertificate = TbsCertificate}) -> #'TBSCertificate'{ subject = {rdnSequence, SubjectList} - } = TbsCertificate, + } = TbsCertificate, %% TODO: Not the best way to find the commonName ShallowSubjectList = [Attribute || [Attribute] <- SubjectList], @@ -560,9 +556,9 @@ get_notAfter(Certificate) -> true -> "19" ++ [Y1,Y2]; _ -> "20" ++ [Y1,Y2] end, - NotAfter = lists:flatten(io_lib:format("~s-~s-~s ~s:~s:~s", + NotAfter = lists:flatten(io_lib:format("~s-~s-~s ~s:~s:~s", [YEAR, [MO1,MO2], [D1,D2], - [H1,H2], [MI1,MI2], [S1,S2]])), + [H1,H2], [MI1,MI2], [S1,S2]])), case close_to_expire(UtcTime, 0) of true -> @@ -577,7 +573,7 @@ get_subjectAltNames(#'Certificate'{tbsCertificate = TbsCertificate}) -> extensions = Exts } = TbsCertificate, - EncodedSANs = [Val || #'Extension'{extnID = Oid, extnValue = Val} <- Exts, + EncodedSANs = [Val || #'Extension'{extnID = Oid, extnValue = Val} <- Exts, Oid =:= attribute_oid(subjectAltName)], lists:flatmap( @@ -586,7 +582,7 @@ get_subjectAltNames(#'Certificate'{tbsCertificate = TbsCertificate}) -> [Name || {dNSName, Name} <- SANs0] end, EncodedSANs). - + -spec get_utc_validity(#'Certificate'{}) -> string(). get_utc_validity(#'Certificate'{tbsCertificate = TbsCertificate}) -> @@ -618,18 +614,17 @@ revoke_certificates(DomainOrFile) -> catch throw:Throw -> Throw; - E:R -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, St]), + ?EX_RULE(E, R, St) -> + ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, ?EX_STACK(St)]), {error, revoke_certificate} - end. + end. -spec revoke_certificate0(url(), string()) -> {ok, deleted}. revoke_certificate0(CAUrl, DomainOrFile) -> ParsedCert = parse_revoke_cert_argument(DomainOrFile), revoke_certificate1(CAUrl, ParsedCert). --spec revoke_certificate1(url(), {domain, bitstring()} | {file, file:filename()}) -> +-spec revoke_certificate1(url(), {domain, bitstring()} | {file, file:filename()}) -> {ok, deleted}. revoke_certificate1(CAUrl, {domain, Domain}) -> case domain_certificate_exists(Domain) of @@ -650,7 +645,7 @@ revoke_certificate1(CAUrl, {file, File}) -> ?ERROR_MSG("Error: ~p reading pem certificate-key file: ~p", [Reason, File]), throw({error, Reason}) end. - + -spec revoke_certificate2(url(), pem()) -> ok. revoke_certificate2(CAUrl, PemEncodedCert) -> @@ -676,10 +671,10 @@ prepare_certificate_revoke(PemEncodedCert) -> DerCert = public_key:der_encode('Certificate', PemCert), Base64Cert = base64url:encode(DerCert), - {ok, Key} = find_private_key_in_pem(PemEncodedCert), + {ok, Key} = find_private_key_in_pem(PemEncodedCert), {Base64Cert, Key}. --spec domain_certificate_exists(bitstring()) -> {bitstring(), data_cert()} | false. +-spec domain_certificate_exists(bitstring()) -> {bitstring(), data_cert()} | false. domain_certificate_exists(Domain) -> Certs = read_certificates_persistent(), lists:keyfind(Domain, 1, Certs). @@ -693,7 +688,7 @@ domain_certificate_exists(Domain) -> %% For now we accept only generating a key of %% specific type for signing the csr --spec make_csr(proplist(), [{dNSName, bitstring()}]) +-spec make_csr(proplist(), [{dNSName, bitstring()}]) -> {binary(), jose_jwk:key()}. make_csr(Attributes, SANs) -> Key = generate_key(), @@ -749,9 +744,9 @@ extension(SANs) -> extension_request(SANs) -> #'AttributePKCS-10'{ type = ?'pkcs-9-at-extensionRequest', - values = [{'asn1_OPENTYPE', + values = [{'asn1_OPENTYPE', public_key:der_encode( - 'ExtensionRequest', + 'ExtensionRequest', [extension(SANs)])}] }. @@ -918,7 +913,7 @@ find_private_key_in_pem(Pem) -> JoseKey = jose_jwk:from_key(Key), {ok, JoseKey} end. - + -spec find_private_key_in_pem1([public_key:pki_asn1_type()], [public_key:pem_entry()]) -> @@ -948,10 +943,10 @@ private_key_types() -> find_all_sub_domains(DomainName) -> AllRoutes = ejabberd_router:get_all_routes(), DomainLen = size(DomainName), - [Route || Route <- AllRoutes, - binary:longest_common_suffix([DomainName, Route]) + [Route || Route <- AllRoutes, + binary:longest_common_suffix([DomainName, Route]) =:= DomainLen]. - + -spec is_error(_) -> boolean(). is_error({error, _}) -> true; @@ -981,13 +976,13 @@ data_get_account(Data) -> end. -spec data_set_account(acme_data(), {list(), url(), jose_jwk:key()}) -> acme_data(). -data_set_account(Data, {AccId, CAUrl, PrivateKey}) -> +data_set_account(Data, {AccId, CAUrl, PrivateKey}) -> NewAcc = {account, #data_acc{id = AccId, ca_url = CAUrl, key = PrivateKey}}, lists:keystore(account, 1, Data, NewAcc). %% %% Certificates -%% +%% -spec data_get_certificates(acme_data()) -> data_certs(). data_get_certificates(Data) -> @@ -999,7 +994,7 @@ data_get_certificates(Data) -> end. -spec data_set_certificates(acme_data(), data_certs()) -> acme_data(). -data_set_certificates(Data, NewCerts) -> +data_set_certificates(Data, NewCerts) -> lists:keystore(certs, 1, Data, {certs, NewCerts}). %% ATM we preserve one certificate for each domain @@ -1053,7 +1048,7 @@ write_persistent(Data) -> {error, Reason} -> ?ERROR_MSG("Error: ~p writing acme data file", [Reason]), throw({error, Reason}) - end. + end. -spec create_persistent() -> ok | no_return(). create_persistent() -> @@ -1069,7 +1064,7 @@ create_persistent() -> {error, Reason} -> ?ERROR_MSG("Error: ~p creating acme data file", [Reason]), throw({error, Reason}) - end. + end. -spec write_account_persistent({list(), url(), jose_jwk:key()}) -> ok | no_return(). write_account_persistent({AccId, CAUrl, PrivateKey}) -> @@ -1099,7 +1094,7 @@ remove_certificate_persistent(DataCert) -> NewData = data_remove_certificate(Data, DataCert), ok = write_persistent(NewData). --spec save_certificate({ok, bitstring(), binary()} | {error, _, _}) -> +-spec save_certificate({ok, bitstring(), binary()} | {error, _, _}) -> {ok, bitstring(), saved} | {error, bitstring(), _}. save_certificate({error, _, _} = Error) -> Error; @@ -1123,13 +1118,12 @@ save_certificate({ok, DomainName, Cert}) -> catch throw:Throw -> Throw; - E:R -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, St]), + ?EX_RULE(E, R, St) -> + ?ERROR_MSG("Unknown ~p:~p, ~p", [E, R, ?EX_STACK(St)]), {error, DomainName, saving} end. --spec save_renewed_certificate({ok, bitstring(), _} | {error, _, _}) -> +-spec save_renewed_certificate({ok, bitstring(), _} | {error, _, _}) -> {ok, bitstring(), _} | {error, bitstring(), _}. save_renewed_certificate({error, _, _} = Error) -> Error; diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index beaaaf562..4dbd0a0be 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -5,7 +5,7 @@ %%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 90c36a593..41e284de4 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -5,7 +5,7 @@ %%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -41,7 +41,7 @@ start(normal, _Args) -> {T1, _} = statistics(wall_clock), ejabberd_logger:start(), write_pid_file(), - start_apps(), + start_included_apps(), start_elixir_application(), ejabberd:check_app(ejabberd), setup_if_elixir_conf_used(), @@ -73,6 +73,19 @@ start(normal, _Args) -> start(_, _) -> {error, badarg}. +start_included_apps() -> + {ok, Apps} = application:get_key(ejabberd, included_applications), + lists:foreach( + fun(mnesia) -> + ok; + (lager)-> + ok; + (os_mon)-> + ok; + (App) -> + application:ensure_all_started(App) + end, Apps). + %% Prepare the application for termination. %% This function is called when an application is about to be stopped, %% before shutting down the processes of the application. @@ -148,18 +161,6 @@ file_queue_init() -> end, p1_queue:start(QueueDir). -start_apps() -> - crypto:start(), - ejabberd:start_app(sasl), - ejabberd:start_app(ssl), - ejabberd:start_app(p1_utils), - ejabberd:start_app(fast_yaml), - ejabberd:start_app(fast_tls), - ejabberd:start_app(pkix), - ejabberd:start_app(xmpp), - ejabberd:start_app(cache_tab), - ejabberd:start_app(eimp). - setup_if_elixir_conf_used() -> case ejabberd_config:is_using_elixir_config() of true -> 'Elixir.Ejabberd.Config.Store':start_link(); diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index bc0211548..c27930140 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -5,7 +5,7 @@ %%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index 3c4993cb0..21aecc341 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -5,7 +5,7 @@ %%% Created : 17 Feb 2006 by Mickael Remond <mremond@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 3e300e3a0..6b2e2852e 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -5,7 +5,7 @@ %%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index b23b1c340..06000c7f1 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -5,7 +5,7 @@ %%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_mnesia.erl b/src/ejabberd_auth_mnesia.erl index 004e74996..1f75f686d 100644 --- a/src/ejabberd_auth_mnesia.erl +++ b/src/ejabberd_auth_mnesia.erl @@ -5,7 +5,7 @@ %%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_pam.erl b/src/ejabberd_auth_pam.erl index 71b745df0..ffbab1f1f 100644 --- a/src/ejabberd_auth_pam.erl +++ b/src/ejabberd_auth_pam.erl @@ -5,7 +5,7 @@ %%% Created : 5 Jul 2007 by Evgeniy Khramtsov <xram@jabber.ru> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_riak.erl b/src/ejabberd_auth_riak.erl index 33c25424a..29da504c9 100644 --- a/src/ejabberd_auth_riak.erl +++ b/src/ejabberd_auth_riak.erl @@ -5,7 +5,7 @@ %%% Created : 12 Nov 2012 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_sql.erl b/src/ejabberd_auth_sql.erl index cd9c02b91..f6f4f9efb 100644 --- a/src/ejabberd_auth_sql.erl +++ b/src/ejabberd_auth_sql.erl @@ -5,7 +5,7 @@ %%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_backend_sup.erl b/src/ejabberd_backend_sup.erl index dadb31f12..832c4e3e6 100644 --- a/src/ejabberd_backend_sup.erl +++ b/src/ejabberd_backend_sup.erl @@ -2,7 +2,7 @@ %%% Created : 24 Feb 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_bosh.erl b/src/ejabberd_bosh.erl index e39a67132..cdfd59b8a 100644 --- a/src/ejabberd_bosh.erl +++ b/src/ejabberd_bosh.erl @@ -5,7 +5,7 @@ %%% Created : 20 Jul 2011 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index ba5b04af8..61284e3e6 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -2,7 +2,7 @@ %%% Created : 8 Dec 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -638,15 +638,16 @@ route_probe_reply(From, #{jid := To, Subscription = get_subscription(To, From), if IsAnotherResource orelse Subscription == both orelse Subscription == from -> - Packet = misc:add_delay_info(LastPres, To, TS), - case privacy_check_packet(State, Packet, out) of + Packet = xmpp:set_from_to(LastPres, To, From), + Packet2 = misc:add_delay_info(Packet, To, TS), + case privacy_check_packet(State, Packet2, out) of deny -> ok; allow -> ejabberd_hooks:run(presence_probe_hook, LServer, [From, To, self()]), - ejabberd_router:route(xmpp:set_from_to(Packet, To, From)) + ejabberd_router:route(Packet2) end; true -> ok diff --git a/src/ejabberd_c2s_config.erl b/src/ejabberd_c2s_config.erl index 0a183783d..d6782de4f 100644 --- a/src/ejabberd_c2s_config.erl +++ b/src/ejabberd_c2s_config.erl @@ -6,7 +6,7 @@ %%% Created : 2 Nov 2007 by Mickael Remond <mremond@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 9f9d7b03f..91f0cb2da 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -5,7 +5,7 @@ %%% Created : 26 Apr 2008 by Evgeniy Khramtsov <xramtsov@gmail.com> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -105,12 +105,13 @@ create_captcha(SID, From, To, Lang, Limiter, Args) -> "To unblock them, visit ~s">>, [JID, get_url(Id)]}, Body = xmpp:mk_text(BodyString, Lang), OOB = #oob_x{url = get_url(Id)}, + Hint = #hint{type = 'no-store'}, Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}), ets:insert(captcha, #captcha{id = Id, pid = self(), key = Key, tref = Tref, args = Args}), - {ok, Id, Body, [OOB, Captcha, Data]}; + {ok, Id, Body, [Hint, OOB, Captcha, Data]}; Err -> Err end. diff --git a/src/ejabberd_cluster.erl b/src/ejabberd_cluster.erl index 8fb9dde8e..10f945fe7 100644 --- a/src/ejabberd_cluster.erl +++ b/src/ejabberd_cluster.erl @@ -3,7 +3,7 @@ %%% Created : 5 Jul 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_cluster_mnesia.erl b/src/ejabberd_cluster_mnesia.erl index 4889abd66..fb793cda8 100644 --- a/src/ejabberd_cluster_mnesia.erl +++ b/src/ejabberd_cluster_mnesia.erl @@ -5,7 +5,7 @@ %%% Created : 7 Oct 2015 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index 56a1518e4..921ed25c7 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -5,7 +5,7 @@ %%% Created : 20 May 2008 by Badlop <badlop@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -492,6 +492,7 @@ do_execute_command(Command, Arguments) -> Module = Command#ejabberd_commands.module, Function = Command#ejabberd_commands.function, ?DEBUG("Executing command ~p:~p with Args=~p", [Module, Function, Arguments]), + ejabberd_hooks:run(api_call, [Module, Function, Arguments]), apply(Module, Function, Arguments). -spec get_tags_commands() -> [{string(), [string()]}]. diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index 590e06ea9..b62c4ca5b 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -5,7 +5,7 @@ %%% Created : 20 May 2008 by Badlop <badlop@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 90bbed179..ed52c728b 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -5,7 +5,7 @@ %%% Created : 14 Dec 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -713,10 +713,16 @@ process_term(Term, State) -> process_host_term(Term, Host, State, Action) -> case Term of - {modules, Modules} when Action == set -> - set_option({modules, Host}, replace_modules(Modules), State); - {modules, Modules} when Action == append -> - append_option({modules, Host}, replace_modules(Modules), State); + {modules, Modules} -> + Modules1 = try (gen_mod:opt_type(modules))(Modules) of + _ -> replace_modules(Modules) + catch _:_ -> Modules + end, + if Action == set -> + set_option({modules, Host}, Modules1, State); + Action == append -> + append_option({modules, Host}, Modules1, State) + end; {host, _} -> State; {hosts, _} -> @@ -1449,7 +1455,7 @@ opt_type(hosts) -> [iolist_to_binary(H) || H <- L] end; opt_type(language) -> - fun iolist_to_binary/1; + fun xmpp_lang:check/1; opt_type(max_fsm_queue) -> fun (I) when is_integer(I), I > 0 -> I end; opt_type(default_db) -> diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index c71649562..73a98827c 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -5,7 +5,7 @@ %%% Created : 11 Jan 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -59,6 +59,7 @@ -include("ejabberd_ctl.hrl"). -include("ejabberd_commands.hrl"). -include("logger.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(DEFAULT_VERSION, 1000000). @@ -327,9 +328,9 @@ try_call_command(Args, Auth, AccessCommands, Version) -> catch throw:Error -> {io_lib:format("~p", [Error]), ?STATUS_ERROR}; - A:Why -> - Stack = erlang:get_stacktrace(), - {io_lib:format("Problem '~p ~p' occurred executing the command.~nStacktrace: ~p", [A, Why, Stack]), ?STATUS_ERROR} + ?EX_RULE(A, Why, Stack) -> + {io_lib:format("Problem '~p ~p' occurred executing the command.~nStacktrace: ~p", + [A, Why, ?EX_STACK(Stack)]), ?STATUS_ERROR} end. %% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} | {error, ErrorType} diff --git a/src/ejabberd_hooks.erl b/src/ejabberd_hooks.erl index bc67b4c67..28d994c4a 100644 --- a/src/ejabberd_hooks.erl +++ b/src/ejabberd_hooks.erl @@ -5,7 +5,7 @@ %%% Created : 8 Aug 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -57,6 +57,7 @@ terminate/2]). -include("logger.hrl"). +-include("ejabberd_stacktrace.hrl"). -record(state, {}). -type local_hook() :: { Seq :: integer(), Module :: atom(), Function :: atom()}. @@ -129,14 +130,14 @@ delete_dist(Hook, Node, Module, Function, Seq) -> delete_dist(Hook, Host, Node, Module, Function, Seq) -> gen_server:call(ejabberd_hooks, {delete, Hook, Host, Node, Module, Function, Seq}). --spec delete_all_hooks() -> true. +-spec delete_all_hooks() -> true. %% @doc Primarily for testing / instrumentation delete_all_hooks() -> gen_server:call(ejabberd_hooks, {delete_all}). -spec get_handlers(atom(), binary() | global) -> [local_hook() | distributed_hook()]. -%% @doc Returns currently set handler for hook name +%% @doc Returns currently set handler for hook name get_handlers(Hookname, Host) -> gen_server:call(ejabberd_hooks, {get_handlers, Hookname, Host}). @@ -264,7 +265,7 @@ handle_delete(Hook, Host, El) -> ok; [] -> ok - end. + end. %%---------------------------------------------------------------------- %% Func: handle_cast/2 @@ -379,15 +380,11 @@ safe_apply(Hook, Module, Function, Args) -> true -> apply(Module, Function, Args) end - catch E:R when E /= exit; R /= normal -> - St = get_stacktrace(), + catch ?EX_RULE(E, R, St) when E /= exit; R /= normal -> ?ERROR_MSG("Hook ~p crashed when running ~p:~p/~p:~n" "** Reason = ~p~n" "** Arguments = ~p", [Hook, Module, Function, length(Args), - {E, R, St}, Args]), + {E, R, ?EX_STACK(St)}, Args]), 'EXIT' end. - -get_stacktrace() -> - [{Mod, Fun, Loc, Args} || {Mod, Fun, Args, Loc} <- erlang:get_stacktrace()]. diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 769577371..c226dba1c 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -5,7 +5,7 @@ %%% Created : 27 Feb 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -852,23 +852,23 @@ code_to_phrase(505) -> <<"HTTP Version Not Supported">>. -spec parse_auth(binary()) -> {binary(), binary()} | {oauth, binary(), []} | undefined. parse_auth(<<"Basic ", Auth64/binary>>) -> - Auth = try base64:decode(Auth64) - catch _:badarg -> <<>> - end, - %% Auth should be a string with the format: user@server:password - %% Note that password can contain additional characters '@' and ':' - case str:chr(Auth, $:) of - 0 -> - undefined; - Pos -> - {User, <<$:, Pass/binary>>} = erlang:split_binary(Auth, Pos-1), - PassUtf8 = unicode:characters_to_binary(binary_to_list(Pass), utf8), - {User, PassUtf8} + try base64:decode(Auth64) of + Auth -> + case binary:split(Auth, <<":">>) of + [User, Pass] -> + PassUtf8 = unicode:characters_to_binary(Pass, utf8), + {User, PassUtf8}; + _ -> + invalid + end + catch _:_ -> + invalid end; parse_auth(<<"Bearer ", SToken/binary>>) -> Token = str:strip(SToken), {oauth, Token, []}; -parse_auth(<<_/binary>>) -> undefined. +parse_auth(<<_/binary>>) -> + invalid. parse_urlencoded(S) -> parse_urlencoded(S, nokey, <<>>, key). @@ -992,6 +992,8 @@ listen_opt_type(http_bind) -> fun(B) when is_boolean(B) -> B end; listen_opt_type(xmlrpc) -> fun(B) when is_boolean(B) -> B end; +listen_opt_type(tag) -> + fun(B) when is_binary(B) -> B end; listen_opt_type(request_handlers) -> fun(Hs) -> Hs1 = lists:map(fun @@ -1026,5 +1028,6 @@ listen_options() -> {http_bind, false}, {xmlrpc, false}, {request_handlers, []}, + {tag, <<>>}, {default_host, undefined}, {custom_headers, []}]. diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index d10dbd108..4b54e67ec 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -5,7 +5,7 @@ %%% Created : 09-10-2010 by Eric Cestari <ecestari@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_iq.erl b/src/ejabberd_iq.erl index adee25dbe..aeaffccde 100644 --- a/src/ejabberd_iq.erl +++ b/src/ejabberd_iq.erl @@ -5,7 +5,7 @@ %%% Created : 10 Nov 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -173,4 +173,8 @@ calc_checksum(Data) -> callback(undefined, IQRes, Fun) -> Fun(IQRes); callback(Proc, IQRes, Ctx) -> - Proc ! {iq_reply, IQRes, Ctx}. + try + Proc ! {iq_reply, IQRes, Ctx} + catch _:badarg -> + ok + end. diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index e8742413b..c32f5be86 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -5,7 +5,7 @@ %%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index d9ef97129..1384a2359 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -5,7 +5,7 @@ %%% Created : 30 Nov 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 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,6 +48,7 @@ -include("logger.hrl"). -include_lib("stdlib/include/ms_transform.hrl"). -include("xmpp.hrl"). +-include("ejabberd_stacktrace.hrl"). -record(state, {}). @@ -70,10 +71,9 @@ start_link() -> -spec route(stanza()) -> any(). route(Packet) -> try do_route(Packet) - catch E:R -> - St = erlang:get_stacktrace(), + catch ?EX_RULE(E, R, St) -> ?ERROR_MSG("failed to route packet:~n~s~nReason = ~p", - [xmpp:pp(Packet), {E, {R, St}}]) + [xmpp:pp(Packet), {E, {R, ?EX_STACK(St)}}]) end. -spec route_iq(iq(), function()) -> ok. diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index c7845be2f..e35a769e5 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -5,7 +5,7 @@ %%% Created : 12 May 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2013-2018 ProcessOne +%%% ejabberd, Copyright (C) 2013-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_mnesia.erl b/src/ejabberd_mnesia.erl index 48bc6db5c..3ccf6af89 100644 --- a/src/ejabberd_mnesia.erl +++ b/src/ejabberd_mnesia.erl @@ -5,7 +5,7 @@ %%% Created : 17 Nov 2016 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -43,6 +43,7 @@ -define(NEED_RESET, [local_content, type]). -include("logger.hrl"). +-include("ejabberd_stacktrace.hrl"). -record(state, {tables = #{} :: map(), schema = [] :: [{atom(), [{atom(), any()}]}]}). @@ -385,8 +386,8 @@ do_transform(OldAttrs, Attrs, Old) -> transform_fun(Module, Name) -> fun(Obj) -> try Module:transform(Obj) - catch E:R -> - StackTrace = erlang:get_stacktrace(), + catch ?EX_RULE(E, R, St) -> + StackTrace = ?EX_STACK(St), ?ERROR_MSG("Failed to transform Mnesia table ~s:~n" "** Record: ~p~n" "** Reason: ~p~n" diff --git a/src/ejabberd_oauth.erl b/src/ejabberd_oauth.erl index fbd311335..2913c8ef9 100644 --- a/src/ejabberd_oauth.erl +++ b/src/ejabberd_oauth.erl @@ -5,7 +5,7 @@ %%% Created : 20 Mar 2015 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_oauth_mnesia.erl b/src/ejabberd_oauth_mnesia.erl index 04d5c9958..1c55877eb 100644 --- a/src/ejabberd_oauth_mnesia.erl +++ b/src/ejabberd_oauth_mnesia.erl @@ -5,7 +5,7 @@ %%% Created : 20 Jul 2016 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_oauth_rest.erl b/src/ejabberd_oauth_rest.erl index 151946d30..215766d00 100644 --- a/src/ejabberd_oauth_rest.erl +++ b/src/ejabberd_oauth_rest.erl @@ -5,7 +5,7 @@ %%% Created : 26 Jul 2016 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_oauth_sql.erl b/src/ejabberd_oauth_sql.erl index f8daa51bd..e86e5be9f 100644 --- a/src/ejabberd_oauth_sql.erl +++ b/src/ejabberd_oauth_sql.erl @@ -5,7 +5,7 @@ %%% Created : 27 Jul 2016 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 541fcad8b..02b79ed4d 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -5,7 +5,7 @@ %%% Created : 17 Jul 2008 by Pablo Polvorin <pablo.polvorin@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 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,15 +166,10 @@ export_users([], _Server, _Fd) -> export_user(User, Server, Fd) -> Password = ejabberd_auth:get_password_s(User, Server), LServer = jid:nameprep(Server), - PasswordFormat = ejabberd_auth:password_format(LServer), - Pass = case Password of - {_,_,_,_} -> - case PasswordFormat of - scram -> format_scram_password(Password); - _ -> <<"">> - end; - _ -> Password - end, + Pass = case ejabberd_auth:password_format(LServer) of + scram -> format_scram_password(Password); + _ -> Password + end, Els = get_offline(User, Server) ++ get_vcard(User, Server) ++ get_privacy(User, Server) ++ @@ -186,7 +181,8 @@ export_user(User, Server, Fd) -> {<<"password">>, Pass}], children = Els})). -format_scram_password({StoredKey, ServerKey, Salt, IterationCount}) -> +format_scram_password(#scram{storedkey = StoredKey, serverkey = ServerKey, + salt = Salt, iterationcount = IterationCount}) -> StoredKeyB64 = base64:encode(StoredKey), ServerKeyB64 = base64:encode(ServerKey), SaltB64 = base64:encode(Salt), diff --git a/src/ejabberd_pkix.erl b/src/ejabberd_pkix.erl index 2005ffdfa..39b69d033 100644 --- a/src/ejabberd_pkix.erl +++ b/src/ejabberd_pkix.erl @@ -3,7 +3,7 @@ %%% Created : 4 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl index 2b69258e5..c6f5536d7 100644 --- a/src/ejabberd_rdbms.erl +++ b/src/ejabberd_rdbms.erl @@ -5,7 +5,7 @@ %%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -98,7 +98,10 @@ stop_host(Host) -> -spec reload_host(binary()) -> ok. reload_host(Host) -> - ejabberd_sql_sup:reload(Host). + case needs_sql(Host) of + {true, _} -> ejabberd_sql_sup:reload(Host); + false -> ok + end. %% Returns {true, App} if we have configured sql for the given host needs_sql(Host) -> diff --git a/src/ejabberd_redis.erl b/src/ejabberd_redis.erl index 857bece0e..3fa3f37d2 100644 --- a/src/ejabberd_redis.erl +++ b/src/ejabberd_redis.erl @@ -4,7 +4,7 @@ %%% Created : 8 May 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -50,6 +50,7 @@ -define(CALL_TIMEOUT, 60*1000). %% 60 seconds -include("logger.hrl"). +-include("ejabberd_stacktrace.hrl"). -record(state, {connection :: pid() | undefined, num :: pos_integer(), @@ -106,9 +107,9 @@ multi(F) -> {error, _} = Err -> Err; Result -> get_result(Result) end - catch E:R -> + catch ?EX_RULE(E, R, St) -> erlang:erase(?TR_STACK), - erlang:raise(E, R, erlang:get_stacktrace()) + erlang:raise(E, R, ?EX_STACK(St)) end; _ -> erlang:error(nested_transaction) diff --git a/src/ejabberd_redis_sup.erl b/src/ejabberd_redis_sup.erl index bbcd11449..f34a96655 100644 --- a/src/ejabberd_redis_sup.erl +++ b/src/ejabberd_redis_sup.erl @@ -3,7 +3,7 @@ %%% Created : 6 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_regexp.erl b/src/ejabberd_regexp.erl index 284797529..c454835a9 100644 --- a/src/ejabberd_regexp.erl +++ b/src/ejabberd_regexp.erl @@ -5,7 +5,7 @@ %%% Created : 8 Dec 2011 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_riak.erl b/src/ejabberd_riak.erl index 54c84d543..a86ac06d3 100644 --- a/src/ejabberd_riak.erl +++ b/src/ejabberd_riak.erl @@ -5,7 +5,7 @@ %%% Created : 29 Dec 2011 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl index 950acbd9e..2598297b9 100644 --- a/src/ejabberd_riak_sup.erl +++ b/src/ejabberd_riak_sup.erl @@ -5,7 +5,7 @@ %%% Created : 29 Dec 2011 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index bd9a87ce2..12baed5ee 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -5,7 +5,7 @@ %%% Created : 27 Nov 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -71,6 +71,7 @@ -include("logger.hrl"). -include("ejabberd_router.hrl"). -include("xmpp.hrl"). +-include("ejabberd_stacktrace.hrl"). -callback init() -> any(). -callback register_route(binary(), binary(), local_hint(), @@ -90,10 +91,9 @@ start_link() -> -spec route(stanza()) -> ok. route(Packet) -> try do_route(Packet) - catch E:R -> - St = erlang:get_stacktrace(), + catch ?EX_RULE(E, R, St) -> ?ERROR_MSG("failed to route packet:~n~s~nReason = ~p", - [xmpp:pp(Packet), {E, {R, St}}]) + [xmpp:pp(Packet), {E, {R, ?EX_STACK(St)}}]) end. -spec route(jid(), jid(), xmlel() | stanza()) -> ok. diff --git a/src/ejabberd_router_mnesia.erl b/src/ejabberd_router_mnesia.erl index a97874bcd..03fbe495f 100644 --- a/src/ejabberd_router_mnesia.erl +++ b/src/ejabberd_router_mnesia.erl @@ -2,7 +2,7 @@ %%% Created : 11 Jan 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_router_multicast.erl b/src/ejabberd_router_multicast.erl index c95c18882..6dbaeb41a 100644 --- a/src/ejabberd_router_multicast.erl +++ b/src/ejabberd_router_multicast.erl @@ -5,7 +5,7 @@ %%% Created : 11 Aug 2007 by Badlop <badlop@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_router_redis.erl b/src/ejabberd_router_redis.erl index 706a6b4fe..cafb05b13 100644 --- a/src/ejabberd_router_redis.erl +++ b/src/ejabberd_router_redis.erl @@ -3,7 +3,7 @@ %%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_router_riak.erl b/src/ejabberd_router_riak.erl index b330f201d..20346c369 100644 --- a/src/ejabberd_router_riak.erl +++ b/src/ejabberd_router_riak.erl @@ -3,7 +3,7 @@ %%% Created : 15 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_router_sql.erl b/src/ejabberd_router_sql.erl index edf06dfe0..bc3ef52ef 100644 --- a/src/ejabberd_router_sql.erl +++ b/src/ejabberd_router_sql.erl @@ -3,7 +3,7 @@ %%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -32,6 +32,7 @@ -include("logger.hrl"). -include("ejabberd_sql_pt.hrl"). -include("ejabberd_router.hrl"). +-include("ejabberd_stacktrace.hrl"). %%%=================================================================== %%% API @@ -121,12 +122,11 @@ row_to_route(Domain, {ServerHost, NodeS, PidS, LocalHintS} = Row) -> local_hint = dec_local_hint(LocalHintS)}] catch _:{bad_node, _} -> []; - E:R -> - St = erlang:get_stacktrace(), + ?EX_RULE(E, R, St) -> ?ERROR_MSG("failed to decode row from 'route' table:~n" "Row = ~p~n" "Domain = ~s~n" "Reason = ~p", - [Row, Domain, {E, {R, St}}]), + [Row, Domain, {E, {R, ?EX_STACK(St)}}]), [] end. diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index a33d477e5..4b1881199 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -5,7 +5,7 @@ %%% Created : 7 Dec 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -55,12 +55,10 @@ transform_options/1, opt_type/1]). -include("logger.hrl"). - -include("xmpp.hrl"). - -include("ejabberd_commands.hrl"). - -include_lib("public_key/include/public_key.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(PKIXEXPLICIT, 'OTP-PUB-KEY'). @@ -94,10 +92,9 @@ start_link() -> route(Packet) -> try do_route(Packet) - catch E:R -> - St = erlang:get_stacktrace(), + catch ?EX_RULE(E, R, St) -> ?ERROR_MSG("failed to route packet:~n~s~nReason = ~p", - [xmpp:pp(Packet), {E, {R, St}}]) + [xmpp:pp(Packet), {E, {R, ?EX_STACK(St)}}]) end. clean_temporarily_blocked_table() -> diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 3ceb9c058..db7655ef8 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -2,7 +2,7 @@ %%% Created : 12 Dec 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index db8f3d0a3..d940284ef 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -2,7 +2,7 @@ %%% Created : 16 Dec 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 0f40822b7..c2fa2b8c0 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -2,7 +2,7 @@ %%% Created : 11 Dec 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_shaper.erl b/src/ejabberd_shaper.erl index e42cb4121..cad04986c 100644 --- a/src/ejabberd_shaper.erl +++ b/src/ejabberd_shaper.erl @@ -5,7 +5,7 @@ %%% Created : 9 Feb 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sip.erl b/src/ejabberd_sip.erl index f9061edbe..8f6aed55c 100644 --- a/src/ejabberd_sip.erl +++ b/src/ejabberd_sip.erl @@ -5,7 +5,7 @@ %%% Created : 30 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2013-2018 ProcessOne +%%% ejabberd, Copyright (C) 2013-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index b8c85e9e8..165a750db 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -5,7 +5,7 @@ %%% Created : 24 Nov 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -91,6 +91,7 @@ -include("ejabberd_commands.hrl"). -include("ejabberd_sm.hrl"). +-include("ejabberd_stacktrace.hrl"). -callback init() -> ok | {error, any()}. -callback set_session(#session{}) -> ok | {error, any()}. @@ -141,11 +142,10 @@ route(Packet) -> ?DEBUG("hook dropped stanza:~n~s", [xmpp:pp(Packet)]); Packet1 -> try do_route(Packet1), ok - catch E:R -> - St = erlang:get_stacktrace(), + catch ?EX_RULE(E, R, St) -> ?ERROR_MSG("failed to route packet:~n~s~nReason = ~p", [xmpp:pp(Packet1), - {E, {R, St}}]) + {E, {R, ?EX_STACK(St)}}]) end end. diff --git a/src/ejabberd_sm_mnesia.erl b/src/ejabberd_sm_mnesia.erl index 43b49202e..5e36a3d8a 100644 --- a/src/ejabberd_sm_mnesia.erl +++ b/src/ejabberd_sm_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 9 Mar 2015 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sm_redis.erl b/src/ejabberd_sm_redis.erl index a93be86bb..e4bab3902 100644 --- a/src/ejabberd_sm_redis.erl +++ b/src/ejabberd_sm_redis.erl @@ -4,7 +4,7 @@ %%% Created : 11 Mar 2015 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sm_riak.erl b/src/ejabberd_sm_riak.erl index a8150d938..36c936976 100644 --- a/src/ejabberd_sm_riak.erl +++ b/src/ejabberd_sm_riak.erl @@ -3,7 +3,7 @@ %%% Created : 15 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sm_sql.erl b/src/ejabberd_sm_sql.erl index bdc32a27c..8c3efc9b3 100644 --- a/src/ejabberd_sm_sql.erl +++ b/src/ejabberd_sm_sql.erl @@ -4,7 +4,7 @@ %%% Created : 9 Mar 2015 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sql.erl b/src/ejabberd_sql.erl index 9e088f211..2d9c64187 100644 --- a/src/ejabberd_sql.erl +++ b/src/ejabberd_sql.erl @@ -5,7 +5,7 @@ %%% Created : 8 Dec 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -69,6 +69,7 @@ -include("logger.hrl"). -include("ejabberd_sql_pt.hrl"). +-include("ejabberd_stacktrace.hrl"). -record(state, {db_ref = self() :: pid(), @@ -516,24 +517,26 @@ outer_transaction(F, NRestarts, _Reason) -> end, sql_query_internal([<<"begin;">>]), put(?NESTING_KEY, PreviousNestingLevel + 1), - Result = (catch F()), - put(?NESTING_KEY, PreviousNestingLevel), - case Result of - {aborted, Reason} when NRestarts > 0 -> - sql_query_internal([<<"rollback;">>]), - outer_transaction(F, NRestarts - 1, Reason); - {aborted, Reason} when NRestarts =:= 0 -> - ?ERROR_MSG("SQL transaction restarts exceeded~n** " - "Restarts: ~p~n** Last abort reason: " - "~p~n** Stacktrace: ~p~n** When State " - "== ~p", - [?MAX_TRANSACTION_RESTARTS, Reason, - erlang:get_stacktrace(), get(?STATE_KEY)]), - sql_query_internal([<<"rollback;">>]), - {aborted, Reason}; - {'EXIT', Reason} -> - sql_query_internal([<<"rollback;">>]), {aborted, Reason}; - Res -> sql_query_internal([<<"commit;">>]), {atomic, Res} + try F() of + Res -> + sql_query_internal([<<"commit;">>]), + {atomic, Res} + catch + ?EX_RULE(throw, {aborted, Reason}, _) when NRestarts > 0 -> + sql_query_internal([<<"rollback;">>]), + outer_transaction(F, NRestarts - 1, Reason); + ?EX_RULE(throw, {aborted, Reason}, Stack) when NRestarts =:= 0 -> + ?ERROR_MSG("SQL transaction restarts exceeded~n** " + "Restarts: ~p~n** Last abort reason: " + "~p~n** Stacktrace: ~p~n** When State " + "== ~p", + [?MAX_TRANSACTION_RESTARTS, Reason, + ?EX_STACK(Stack), get(?STATE_KEY)]), + sql_query_internal([<<"rollback;">>]), + {aborted, Reason}; + ?EX_RULE(exit, Reason, _) -> + sql_query_internal([<<"rollback;">>]), + {aborted, Reason} end. execute_bloc(F) -> @@ -599,10 +602,9 @@ sql_query_internal(#sql_query{} = Query) -> {error, <<"killed">>}; exit:{normal, _} -> {error, <<"terminated unexpectedly">>}; - Class:Reason -> - ST = erlang:get_stacktrace(), + ?EX_RULE(Class, Reason, Stack) -> ?ERROR_MSG("Internal error while processing SQL query: ~p", - [{Class, Reason, ST}]), + [{Class, Reason, ?EX_STACK(Stack)}]), {error, <<"internal error">>} end, check_error(Res, Query); @@ -737,12 +739,11 @@ sql_query_format_res({selected, _, Rows}, SQLQuery) -> try [(SQLQuery#sql_query.format_res)(Row)] catch - Class:Reason -> - ST = erlang:get_stacktrace(), + ?EX_RULE(Class, Reason, Stack) -> ?ERROR_MSG("Error while processing " "SQL query result: ~p~n" "row: ~p", - [{Class, Reason, ST}, Row]), + [{Class, Reason, ?EX_STACK(Stack)}, Row]), [] end end, Rows), @@ -1070,9 +1071,9 @@ init_mssql(Host) -> case filelib:ensure_dir(freetds_config()) of ok -> try - ok = file:write_file(freetds_config(), FreeTDS, [append]), - ok = file:write_file(odbcinst_config(), ODBCINST), - ok = file:write_file(odbc_config(), ODBCINI, [append]), + ok = write_file_if_new(freetds_config(), FreeTDS), + ok = write_file_if_new(odbcinst_config(), ODBCINST), + ok = write_file_if_new(odbc_config(), ODBCINI), os:putenv("ODBCSYSINI", tmp_dir()), os:putenv("FREETDS", freetds_config()), os:putenv("FREETDSCONF", freetds_config()), @@ -1088,6 +1089,12 @@ init_mssql(Host) -> Err end. +write_file_if_new(File, Payload) -> + case filelib:is_file(File) of + true -> ok; + false -> file:write_file(File, Payload) + end. + tmp_dir() -> case os:type() of {win32, _} -> filename:join([os:getenv("HOME"), "conf"]); diff --git a/src/ejabberd_sql_pt.erl b/src/ejabberd_sql_pt.erl index 1f6134d07..0ae04c64d 100644 --- a/src/ejabberd_sql_pt.erl +++ b/src/ejabberd_sql_pt.erl @@ -5,7 +5,7 @@ %%% Created : 20 Jan 2016 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sql_sup.erl b/src/ejabberd_sql_sup.erl index ee889bd21..f16c23a00 100644 --- a/src/ejabberd_sql_sup.erl +++ b/src/ejabberd_sql_sup.erl @@ -5,7 +5,7 @@ %%% Created : 22 Dec 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index 1e00c85f5..24f3e696b 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -5,7 +5,7 @@ %%% Created : 8 May 2014 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2013-2018 ProcessOne +%%% ejabberd, Copyright (C) 2013-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index 86a14c78a..edf15e438 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -5,7 +5,7 @@ %%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index cf50209fb..59ba6f806 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -5,7 +5,7 @@ %%% Created : 21 Mar 2007 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_tmp_sup.erl b/src/ejabberd_tmp_sup.erl index aa8a7e0f2..8f3e1f06c 100644 --- a/src/ejabberd_tmp_sup.erl +++ b/src/ejabberd_tmp_sup.erl @@ -5,7 +5,7 @@ %%% Created : 18 Jul 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_update.erl b/src/ejabberd_update.erl index 4c360011f..c7aa652c1 100644 --- a/src/ejabberd_update.erl +++ b/src/ejabberd_update.erl @@ -5,7 +5,7 @@ %%% Created : 27 Jan 2006 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_web.erl b/src/ejabberd_web.erl index a0291fc6f..3025dc146 100644 --- a/src/ejabberd_web.erl +++ b/src/ejabberd_web.erl @@ -6,7 +6,7 @@ %%% Created : 28 Feb 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 03b11c9f6..4c4501436 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -5,7 +5,7 @@ %%% Created : 9 Apr 2004 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -254,6 +254,7 @@ get_auth_admin(Auth, HostHTTP, RPath, Method) -> catch _:{bad_jid, _} -> {unauthorized, <<"badformed-jid">>} end; + invalid -> {unauthorized, <<"no-auth-provided">>}; undefined -> {unauthorized, <<"no-auth-provided">>} end. @@ -305,7 +306,7 @@ make_xhtml(Els, Host, Node, Lang, JID) -> #xmlel{name = <<"script">>, attrs = [{<<"src">>, - <<Base/binary, "/additions.js">>}, + <<Base/binary, "additions.js">>}, {<<"type">>, <<"text/javascript">>}], children = [?C(<<" ">>)]}, #xmlel{name = <<"link">>, @@ -337,7 +338,7 @@ make_xhtml(Els, Host, Node, Lang, JID) -> [?XAE(<<"div">>, [{<<"id">>, <<"copyright">>}], [?XE(<<"p">>, [?AC(<<"https://www.ejabberd.im/">>, <<"ejabberd">>), - ?C(<<" (c) 2002-2018 ">>), + ?C(<<" (c) 2002-2019 ">>), ?AC(<<"https://www.process-one.net/">>, <<"ProcessOne, leader in messaging and push solutions">>)] )])])])]}}. @@ -2380,10 +2381,13 @@ node_modules_parse_query(Host, Node, Modules, Query) -> {ok, Tokens, _} = erl_scan:string(binary_to_list(<<SOpts/binary, ".">>)), {ok, Opts} = erl_parse:parse_term(Tokens), + NewMods = lists:keystore(Module, 1, ejabberd_config:get_option(modules), {Module, Opts}), ejabberd_cluster:call(Node, gen_mod, stop_module, [Host, Module]), + ejabberd_cluster:call(Node, ejabberd_config, add_option, + [modules, NewMods]), ejabberd_cluster:call(Node, gen_mod, start_module, - [Host, Module, Opts]), + [Host, Module]), throw(submitted); _ -> case lists:keysearch(<<"stop", SModule/binary>>, diff --git a/src/ejabberd_websocket.erl b/src/ejabberd_websocket.erl index 5a329797b..506ff142b 100644 --- a/src/ejabberd_websocket.erl +++ b/src/ejabberd_websocket.erl @@ -33,7 +33,7 @@ %%% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE %%% POSSIBILITY OF SUCH DAMAGE. %%% ========================================================================================================== -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%%---------------------------------------------------------------------- -module(ejabberd_websocket). diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index 11da7f369..cda2864df 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -5,7 +5,7 @@ %%% Created : 21 Aug 2007 by Badlop <badlop@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejd2sql.erl b/src/ejd2sql.erl index 40793f405..546b86879 100644 --- a/src/ejd2sql.erl +++ b/src/ejd2sql.erl @@ -5,7 +5,7 @@ %%% Created : 22 Aug 2005 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/eldap_filter.erl b/src/eldap_filter.erl index 32cb85fd9..7ab634d95 100644 --- a/src/eldap_filter.erl +++ b/src/eldap_filter.erl @@ -6,7 +6,7 @@ %%% Author: Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/eldap_pool.erl b/src/eldap_pool.erl index 3e8e35b84..b6421c230 100644 --- a/src/eldap_pool.erl +++ b/src/eldap_pool.erl @@ -5,7 +5,7 @@ %%% Created : 12 Nov 2006 by Evgeniy Khramtsov <xram@jabber.ru> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/eldap_utils.erl b/src/eldap_utils.erl index d757aa31b..47e18aac3 100644 --- a/src/eldap_utils.erl +++ b/src/eldap_utils.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Mickael Remond <mremond@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/elixir_logger_backend.erl b/src/elixir_logger_backend.erl index bbe43a2d3..16d7f954c 100644 --- a/src/elixir_logger_backend.erl +++ b/src/elixir_logger_backend.erl @@ -5,7 +5,7 @@ %%% Created : 9 March 2016 by Mickael Remond <mremond@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 02165bea8..0d734e08c 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -5,7 +5,7 @@ %%% Created : 19 Feb 2015 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2006-2018 ProcessOne +%%% ejabberd, Copyright (C) 2006-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/extauth.erl b/src/extauth.erl index f77d3d2cc..ace340f72 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -2,7 +2,7 @@ %%% Created : 7 May 2018 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/extauth_sup.erl b/src/extauth_sup.erl index c9dc0cdff..f4220fa81 100644 --- a/src/extauth_sup.erl +++ b/src/extauth_sup.erl @@ -2,7 +2,7 @@ %%% Created : 7 May 2018 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl index f6a6744fd..38aa32e36 100644 --- a/src/gen_iq_handler.erl +++ b/src/gen_iq_handler.erl @@ -5,7 +5,7 @@ %%% Created : 22 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 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,6 +40,7 @@ -include("logger.hrl"). -include("xmpp.hrl"). -include("translate.hrl"). +-include("ejabberd_stacktrace.hrl"). -type component() :: ejabberd_sm | ejabberd_local. @@ -113,10 +114,9 @@ process_iq(_Host, Module, Function, IQ) -> ejabberd_router:route(ResIQ); ignore -> ok - catch E:R -> - St = erlang:get_stacktrace(), + catch ?EX_RULE(E, R, St) -> ?ERROR_MSG("failed to process iq:~n~s~nReason = ~p", - [xmpp:pp(IQ), {E, {R, St}}]), + [xmpp:pp(IQ), {E, {R, ?EX_STACK(St)}}]), Txt = <<"Module failed to handle the query">>, Err = xmpp:err_internal_server_error(Txt, IQ#iq.lang), ejabberd_router:route_error(IQ, Err) diff --git a/src/gen_mod.erl b/src/gen_mod.erl index cf107f7b0..cec3ddb24 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -5,7 +5,7 @@ %%% Created : 24 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -58,6 +58,7 @@ -include("logger.hrl"). -include_lib("stdlib/include/ms_transform.hrl"). +-include("ejabberd_stacktrace.hrl"). -record(ejabberd_module, {module_host = {undefined, <<"">>} :: {atom(), binary()}, @@ -217,8 +218,8 @@ start_module(Host, Module, Opts0, Order, NeedValidation) -> {ok, Pid} when is_pid(Pid) -> {ok, Pid}; Err -> erlang:error({bad_return, Module, Err}) end - catch Class:Reason -> - StackTrace = erlang:get_stacktrace(), + catch ?EX_RULE(Class, Reason, Stack) -> + StackTrace = ?EX_STACK(Stack), ets:delete(ejabberd_modules, {Module, Host}), ErrorText = format_module_error( Module, start, 2, @@ -282,8 +283,8 @@ reload_module(Host, Module, NewOpts, OldOpts, Order) -> {ok, Pid} when is_pid(Pid) -> {ok, Pid}; Err -> erlang:error({bad_return, Module, Err}) end - catch Class:Reason -> - StackTrace = erlang:get_stacktrace(), + catch ?EX_RULE(Class, Reason, Stack) -> + StackTrace = ?EX_STACK(Stack), ErrorText = format_module_error( Module, reload, 3, NewOpts, Class, Reason, @@ -936,8 +937,12 @@ opt_type(modules) -> fun(Mods) -> lists:map( fun({M, A}) when is_atom(M) -> - true = is_opt_list(A), - {M, A} + case is_opt_list(A) of + true -> {M, A}; + false -> + ?ERROR_MSG("Malformed configuration format of module ~s", [M]), + erlang:error(badarg) + end end, Mods) end; opt_type(_) -> [modules]. diff --git a/src/gen_pubsub_node.erl b/src/gen_pubsub_node.erl index b54cc569b..624b2fd07 100644 --- a/src/gen_pubsub_node.erl +++ b/src/gen_pubsub_node.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/gen_pubsub_nodetree.erl b/src/gen_pubsub_nodetree.erl index bcf52855c..aba78a89a 100644 --- a/src/gen_pubsub_nodetree.erl +++ b/src/gen_pubsub_nodetree.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/jd2ejd.erl b/src/jd2ejd.erl index 394a5a471..0122a7f2d 100644 --- a/src/jd2ejd.erl +++ b/src/jd2ejd.erl @@ -5,7 +5,7 @@ %%% Created : 2 Feb 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/misc.erl b/src/misc.erl index 5aa281565..3c5407cd0 100644 --- a/src/misc.erl +++ b/src/misc.erl @@ -8,7 +8,7 @@ %%% Created : 30 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index 9071ca817..c77d6a047 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -5,7 +5,7 @@ %%% Created : 15 Nov 2005 by Magnus Henoch <henoch@dtek.chalmers.se> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 367196a07..4655ac226 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -5,7 +5,7 @@ %%% Created : 10 Aug 2008 by Badlop <badlop@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -987,11 +987,15 @@ get_status_list(Host, Status_required) -> apply(Fstatus, [Status, Status_required])]. connected_users_info() -> - lists:map( + lists:filtermap( fun({U, S, R}) -> - Info = user_session_info(U, S, R), - Jid = jid:encode(jid:make(U, S, R)), - erlang:insert_element(1, Info, Jid) + case user_session_info(U, S, R) of + offline -> + false; + Info -> + Jid = jid:encode(jid:make(U, S, R)), + {true, erlang:insert_element(1, Info, Jid)} + end end, ejabberd_sm:dirty_get_sessions_list()). @@ -1054,23 +1058,31 @@ set_presence(User, Host, Resource, Type, Show, Status, Priority0) -> ejabberd_c2s:set_presence(Ref, Pres). user_sessions_info(User, Host) -> - [user_session_info(User, Host, Resource) || - Resource <- ejabberd_sm:get_user_resources(User, Host)]. + lists:filtermap(fun(Resource) -> + case user_session_info(User, Host, Resource) of + offline -> false; + Info -> {true, Info} + end + end, ejabberd_sm:get_user_resources(User, Host)). user_session_info(User, Host, Resource) -> CurrentSec = calendar:datetime_to_gregorian_seconds({date(), time()}), - Info = ejabberd_sm:get_user_info(User, Host, Resource), - Now = proplists:get_value(ts, Info), - Pid = proplists:get_value(pid, Info), - {_U, _Resource, Status, StatusText} = get_presence(Pid), - Priority = proplists:get_value(priority, Info), - Conn = proplists:get_value(conn, Info), - {Ip, Port} = proplists:get_value(ip, Info), - IPS = inet_parse:ntoa(Ip), - NodeS = atom_to_list(node(Pid)), - Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds( - calendar:now_to_local_time(Now)), - {atom_to_list(Conn), IPS, Port, num_prio(Priority), NodeS, Uptime, Status, Resource, StatusText}. + case ejabberd_sm:get_user_info(User, Host, Resource) of + offline -> + offline; + Info -> + Now = proplists:get_value(ts, Info), + Pid = proplists:get_value(pid, Info), + {_U, _Resource, Status, StatusText} = get_presence(Pid), + Priority = proplists:get_value(priority, Info), + Conn = proplists:get_value(conn, Info), + {Ip, Port} = proplists:get_value(ip, Info), + IPS = inet_parse:ntoa(Ip), + NodeS = atom_to_list(node(Pid)), + Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds( + calendar:now_to_local_time(Now)), + {atom_to_list(Conn), IPS, Port, num_prio(Priority), NodeS, Uptime, Status, Resource, StatusText} + end. %%% diff --git a/src/mod_admin_update_sql.erl b/src/mod_admin_update_sql.erl index 3c036f341..0212dab25 100644 --- a/src/mod_admin_update_sql.erl +++ b/src/mod_admin_update_sql.erl @@ -5,7 +5,7 @@ %%% Created : 9 Aug 2017 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_announce.erl b/src/mod_announce.erl index b8ca970c9..c8d3e9e74 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -5,7 +5,7 @@ %%% Created : 11 Aug 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_announce_mnesia.erl b/src/mod_announce_mnesia.erl index f3b8aef7c..ea7c54f36 100644 --- a/src/mod_announce_mnesia.erl +++ b/src/mod_announce_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_announce_riak.erl b/src/mod_announce_riak.erl index 55959b58b..1d2435151 100644 --- a/src/mod_announce_riak.erl +++ b/src/mod_announce_riak.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_announce_sql.erl b/src/mod_announce_sql.erl index c4f1ba86f..60c3edcf6 100644 --- a/src/mod_announce_sql.erl +++ b/src/mod_announce_sql.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_avatar.erl b/src/mod_avatar.erl index d5f24e75d..e706a23c3 100644 --- a/src/mod_avatar.erl +++ b/src/mod_avatar.erl @@ -3,7 +3,7 @@ %%% Created : 13 Sep 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_block_strangers.erl b/src/mod_block_strangers.erl index 0496245b0..486bea7fd 100644 --- a/src/mod_block_strangers.erl +++ b/src/mod_block_strangers.erl @@ -5,7 +5,7 @@ %%% Created : 25 Dec 2016 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index d428e7d28..b1856c937 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -5,7 +5,7 @@ %%% Created : 24 Aug 2008 by Stephan Maka <stephan@spaceboyz.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_bosh.erl b/src/mod_bosh.erl index a393597eb..03bdc6e15 100644 --- a/src/mod_bosh.erl +++ b/src/mod_bosh.erl @@ -7,7 +7,7 @@ %%% Created : 20 Jul 2011 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_bosh_mnesia.erl b/src/mod_bosh_mnesia.erl index fdd7225ca..a0da1867f 100644 --- a/src/mod_bosh_mnesia.erl +++ b/src/mod_bosh_mnesia.erl @@ -2,7 +2,7 @@ %%% Created : 12 Jan 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_bosh_redis.erl b/src/mod_bosh_redis.erl index 7c7cf6578..b94322194 100644 --- a/src/mod_bosh_redis.erl +++ b/src/mod_bosh_redis.erl @@ -5,7 +5,7 @@ %%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2017-2018 ProcessOne +%%% ejabberd, Copyright (C) 2017-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_bosh_riak.erl b/src/mod_bosh_riak.erl index df376f3d1..7ebd1bd6f 100644 --- a/src/mod_bosh_riak.erl +++ b/src/mod_bosh_riak.erl @@ -3,7 +3,7 @@ %%% Created : 15 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_bosh_sql.erl b/src/mod_bosh_sql.erl index c32714c87..4ec65e779 100644 --- a/src/mod_bosh_sql.erl +++ b/src/mod_bosh_sql.erl @@ -5,7 +5,7 @@ %%% Created : 28 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2017-2018 ProcessOne +%%% ejabberd, Copyright (C) 2017-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 3d2b52dac..96b44cd68 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -5,7 +5,7 @@ %%% Created : 7 Oct 2006 by Magnus Henoch <henoch@dtek.chalmers.se> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_caps_mnesia.erl b/src/mod_caps_mnesia.erl index c44834fc5..9855b1fc2 100644 --- a/src/mod_caps_mnesia.erl +++ b/src/mod_caps_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_caps_riak.erl b/src/mod_caps_riak.erl index 1d94ceee4..37a29ff7f 100644 --- a/src/mod_caps_riak.erl +++ b/src/mod_caps_riak.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_caps_sql.erl b/src/mod_caps_sql.erl index 01da67158..b0829156e 100644 --- a/src/mod_caps_sql.erl +++ b/src/mod_caps_sql.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index e1f82e872..72c098570 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -7,7 +7,7 @@ %%% {mod_carboncopy, []} %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 156fde726..162d47aa2 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -5,7 +5,7 @@ %%% Created : 11 Sep 2014 by Holger Weiss <holger@zedat.fu-berlin.de> %%% %%% -%%% ejabberd, Copyright (C) 2014-2018 ProcessOne +%%% ejabberd, Copyright (C) 2014-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_configure.erl b/src/mod_configure.erl index a52376504..aa431e285 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -5,7 +5,7 @@ %%% Created : 19 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_delegation.erl b/src/mod_delegation.erl index 45e44c497..532463e3a 100644 --- a/src/mod_delegation.erl +++ b/src/mod_delegation.erl @@ -4,7 +4,7 @@ %%% Purpose : XEP-0355: Namespace Delegation %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 3b394b8dd..f0d23a0ca 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -5,7 +5,7 @@ %%% Created : 1 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_echo.erl b/src/mod_echo.erl index 26cf60611..eaa630ac7 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index 11004efef..141462566 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -5,7 +5,7 @@ %%% Created : 15 Aug 2014 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2014-2018 ProcessOne +%%% ejabberd, Copyright (C) 2014-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl index 3fb0d5981..8cc80982a 100644 --- a/src/mod_http_api.erl +++ b/src/mod_http_api.erl @@ -5,7 +5,7 @@ %%% Created : 15 Sep 2014 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -80,6 +80,7 @@ -include("xmpp.hrl"). -include("logger.hrl"). -include("ejabberd_http.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(DEFAULT_API_VERSION, 0). @@ -136,39 +137,43 @@ depends(_Host, _Opts) -> %% basic auth %% ---------- -extract_auth(#request{auth = HTTPAuth, ip = {IP, _}}) -> +extract_auth(#request{auth = HTTPAuth, ip = {IP, _}, opts = Opts}) -> Info = case HTTPAuth of - {SJID, Pass} -> - try jid:decode(SJID) of + {SJID, Pass} -> + try jid:decode(SJID) of #jid{luser = User, lserver = Server} -> - case ejabberd_auth:check_password(User, <<"">>, Server, Pass) of + case ejabberd_auth:check_password(User, <<"">>, Server, Pass) of true -> #{usr => {User, Server, <<"">>}, caller_server => Server}; false -> {error, invalid_auth} - end - catch _:{bad_jid, _} -> - {error, invalid_auth} - end; - {oauth, Token, _} -> + end + catch _:{bad_jid, _} -> + {error, invalid_auth} + end; + {oauth, Token, _} -> case ejabberd_oauth:check_token(Token) of {ok, {U, S}, Scope} -> #{usr => {U, S, <<"">>}, oauth_scope => Scope, caller_server => S}; {false, Reason} -> {error, Reason} - end; - _ -> + end; + invalid -> + {error, invalid_auth}; + _ -> #{} - end, + end, case Info of Map when is_map(Map) -> - Map#{caller_module => ?MODULE, ip => IP}; + Tag = proplists:get_value(tag, Opts, <<>>), + Map#{caller_module => ?MODULE, ip => IP, tag => Tag}; _ -> ?DEBUG("Invalid auth data: ~p", [Info]), Info end; -extract_auth(#request{ip = IP}) -> - #{ip => IP, caller_module => ?MODULE}. +extract_auth(#request{ip = IP, opts = Opts}) -> + Tag = proplists:get_value(tag, Opts, <<>>), + #{ip => IP, caller_module => ?MODULE, tag => Tag}. %% ------------------ %% command processing @@ -192,9 +197,8 @@ process([Call], #request{method = 'POST', data = Data, ip = IPPort} = Req) -> _:{error,{_,invalid_json}} = _Err -> ?DEBUG("Bad Request: ~p", [_Err]), badrequest_response(<<"Invalid JSON input">>); - _:_Error -> - St = erlang:get_stacktrace(), - ?DEBUG("Bad Request: ~p ~p", [_Error, St]), + ?EX_RULE(_Class, _Error, Stack) -> + ?DEBUG("Bad Request: ~p ~p", [_Error, ?EX_STACK(Stack)]), badrequest_response() end; process([Call], #request{method = 'GET', q = Data, ip = {IP, _}} = Req) -> @@ -210,9 +214,8 @@ process([Call], #request{method = 'GET', q = Data, ip = {IP, _}} = Req) -> %% TODO We need to refactor to remove redundant error return formatting throw:{error, unknown_command} -> json_format({404, 44, <<"Command not found.">>}); - _:_Error -> - St = erlang:get_stacktrace(), - ?DEBUG("Bad Request: ~p ~p", [_Error, St]), + ?EX_RULE(_, _Error, Stack) -> + ?DEBUG("Bad Request: ~p ~p", [_Error, ?EX_STACK(Stack)]), badrequest_response() end; process([_Call], #request{method = 'OPTIONS', data = <<>>}) -> @@ -302,9 +305,8 @@ handle(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) -> {400, misc:atom_to_binary(Error)}; throw:Msg when is_list(Msg); is_binary(Msg) -> {400, iolist_to_binary(Msg)}; - _Error -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("REST API Error: ~p ~p", [_Error, St]), + ?EX_RULE(Class, Error, Stack) -> + ?ERROR_MSG("REST API Error: ~p:~p ~p", [Class, Error, ?EX_STACK(Stack)]), {500, <<"internal_error">>} end; {error, Msg} -> @@ -355,7 +357,10 @@ format_args(Args, ArgsFormat) -> {Args, []}, ArgsFormat), case ArgsRemaining of [] -> R; - L when is_list(L) -> exit({additional_unused_args, L}) + L when is_list(L) -> + throw({invalid_parameter, + io_lib:format("Request have unknown arguments: ~w", + [[N || {N, _} <- L]])}) end. format_arg({Elements}, diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index 47cf31bce..d34d7193e 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -5,7 +5,7 @@ %%% Created : %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index fe3379f16..66df9f91d 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -5,7 +5,7 @@ %%% Created : 20 Aug 2015 by Holger Weiss <holger@zedat.fu-berlin.de> %%% %%% -%%% ejabberd, Copyright (C) 2015-2018 ProcessOne +%%% ejabberd, Copyright (C) 2015-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index f27c0222e..10f7831bd 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -5,7 +5,7 @@ %%% Created : 15 Oct 2015 by Holger Weiss <holger@zedat.fu-berlin.de> %%% %%% -%%% ejabberd, Copyright (C) 2015-2018 ProcessOne +%%% ejabberd, Copyright (C) 2015-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_last.erl b/src/mod_last.erl index f0651b054..dcae1c27e 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -5,7 +5,7 @@ %%% Created : 24 Oct 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_last_mnesia.erl b/src/mod_last_mnesia.erl index de5e448d3..d8d5296f3 100644 --- a/src/mod_last_mnesia.erl +++ b/src/mod_last_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_last_riak.erl b/src/mod_last_riak.erl index ca41a6a06..cd5dd43d4 100644 --- a/src/mod_last_riak.erl +++ b/src/mod_last_riak.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_last_sql.erl b/src/mod_last_sql.erl index e8168f3f2..85f3e3895 100644 --- a/src/mod_last_sql.erl +++ b/src/mod_last_sql.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_legacy_auth.erl b/src/mod_legacy_auth.erl index 19b905ad8..c4614d74c 100644 --- a/src/mod_legacy_auth.erl +++ b/src/mod_legacy_auth.erl @@ -2,7 +2,7 @@ %%% Created : 11 Dec 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 32c13c875..f1f481260 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -5,7 +5,7 @@ %%% Created : 4 Jul 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2013-2018 ProcessOne +%%% ejabberd, Copyright (C) 2013-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -41,6 +41,7 @@ delete_old_messages/2, get_commands_spec/0, msg_to_el/4, get_room_config/4, set_room_option/3, offline_message/1, export/1, mod_options/1, remove_mam_for_user_with_peer/3, remove_mam_for_user/2, + is_empty_for_user/2, is_empty_for_room/3, check_create_room/4, process_iq/3, store_mam_message/7, make_id/0]). -include("xmpp.hrl"). @@ -53,6 +54,7 @@ -define(MAX_PAGE_SIZE, 250). -type c2s_state() :: ejabberd_c2s:state(). +-type count() :: non_neg_integer() | undefined. -callback init(binary(), gen_mod:opts()) -> any(). -callback remove_user(binary(), binary()) -> any(). @@ -64,13 +66,16 @@ -callback store(xmlel(), binary(), {binary(), binary()}, chat | groupchat, jid(), binary(), recv | send, integer()) -> ok | any(). -callback write_prefs(binary(), binary(), #archive_prefs{}, binary()) -> ok | any(). --callback get_prefs(binary(), binary()) -> {ok, #archive_prefs{}} | error. +-callback get_prefs(binary(), binary()) -> {ok, #archive_prefs{}} | error | {error, db_failure}. -callback select(binary(), jid(), jid(), mam_query:result(), #rsm_set{} | undefined, chat | groupchat) -> - {[{binary(), non_neg_integer(), xmlel()}], boolean(), non_neg_integer()}. + {[{binary(), non_neg_integer(), xmlel()}], boolean(), count()} | + {error, db_failure}. -callback use_cache(binary()) -> boolean(). -callback cache_nodes(binary()) -> [node()]. -callback remove_from_archive(binary(), binary(), jid() | none) -> ok | {error, any()}. +-callback is_empty_for_user(binary(), binary()) -> boolean(). +-callback is_empty_for_room(binary(), binary(), binary()) -> boolean(). -optional_callbacks([use_cache/1, cache_nodes/1]). @@ -90,44 +95,54 @@ start(Host, Opts) -> ok end, Mod = gen_mod:db_mod(Host, Opts, ?MODULE), - Mod:init(Host, Opts), - init_cache(Mod, Host, Opts), - register_iq_handlers(Host), - ejabberd_hooks:add(sm_receive_packet, Host, ?MODULE, - sm_receive_packet, 50), - ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, - user_receive_packet, 88), - ejabberd_hooks:add(user_send_packet, Host, ?MODULE, - user_send_packet, 88), - ejabberd_hooks:add(user_send_packet, Host, ?MODULE, - user_send_packet_strip_tag, 500), - ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, - offline_message, 50), - ejabberd_hooks:add(muc_filter_message, Host, ?MODULE, - muc_filter_message, 50), - ejabberd_hooks:add(muc_process_iq, Host, ?MODULE, - muc_process_iq, 50), - ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, - disco_sm_features, 50), - ejabberd_hooks:add(remove_user, Host, ?MODULE, - remove_user, 50), - ejabberd_hooks:add(remove_room, Host, ?MODULE, - remove_room, 50), - ejabberd_hooks:add(get_room_config, Host, ?MODULE, - get_room_config, 50), - ejabberd_hooks:add(set_room_option, Host, ?MODULE, - set_room_option, 50), - ejabberd_hooks:add(store_mam_message, Host, ?MODULE, - store_mam_message, 100), - case gen_mod:get_opt(assume_mam_usage, Opts) of - true -> - ejabberd_hooks:add(message_is_archived, Host, ?MODULE, - message_is_archived, 50); - false -> - ok - end, - ejabberd_commands:register_commands(get_commands_spec()), - ok. + case Mod:init(Host, Opts) of + ok -> + init_cache(Mod, Host, Opts), + register_iq_handlers(Host), + ejabberd_hooks:add(sm_receive_packet, Host, ?MODULE, + sm_receive_packet, 50), + ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, + user_receive_packet, 88), + ejabberd_hooks:add(user_send_packet, Host, ?MODULE, + user_send_packet, 88), + ejabberd_hooks:add(user_send_packet, Host, ?MODULE, + user_send_packet_strip_tag, 500), + ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, + offline_message, 50), + ejabberd_hooks:add(muc_filter_message, Host, ?MODULE, + muc_filter_message, 50), + ejabberd_hooks:add(muc_process_iq, Host, ?MODULE, + muc_process_iq, 50), + ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, + disco_sm_features, 50), + ejabberd_hooks:add(remove_user, Host, ?MODULE, + remove_user, 50), + ejabberd_hooks:add(get_room_config, Host, ?MODULE, + get_room_config, 50), + ejabberd_hooks:add(set_room_option, Host, ?MODULE, + set_room_option, 50), + ejabberd_hooks:add(store_mam_message, Host, ?MODULE, + store_mam_message, 100), + case gen_mod:get_opt(assume_mam_usage, Opts) of + true -> + ejabberd_hooks:add(message_is_archived, Host, ?MODULE, + message_is_archived, 50); + false -> + ok + end, + case gen_mod:get_opt(clear_archive_on_room_destroy, Opts) of + true -> + ejabberd_hooks:add(remove_room, Host, ?MODULE, + remove_room, 50); + false -> + ejabberd_hooks:add(check_create_room, Host, ?MODULE, + check_create_room, 50) + end, + ejabberd_commands:register_commands(get_commands_spec()), + ok; + Err -> + Err + end. use_cache(Mod, Host) -> case erlang:function_exported(Mod, use_cache, 2) of @@ -178,8 +193,6 @@ stop(Host) -> disco_sm_features, 50), ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), - ejabberd_hooks:delete(remove_room, Host, ?MODULE, - remove_room, 50), ejabberd_hooks:delete(get_room_config, Host, ?MODULE, get_room_config, 50), ejabberd_hooks:delete(set_room_option, Host, ?MODULE, @@ -193,6 +206,14 @@ stop(Host) -> false -> ok end, + case gen_mod:get_module_opt(Host, ?MODULE, clear_archive_on_room_destroy) of + true -> + ejabberd_hooks:delete(remove_room, Host, ?MODULE, + remove_room, 50); + false -> + ejabberd_hooks:delete(check_create_room, Host, ?MODULE, + check_create_room, 50) + end, case gen_mod:is_loaded_elsewhere(Host, ?MODULE) of false -> ejabberd_commands:unregister_commands(get_commands_spec()); @@ -563,6 +584,24 @@ export(LServer) -> Mod = gen_mod:db_mod(LServer, ?MODULE), Mod:export(LServer). +-spec is_empty_for_user(binary(), binary()) -> boolean(). +is_empty_for_user(User, Server) -> + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + Mod = gen_mod:db_mod(LServer, ?MODULE), + Mod:is_empty_for_user(LUser, LServer). + +-spec is_empty_for_room(binary(), binary(), binary()) -> boolean(). +is_empty_for_room(LServer, Name, Host) -> + LName = jid:nodeprep(Name), + LHost = jid:nameprep(Host), + Mod = gen_mod:db_mod(LServer, ?MODULE), + Mod:is_empty_for_room(LServer, LName, LHost). + +-spec check_create_room(boolean(), binary(), binary(), binary()) -> boolean(). +check_create_room(Acc, ServerHost, RoomID, Host) -> + Acc and is_empty_for_room(ServerHost, RoomID, Host). + %%%=================================================================== %%% Internal functions %%%=================================================================== @@ -603,37 +642,48 @@ process_iq(#iq{from = #jid{luser = LUser, lserver = LServer}, xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang)) end; process_iq(#iq{from = #jid{luser = LUser, lserver = LServer}, - to = #jid{lserver = LServer}, + to = #jid{lserver = LServer}, lang = Lang, type = get, sub_els = [#mam_prefs{xmlns = NS}]} = IQ) -> - Prefs = get_prefs(LUser, LServer), - PrefsEl = prefs_el(Prefs#archive_prefs.default, - Prefs#archive_prefs.always, - Prefs#archive_prefs.never, - NS), - xmpp:make_iq_result(IQ, PrefsEl); + case get_prefs(LUser, LServer) of + {ok, Prefs} -> + PrefsEl = prefs_el(Prefs#archive_prefs.default, + Prefs#archive_prefs.always, + Prefs#archive_prefs.never, + NS), + xmpp:make_iq_result(IQ, PrefsEl); + {error, _} -> + Txt = <<"Database failure">>, + xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang)) + end; process_iq(IQ) -> xmpp:make_error(IQ, xmpp:err_not_allowed()). process_iq(LServer, #iq{from = #jid{luser = LUser}, lang = Lang, sub_els = [SubEl]} = IQ, MsgType) -> - case MsgType of - chat -> - maybe_activate_mam(LUser, LServer); - _ -> - ok - end, - case SubEl of - #mam_query{rsm = #rsm_set{index = I}} when is_integer(I) -> - Txt = <<"Unsupported <index/> element">>, - xmpp:make_error(IQ, xmpp:err_feature_not_implemented(Txt, Lang)); - #mam_query{rsm = RSM, xmlns = NS} -> - case parse_query(SubEl, Lang) of - {ok, Query} -> - NewRSM = limit_max(RSM, NS), - select_and_send(LServer, Query, NewRSM, IQ, MsgType); - {error, Err} -> - xmpp:make_error(IQ, Err) - end + Ret = case MsgType of + chat -> + maybe_activate_mam(LUser, LServer); + _ -> + ok + end, + case Ret of + ok -> + case SubEl of + #mam_query{rsm = #rsm_set{index = I}} when is_integer(I) -> + Txt = <<"Unsupported <index/> element">>, + xmpp:make_error(IQ, xmpp:err_feature_not_implemented(Txt, Lang)); + #mam_query{rsm = RSM, xmlns = NS} -> + case parse_query(SubEl, Lang) of + {ok, Query} -> + NewRSM = limit_max(RSM, NS), + select_and_send(LServer, Query, NewRSM, IQ, MsgType); + {error, Err} -> + xmpp:make_error(IQ, Err) + end + end; + {error, _} -> + Txt = <<"Database failure">>, + xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang)) end. -spec should_archive(message(), binary()) -> boolean(). @@ -827,17 +877,21 @@ may_enter_room(From, MUCState) -> -spec store_msg(message(), binary(), binary(), jid(), send | recv) -> ok | pass | any(). store_msg(Pkt, LUser, LServer, Peer, Dir) -> - Prefs = get_prefs(LUser, LServer), - case {should_archive_peer(LUser, LServer, Prefs, Peer), Pkt} of - {true, #message{meta = #{sm_copy := true}}} -> - ok; % Already stored. - {true, _} -> - case ejabberd_hooks:run_fold(store_mam_message, LServer, Pkt, - [LUser, LServer, Peer, <<"">>, chat, Dir]) of - #message{} -> ok; - _ -> pass + case get_prefs(LUser, LServer) of + {ok, Prefs} -> + case {should_archive_peer(LUser, LServer, Prefs, Peer), Pkt} of + {true, #message{meta = #{sm_copy := true}}} -> + ok; % Already stored. + {true, _} -> + case ejabberd_hooks:run_fold(store_mam_message, LServer, Pkt, + [LUser, LServer, Peer, <<"">>, chat, Dir]) of + #message{} -> ok; + _ -> pass + end; + {false, _} -> + pass end; - {false, _} -> + {error, _} -> pass end. @@ -896,18 +950,20 @@ get_prefs(LUser, LServer) -> end, case Res of {ok, Prefs} -> - Prefs; + {ok, Prefs}; + {error, _} -> + {error, db_failure}; error -> ActivateOpt = gen_mod:get_module_opt( LServer, ?MODULE, request_activates_archiving), case ActivateOpt of true -> - #archive_prefs{us = {LUser, LServer}, default = never}; + {ok, #archive_prefs{us = {LUser, LServer}, default = never}}; false -> Default = gen_mod:get_module_opt( LServer, ?MODULE, default), - #archive_prefs{us = {LUser, LServer}, default = Default} + {ok, #archive_prefs{us = {LUser, LServer}, default = Default}} end end. @@ -936,6 +992,8 @@ maybe_activate_mam(LUser, LServer) -> case Res of {ok, _Prefs} -> ok; + {error, _} -> + {error, db_failure}; error -> Default = gen_mod:get_module_opt( LServer, ?MODULE, default), @@ -946,15 +1004,21 @@ maybe_activate_mam(LUser, LServer) -> end. select_and_send(LServer, Query, RSM, #iq{from = From, to = To} = IQ, MsgType) -> - {Msgs, IsComplete, Count} = - case MsgType of - chat -> - select(LServer, From, From, Query, RSM, MsgType); - _ -> - select(LServer, From, To, Query, RSM, MsgType) - end, - SortedMsgs = lists:keysort(2, Msgs), - send(SortedMsgs, Count, IsComplete, IQ). + Ret = case MsgType of + chat -> + select(LServer, From, From, Query, RSM, MsgType); + _ -> + select(LServer, From, To, Query, RSM, MsgType) + end, + case Ret of + {Msgs, IsComplete, Count} -> + SortedMsgs = lists:keysort(2, Msgs), + send(SortedMsgs, Count, IsComplete, IQ); + {error, _} -> + Txt = <<"Database failure">>, + Err = xmpp:err_internal_server_error(Txt, IQ#iq.lang), + xmpp:make_error(IQ, Err) + end. select(_LServer, JidRequestor, JidArchive, Query, RSM, {groupchat, _Role, #state{config = #config{mam = false}, @@ -1055,7 +1119,7 @@ maybe_update_from_to(Pkt, _JidRequestor, _JidArchive, _Peer, _MsgType, _Nick) -> Pkt. -spec send([{binary(), integer(), xmlel()}], - non_neg_integer(), boolean(), iq()) -> iq() | ignore. + count(), boolean(), iq()) -> iq() | ignore. send(Msgs, Count, IsComplete, #iq{from = From, to = To, sub_els = [#mam_query{id = QID, xmlns = NS}]} = IQ) -> @@ -1093,7 +1157,7 @@ send(Msgs, Count, IsComplete, ignore end. --spec make_rsm_out([{binary(), integer(), xmlel()}], non_neg_integer()) -> rsm_set(). +-spec make_rsm_out([{binary(), integer(), xmlel()}], count()) -> rsm_set(). make_rsm_out([], Count) -> #rsm_set{count = Count}; make_rsm_out([{FirstID, _, _}|_] = Msgs, Count) -> @@ -1191,6 +1255,8 @@ mod_opt_type(default) -> (roster) -> roster end; mod_opt_type(request_activates_archiving) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(clear_archive_on_room_destroy) -> fun (B) when is_boolean(B) -> B end. mod_options(Host) -> @@ -1198,6 +1264,7 @@ mod_options(Host) -> {default, never}, {request_activates_archiving, false}, {compress_xml, false}, + {clear_archive_on_room_destroy, true}, {db_type, ejabberd_config:default_db(Host, ?MODULE)}, {use_cache, ejabberd_config:use_cache(Host)}, {cache_size, ejabberd_config:cache_size(Host)}, diff --git a/src/mod_mam_mnesia.erl b/src/mod_mam_mnesia.erl index 55154f6bb..f94dd2e49 100644 --- a/src/mod_mam_mnesia.erl +++ b/src/mod_mam_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 15 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -28,7 +28,8 @@ %% API -export([init/2, remove_user/2, remove_room/3, delete_old_messages/3, - extended_fields/0, store/8, write_prefs/4, get_prefs/2, select/6, remove_from_archive/3]). + extended_fields/0, store/8, write_prefs/4, get_prefs/2, select/6, remove_from_archive/3, + is_empty_for_user/2, is_empty_for_room/3]). -include_lib("stdlib/include/ms_transform.hrl"). -include("xmpp.hrl"). @@ -48,13 +49,20 @@ %%% API %%%=================================================================== init(_Host, _Opts) -> - ejabberd_mnesia:create(?MODULE, archive_msg, + try + {atomic, _} = ejabberd_mnesia:create( + ?MODULE, archive_msg, [{disc_only_copies, [node()]}, {type, bag}, {attributes, record_info(fields, archive_msg)}]), - ejabberd_mnesia:create(?MODULE, archive_prefs, + {atomic, _} = ejabberd_mnesia:create( + ?MODULE, archive_prefs, [{disc_only_copies, [node()]}, - {attributes, record_info(fields, archive_prefs)}]). + {attributes, record_info(fields, archive_prefs)}]), + ok + catch _:{badmatch, _} -> + {error, db_failure} + end. remove_user(LUser, LServer) -> US = {LUser, LServer}, @@ -191,6 +199,13 @@ select(_LServer, JidRequestor, erlang:garbage_collect(), Result. +is_empty_for_user(LUser, LServer) -> + not lists:member({LUser, LServer}, + mnesia:dirty_all_keys(archive_msg)). + +is_empty_for_room(_LServer, LName, LHost) -> + is_empty_for_user(LName, LHost). + %%%=================================================================== %%% Internal functions %%%=================================================================== diff --git a/src/mod_mam_sql.erl b/src/mod_mam_sql.erl index 4fac259bc..48112842c 100644 --- a/src/mod_mam_sql.erl +++ b/src/mod_mam_sql.erl @@ -4,7 +4,7 @@ %%% Created : 15 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 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,7 +30,8 @@ %% API -export([init/2, remove_user/2, remove_room/3, delete_old_messages/3, - extended_fields/0, store/8, write_prefs/4, get_prefs/2, select/6, export/1, remove_from_archive/3]). + extended_fields/0, store/8, write_prefs/4, get_prefs/2, select/6, export/1, remove_from_archive/3, + is_empty_for_user/2, is_empty_for_room/3]). -include_lib("stdlib/include/ms_transform.hrl"). -include("xmpp.hrl"). @@ -264,6 +265,23 @@ export(_Server) -> [] end}]. +is_empty_for_user(LUser, LServer) -> + case ejabberd_sql:sql_query( + LServer, + ?SQL("select @(count(*))d from archive" + " where username=%(LUser)s and %(LServer)H")) of + {selected, [{Res}]} -> + case Res of + 0 -> true; + _ -> false + end; + _ -> false + end. + +is_empty_for_room(LServer, LName, LHost) -> + LUser = jid:encode({LName, LHost, <<>>}), + is_empty_for_user(LUser, LServer). + %%%=================================================================== %%% Internal functions %%%=================================================================== diff --git a/src/mod_metrics.erl b/src/mod_metrics.erl index 282dca7ef..a84d92b9c 100644 --- a/src/mod_metrics.erl +++ b/src/mod_metrics.erl @@ -5,7 +5,7 @@ %%% Created : 22 Oct 2015 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 8a80e3012..ae3c6f9f7 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -5,7 +5,7 @@ %%% Created : 19 Mar 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -65,7 +65,8 @@ iq_set_register_info/5, count_online_rooms_by_user/3, get_online_rooms_by_user/3, - can_use_nick/4]). + can_use_nick/4, + check_create_room/4]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, @@ -112,10 +113,14 @@ %% API %%==================================================================== start(Host, Opts) -> + ejabberd_hooks:add(check_create_room, Host, ?MODULE, + check_create_room, 50), gen_mod:start_child(?MODULE, Host, Opts). stop(Host) -> Rooms = shutdown_rooms(Host), + ejabberd_hooks:delete(check_create_room, Host, ?MODULE, + check_create_room, 50), gen_mod:stop_child(?MODULE, Host), {wait, Rooms}. @@ -354,6 +359,7 @@ init_state(Host, Opts) -> AccessCreate = gen_mod:get_opt(access_create, Opts), AccessAdmin = gen_mod:get_opt(access_admin, Opts), AccessPersistent = gen_mod:get_opt(access_persistent, Opts), + AccessMam = gen_mod:get_opt(access_mam, Opts), HistorySize = gen_mod:get_opt(history_size, Opts), MaxRoomsDiscoItems = gen_mod:get_opt(max_rooms_discoitems, Opts), DefRoomOpts = gen_mod:get_opt(default_room_options, Opts), @@ -361,7 +367,7 @@ init_state(Host, Opts) -> RoomShaper = gen_mod:get_opt(room_shaper, Opts), #state{hosts = MyHosts, server_host = Host, - access = {Access, AccessCreate, AccessAdmin, AccessPersistent}, + access = {Access, AccessCreate, AccessAdmin, AccessPersistent, AccessMam}, default_room_opts = DefRoomOpts, queue_type = QueueType, history_size = HistorySize, @@ -392,7 +398,7 @@ unregister_iq_handlers(Host) -> do_route(Host, ServerHost, Access, HistorySize, RoomShaper, From, To, Packet, DefRoomOpts, _MaxRoomsDiscoItems, QueueType) -> - {AccessRoute, _AccessCreate, _AccessAdmin, _AccessPersistent} = Access, + {AccessRoute, _AccessCreate, _AccessAdmin, _AccessPersistent, _AccessMam} = Access, case acl:match_rule(ServerHost, AccessRoute, From) of allow -> do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, @@ -411,7 +417,7 @@ do_route1(_Host, _ServerHost, _Access, _HistorySize, _RoomShaper, do_route1(Host, ServerHost, Access, _HistorySize, _RoomShaper, From, #jid{luser = <<"">>, lresource = <<"">>} = _To, #message{lang = Lang, body = Body, type = Type} = Packet, _, _) -> - {_AccessRoute, _AccessCreate, AccessAdmin, _AccessPersistent} = Access, + {_AccessRoute, _AccessCreate, AccessAdmin, _AccessPersistent, _AccessMam} = Access, if Type == error -> ok; true -> @@ -432,7 +438,7 @@ do_route1(_Host, _ServerHost, _Access, _HistorySize, _RoomShaper, ejabberd_router:route_error(Packet, Err); do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, From, To, Packet, DefRoomOpts, QueueType) -> - {_AccessRoute, AccessCreate, _AccessAdmin, _AccessPersistent} = Access, + {_AccessRoute, AccessCreate, _AccessAdmin, _AccessPersistent, _AccessMam} = Access, {Room, _, Nick} = jid:tolower(To), RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE), case RMod:find_online_room(ServerHost, Room, Host) of @@ -441,7 +447,9 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, true -> case check_user_can_create_room( ServerHost, AccessCreate, From, Room) and - check_create_roomid(ServerHost, Room) of + ejabberd_hooks:run_fold(check_create_room, + ServerHost, true, + [ServerHost, Room, Host]) of true -> {ok, Pid} = start_new_room( Host, ServerHost, Access, @@ -610,9 +618,10 @@ check_user_can_create_room(ServerHost, AccessCreate, _ -> false end. -check_create_roomid(ServerHost, RoomID) -> +check_create_room(Acc, ServerHost, RoomID, _Host) -> Max = gen_mod:get_module_opt(ServerHost, ?MODULE, max_room_id), Regexp = gen_mod:get_module_opt(ServerHost, ?MODULE, regexp_room_id), + Acc and (byte_size(RoomID) =< Max) and (re:run(RoomID, Regexp, [unicode, {capture, none}]) == match). @@ -884,6 +893,8 @@ mod_opt_type(access_create) -> fun acl:access_rules_validator/1; mod_opt_type(access_persistent) -> fun acl:access_rules_validator/1; +mod_opt_type(access_mam) -> + fun acl:access_rules_validator/1; mod_opt_type(access_register) -> fun acl:access_rules_validator/1; mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end; @@ -985,13 +996,14 @@ mod_opt_type({default_room_options, presence_broadcast}) -> end, L) end; mod_opt_type({default_room_options, lang}) -> - fun iolist_to_binary/1. + fun xmpp_lang:check/1. mod_options(Host) -> [{access, all}, {access_admin, none}, {access_create, all}, {access_persistent, all}, + {access_mam, all}, {access_register, all}, {db_type, ejabberd_config:default_db(Host, ?MODULE)}, {ram_db_type, ejabberd_config:default_ram_db(Host, ?MODULE)}, diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index c050d4fc2..494a4ef3f 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -5,7 +5,7 @@ %%% Created : 8 Sep 2007 by Badlop <badlop@ono.com> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -34,6 +34,7 @@ create_room_with_opts/4, create_room/3, destroy_room/2, create_rooms_file/1, destroy_rooms_file/1, rooms_unused_list/2, rooms_unused_destroy/2, + rooms_empty_list/1, rooms_empty_destroy/1, get_user_rooms/2, get_room_occupants/2, get_room_occupants_number/2, send_direct_invitation/5, change_room_option/4, get_room_options/2, @@ -116,14 +117,14 @@ get_commands_spec() -> module = ?MODULE, function = muc_register_nick, args_desc = ["Nick", "User JID", "Server Host"], args_example = [<<"Tim">>, <<"tim@example.org">>, <<"example.org">>], - args = [{nick, binary}, {jid, binary}, {serverhost, binary}], + args = [{nick, binary}, {jid, binary}, {host, binary}], result = {res, rescode}}, #ejabberd_commands{name = muc_unregister_nick, tags = [muc], desc = "Unregister the nick registered by that account in the MUC service", module = ?MODULE, function = muc_unregister_nick, args_desc = ["User JID", "MUC service"], args_example = [<<"tim@example.org">>, <<"example.org">>], - args = [{jid, binary}, {serverhost, binary}], + args = [{jid, binary}, {host, binary}], result = {res, rescode}}, #ejabberd_commands{name = create_room, tags = [muc_room], @@ -173,6 +174,8 @@ get_commands_spec() -> result = {res, rescode}}, #ejabberd_commands{name = rooms_unused_list, tags = [muc], desc = "List the rooms that are unused for many days in host", + longdesc = "The room recent history is used, so it's recommended " + " to wait a few days after service start before running this.", module = ?MODULE, function = rooms_unused_list, args_desc = ["Server host", "Number of days"], args_example = ["example.com", 31], @@ -182,6 +185,8 @@ get_commands_spec() -> result = {rooms, {list, {room, string}}}}, #ejabberd_commands{name = rooms_unused_destroy, tags = [muc], desc = "Destroy the rooms that are unused for many days in host", + longdesc = "The room recent history is used, so it's recommended " + " to wait a few days after service start before running this.", module = ?MODULE, function = rooms_unused_destroy, args_desc = ["Server host", "Number of days"], args_example = ["example.com", 31], @@ -190,6 +195,25 @@ get_commands_spec() -> args = [{host, binary}, {days, integer}], result = {rooms, {list, {room, string}}}}, + #ejabberd_commands{name = rooms_empty_list, tags = [muc], + desc = "List the rooms that have no messages in archive", + module = ?MODULE, function = rooms_empty_list, + args_desc = ["Server host"], + args_example = ["example.com"], + result_desc = "List of empty rooms", + result_example = ["room1@muc.example.com", "room2@muc.example.com"], + args = [{host, binary}], + result = {rooms, {list, {room, string}}}}, + #ejabberd_commands{name = rooms_empty_destroy, tags = [muc], + desc = "Destroy the rooms that have no messages in archive", + module = ?MODULE, function = rooms_empty_destroy, + args_desc = ["Server host"], + args_example = ["example.com"], + result_desc = "List of empty rooms that have been destroyed", + result_example = ["room1@muc.example.com", "room2@muc.example.com"], + args = [{host, binary}], + result = {rooms, {list, {room, string}}}}, + #ejabberd_commands{name = get_user_rooms, tags = [muc], desc = "Get the list of rooms where this user is occupant", module = ?MODULE, function = get_user_rooms, @@ -263,9 +287,9 @@ get_commands_spec() -> #ejabberd_commands{name = subscribe_room, tags = [muc_room], desc = "Subscribe to a MUC conference", module = ?MODULE, function = subscribe_room, - args_desc = ["Full JID, including some resource", "a user's nick", + args_desc = ["User JID", "a user's nick", "the room to subscribe", "nodes separated by commas: ,"], - args_example = ["tom@localhost/dummy", "Tom", "room1@conference.localhost", + args_example = ["tom@localhost", "Tom", "room1@conference.localhost", "urn:xmpp:mucsub:nodes:messages,urn:xmpp:mucsub:nodes:affiliations"], result_desc = "The list of nodes that has subscribed", result_example = ["urn:xmpp:mucsub:nodes:messages", @@ -604,6 +628,7 @@ create_room_with_opts(Name1, Host1, ServerHost, CustomRoomOpts) -> AcCreate = gen_mod:get_module_opt(ServerHost, mod_muc, access_create), AcAdmin = gen_mod:get_module_opt(ServerHost, mod_muc, access_admin), AcPer = gen_mod:get_module_opt(ServerHost, mod_muc, access_persistent), + AcMam = gen_mod:get_module_opt(ServerHost, mod_muc, access_mam), HistorySize = gen_mod:get_module_opt(ServerHost, mod_muc, history_size), RoomShaper = gen_mod:get_module_opt(ServerHost, mod_muc, room_shaper), QueueType = gen_mod:get_module_opt(ServerHost, mod_muc, queue_type), @@ -615,7 +640,7 @@ create_room_with_opts(Name1, Host1, ServerHost, CustomRoomOpts) -> {ok, Pid} = mod_muc_room:start( Host, ServerHost, - {Access, AcCreate, AcAdmin, AcPer}, + {Access, AcCreate, AcAdmin, AcPer, AcMam}, Name, HistorySize, RoomShaper, @@ -713,35 +738,41 @@ create_rooms_file(Filename) -> ok. -%%---------------------------- -%% List/Delete Unused Rooms -%%---------------------------- +%%--------------------------------- +%% List/Delete Unused/Empty Rooms +%%--------------------------------- %%--------------- %% Control rooms_unused_list(ServerHost, Days) -> - rooms_unused_report(list, ServerHost, Days). + rooms_report(unused, list, ServerHost, Days). rooms_unused_destroy(ServerHost, Days) -> - rooms_unused_report(destroy, ServerHost, Days). + rooms_report(unused, destroy, ServerHost, Days). + +rooms_empty_list(ServerHost) -> + rooms_report(empty, list, ServerHost, 0). +rooms_empty_destroy(ServerHost) -> + rooms_report(empty, destroy, ServerHost, 0). -rooms_unused_report(Action, ServerHost, Days) -> - {NA, NP, RP} = muc_unused(Action, ServerHost, Days), - io:format("Unused rooms: ~p out of ~p~n", [NP, NA]), + +rooms_report(Method, Action, ServerHost, Days) -> + {NA, NP, RP} = muc_unused(Method, Action, ServerHost, Days), + io:format("rooms ~s: ~p out of ~p~n", [Method, NP, NA]), [<<R/binary, "@", H/binary>> || {R, H, _P} <- RP]. -muc_unused(Action, ServerHost, Last_allowed) -> +muc_unused(Method, Action, ServerHost, Last_allowed) -> %% Get all required info about all existing rooms Rooms_all = get_rooms(ServerHost), %% Decide which ones pass the requirements - Rooms_pass = decide_rooms(Rooms_all, Last_allowed), + Rooms_pass = decide_rooms(Method, Rooms_all, ServerHost, Last_allowed), Num_rooms_all = length(Rooms_all), Num_rooms_pass = length(Rooms_pass), %% Perform the desired action for matching rooms - act_on_rooms(Action, Rooms_pass, ServerHost), + act_on_rooms(Method, Action, Rooms_pass, ServerHost), {Num_rooms_all, Num_rooms_pass, Rooms_pass}. @@ -766,11 +797,11 @@ get_room_state(Room_pid) -> %%--------------- %% Decide -decide_rooms(Rooms, Last_allowed) -> - Decide = fun(R) -> decide_room(R, Last_allowed) end, +decide_rooms(Method, Rooms, ServerHost, Last_allowed) -> + Decide = fun(R) -> decide_room(Method, R, ServerHost, Last_allowed) end, lists:filter(Decide, Rooms). -decide_room({_Room_name, _Host, Room_pid}, Last_allowed) -> +decide_room(unused, {_Room_name, _Host, Room_pid}, ServerHost, Last_allowed) -> C = get_room_config(Room_pid), Persistent = C#config.persistent, @@ -782,10 +813,15 @@ decide_room({_Room_name, _Host, Room_pid}, Last_allowed) -> History = (S#state.history)#lqueue.queue, Ts_now = calendar:universal_time(), - Ts_uptime = uptime_seconds(), + HistorySize = gen_mod:get_module_opt(ServerHost, mod_muc, history_size), + JustCreated = S#state.just_created, {Has_hist, Last} = case p1_queue:is_empty(History) of + true when (HistorySize == 0) or (JustCreated == true) -> + {false, 0}; true -> - {false, Ts_uptime}; + Ts_diff = (misc:now_to_usec(now()) + - S#state.just_created) div 1000000, + {false, Ts_diff}; false -> Last_message = get_queue_last(History), Ts_last = calendar:now_to_universal_time( @@ -795,13 +831,19 @@ decide_room({_Room_name, _Host, Room_pid}, Last_allowed) -> - calendar:datetime_to_gregorian_seconds(Ts_last), {true, Ts_diff} end, - case {Persistent, Just_created, Num_users, Has_hist, seconds_to_days(Last)} of - {_true, false, 0, _, Last_days} - when Last_days >= Last_allowed -> + {_true, JC, 0, _, Last_days} + when (Last_days >= Last_allowed) and (JC /= true) -> true; _ -> false + end; +decide_room(empty, {Room_name, Host, _Room_pid}, ServerHost, _Last_allowed) -> + case gen_mod:is_loaded(ServerHost, mod_mam) of + true -> + mod_mam:is_empty_for_room(ServerHost, Room_name, Host); + _ -> + false end. seconds_to_days(S) -> @@ -810,7 +852,7 @@ seconds_to_days(S) -> %%--------------- %% Act -act_on_rooms(Action, Rooms, ServerHost) -> +act_on_rooms(Method, Action, Rooms, ServerHost) -> ServerHosts = [ {A, find_host(A)} || A <- ejabberd_config:get_myhosts() ], Delete = fun({_N, H, _Pid} = Room) -> SH = case ServerHost of @@ -818,7 +860,7 @@ act_on_rooms(Action, Rooms, ServerHost) -> O -> O end, - act_on_room(Action, Room, SH) + act_on_room(Method, Action, Room, SH) end, lists:foreach(Delete, Rooms). @@ -826,13 +868,15 @@ find_serverhost(Host, ServerHosts) -> {value, {ServerHost, Host}} = lists:keysearch(Host, 2, ServerHosts), ServerHost. -act_on_room(destroy, {N, H, Pid}, SH) -> +act_on_room(Method, destroy, {N, H, Pid}, SH) -> + Message = iolist_to_binary(io_lib:format( + <<"Room destroyed by rooms_~s_destroy.">>, [Method])), p1_fsm:send_all_state_event( - Pid, {destroy, <<"Room destroyed by rooms_unused_destroy.">>}), + Pid, {destroy, Message}), mod_muc:room_destroyed(H, N, Pid, SH), mod_muc:forget_room(SH, H, N); -act_on_room(list, _, _) -> +act_on_room(_Method, list, _, _) -> ok. @@ -1104,9 +1148,8 @@ subscribe_room(User, Nick, Room, Nodes) -> try jid:decode(Room) of #jid{luser = Name, lserver = Host} when Name /= <<"">> -> try jid:decode(User) of - #jid{lresource = <<"">>} -> - throw({error, "User's JID should have a resource"}); - UserJID -> + UserJID1 -> + UserJID = jid:replace_resource(UserJID1, <<"modmucadmin">>), case get_room_pid(Name, Host) of Pid when is_pid(Pid) -> case p1_fsm:sync_send_all_state_event( @@ -1215,9 +1258,6 @@ make_opts(StateData) -> %% Utils %%---------------------------- -uptime_seconds() -> - trunc(element(1, erlang:statistics(wall_clock))/1000). - find_host(global) -> global; find_host("global") -> diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index a847a3874..42a9cc0a5 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -5,7 +5,7 @@ %%% Created : 12 Mar 2006 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_muc_mnesia.erl b/src/mod_muc_mnesia.erl index 43cf1aa01..32006256e 100644 --- a/src/mod_muc_mnesia.erl +++ b/src/mod_muc_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_muc_riak.erl b/src/mod_muc_riak.erl index d9e0732db..a5d02fd1a 100644 --- a/src/mod_muc_riak.erl +++ b/src/mod_muc_riak.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 39f727111..a8818aca4 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -5,7 +5,7 @@ %%% Created : 19 Mar 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -54,6 +54,7 @@ -include("xmpp.hrl"). -include("translate.hrl"). -include("mod_muc_room.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(MAX_USERS_DEFAULT_LIST, [5, 10, 20, 30, 50, 100, 200, 500, 1000, 2000, 5000]). @@ -339,7 +340,7 @@ normal_state({route, <<"">>, #iq{} = IQ}, StateData) -> ejabberd_router:route_error(IQ, Err), case StateData#state.just_created of true -> {stop, normal, StateData}; - false -> {next_state, normal_state, StateData} + _ -> {next_state, normal_state, StateData} end; normal_state({route, Nick, #presence{from = From} = Packet}, StateData) -> Activity = get_user_activity(From, StateData), @@ -698,36 +699,42 @@ handle_info(_Info, StateName, StateData) -> {next_state, StateName, StateData}. terminate(Reason, _StateName, StateData) -> - ?INFO_MSG("Stopping MUC room ~s@~s", - [StateData#state.room, StateData#state.host]), - ReasonT = case Reason of - shutdown -> - <<"You are being removed from the room " - "because of a system shutdown">>; - _ -> <<"Room terminates">> - end, - Packet = #presence{ - type = unavailable, - sub_els = [#muc_user{items = [#muc_item{affiliation = none, - reason = ReasonT, - role = none}], - status_codes = [332,110]}]}, - maps:fold( - fun(LJID, Info, _) -> - Nick = Info#user.nick, - case Reason of - shutdown -> - send_wrapped(jid:replace_resource(StateData#state.jid, Nick), - Info#user.jid, Packet, - ?NS_MUCSUB_NODES_PARTICIPANTS, - StateData); - _ -> ok - end, - tab_remove_online_user(LJID, StateData) - end, [], get_users_and_subscribers(StateData)), - add_to_log(room_existence, stopped, StateData), - mod_muc:room_destroyed(StateData#state.host, StateData#state.room, self(), - StateData#state.server_host), + try + ?INFO_MSG("Stopping MUC room ~s@~s", + [StateData#state.room, StateData#state.host]), + ReasonT = case Reason of + shutdown -> + <<"You are being removed from the room " + "because of a system shutdown">>; + _ -> <<"Room terminates">> + end, + Packet = #presence{ + type = unavailable, + sub_els = [#muc_user{items = [#muc_item{affiliation = none, + reason = ReasonT, + role = none}], + status_codes = [332,110]}]}, + maps:fold( + fun(LJID, Info, _) -> + Nick = Info#user.nick, + case Reason of + shutdown -> + send_wrapped(jid:replace_resource(StateData#state.jid, Nick), + Info#user.jid, Packet, + ?NS_MUCSUB_NODES_PARTICIPANTS, + StateData); + _ -> ok + end, + tab_remove_online_user(LJID, StateData) + end, [], get_users_and_subscribers(StateData)), + add_to_log(room_existence, stopped, StateData), + mod_muc:room_destroyed(StateData#state.host, StateData#state.room, self(), + StateData#state.server_host) + catch ?EX_RULE(E, R, St) -> + mod_muc:room_destroyed(StateData#state.host, StateData#state.room, self(), + StateData#state.server_host), + ?ERROR_MSG("Got exception on room termination: ~p", [{E, {R, ?EX_STACK(St)}}]) + end, ok. %%%---------------------------------------------------------------------- @@ -1408,7 +1415,7 @@ get_affiliations_callback(StateData) -> -spec get_service_affiliation(jid(), state()) -> owner | none. get_service_affiliation(JID, StateData) -> {_AccessRoute, _AccessCreate, AccessAdmin, - _AccessPersistent} = + _AccessPersistent, _AccessMam} = StateData#state.access, case acl:match_rule(StateData#state.server_host, AccessAdmin, JID) @@ -1953,8 +1960,8 @@ add_new_user(From, Nick, Packet, StateData) -> ResultState = case NewStateData#state.just_created of true -> - NewStateData#state{just_created = false}; - false -> + NewStateData#state{just_created = misc:now_to_usec(now())}; + _ -> Robots = maps:remove(From, StateData#state.robots), NewStateData#state{robots = Robots} end, @@ -2142,15 +2149,15 @@ presence_broadcast_allowed(JID, StateData) -> -spec send_initial_presences_and_messages( jid(), binary(), presence(), state(), state()) -> ok. send_initial_presences_and_messages(From, Nick, Presence, NewState, OldState) -> - send_self_presence(From, NewState), + advertise_entity_capabilities(From, NewState), send_existing_presences(From, NewState), - send_initial_presence(From, NewState, OldState), + send_self_presence(From, NewState, OldState), History = get_history(Nick, Presence, NewState), send_history(From, History, NewState), send_subject(From, OldState). --spec send_self_presence(jid(), state()) -> ok. -send_self_presence(JID, State) -> +-spec advertise_entity_capabilities(jid(), state()) -> ok. +advertise_entity_capabilities(JID, State) -> AvatarHash = (State#state.config)#config.vcard_xupdate, DiscoInfo = make_disco_info(JID, State), Extras = iq_disco_info_extras(<<"en">>, State, true), @@ -2168,8 +2175,8 @@ send_self_presence(JID, State) -> id = p1_rand:get_string(), sub_els = Els2}). --spec send_initial_presence(jid(), state(), state()) -> ok. -send_initial_presence(NJID, StateData, OldStateData) -> +-spec send_self_presence(jid(), state(), state()) -> ok. +send_self_presence(NJID, StateData, OldStateData) -> send_new_presence(NJID, <<"">>, true, StateData, OldStateData). -spec send_update_presence(jid(), state(), state()) -> ok. @@ -2468,7 +2475,7 @@ status_codes(IsInitialPresence, _IsSelfPresence = true, StateData) -> true -> S1 = case StateData#state.just_created of true -> [201|S0]; - false -> S0 + _ -> S0 end, S2 = case (StateData#state.config)#config.anonymous of true -> S1; @@ -2765,7 +2772,7 @@ process_item_change(Item, SD, UJID) -> maybe_send_affiliation(JID, A, SD1), SD1 end - catch E:R -> + catch ?EX_RULE(E, R, St) -> FromSuffix = case UJID of #jid{} -> JidString = jid:encode(UJID), @@ -2773,9 +2780,8 @@ process_item_change(Item, SD, UJID) -> undefined -> <<"">> end, - St = erlang:get_stacktrace(), ?ERROR_MSG("failed to set item ~p~s: ~p", - [Item, FromSuffix, {E, {R, St}}]), + [Item, FromSuffix, {E, {R, ?EX_STACK(St)}}]), {error, xmpp:err_internal_server_error()} end. @@ -3170,6 +3176,7 @@ process_iq_owner(From, #iq{type = set, lang = Lang, Options -> case is_allowed_log_change(Options, StateData, From) andalso is_allowed_persistent_change(Options, StateData, From) andalso + is_allowed_mam_change(Options, StateData, From) andalso is_allowed_room_name_desc_limits(Options, StateData) andalso is_password_settings_correct(Options, StateData) of true -> @@ -3234,13 +3241,26 @@ is_allowed_persistent_change(Options, StateData, From) -> false -> true; true -> {_AccessRoute, _AccessCreate, _AccessAdmin, - AccessPersistent} = + AccessPersistent, _AccessMam} = StateData#state.access, allow == acl:match_rule(StateData#state.server_host, AccessPersistent, From) end. +-spec is_allowed_mam_change(muc_roomconfig:result(), state(), jid()) -> boolean(). +is_allowed_mam_change(Options, StateData, From) -> + case proplists:is_defined(mam, Options) of + false -> true; + true -> + {_AccessRoute, _AccessCreate, _AccessAdmin, + _AccessPersistent, AccessMam} = + StateData#state.access, + allow == + acl:match_rule(StateData#state.server_host, + AccessMam, From) + end. + %% Check if the Room Name and Room Description defined in the Data Form %% are conformant to the configured limits -spec is_allowed_room_name_desc_limits(muc_roomconfig:result(), state()) -> boolean(). @@ -3283,7 +3303,7 @@ get_default_room_maxusers(RoomState) -> -spec get_config(binary(), state(), jid()) -> xdata(). get_config(Lang, StateData, From) -> - {_AccessRoute, _AccessCreate, _AccessAdmin, AccessPersistent} = + {_AccessRoute, _AccessCreate, _AccessAdmin, AccessPersistent, _AccessMam} = StateData#state.access, ServiceMaxUsers = get_service_max_users(StateData), DefaultRoomMaxUsers = get_default_room_maxusers(StateData), @@ -3493,7 +3513,7 @@ send_config_change_info(New, #state{config = Old} = StateData) -> if Codes /= [] -> maps:fold( fun(_LJID, #user{jid = JID}, _) -> - send_self_presence(JID, StateData#state{config = New}) + advertise_entity_capabilities(JID, StateData#state{config = New}) end, ok, StateData#state.users), Message = #message{type = groupchat, id = p1_rand:get_string(), @@ -3963,7 +3983,7 @@ process_iq_vcard(From, #iq{type = set, lang = Lang, sub_els = [Pkt]}, {ignore, state()}. process_iq_mucsub(_From, #iq{type = set, lang = Lang, sub_els = [#muc_subscribe{}]}, - #state{just_created = false, config = #config{allow_subscription = false}}) -> + #state{just_created = Just, config = #config{allow_subscription = false}}) when Just /= true -> {error, xmpp:err_not_allowed(<<"Subscriptions are not allowed">>, Lang)}; process_iq_mucsub(From, #iq{type = set, lang = Lang, @@ -4345,7 +4365,7 @@ send_subscriptions_change_notifications(From, Nick, Type, State) -> items = [#ps_item{ id = p1_rand:get_string(), sub_els = [Payload]}]}}]}, - ejabberd_router:route(xmpp:set_from_to(Packet, From, JID)); + ejabberd_router:route(xmpp:set_from_to(Packet, State#state.jid, JID)); false -> ok end diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl index e92b4bc54..12487e628 100644 --- a/src/mod_muc_sql.erl +++ b/src/mod_muc_sql.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index 72c177b80..509fe8893 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -5,7 +5,7 @@ %%% Created : 29 May 2007 by Badlop <badlop@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 53e437020..2582a7c98 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -5,7 +5,7 @@ %%% Created : 5 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -101,6 +101,8 @@ -callback remove_all_messages(binary(), binary()) -> {atomic, any()}. -callback count_messages(binary(), binary()) -> non_neg_integer(). +-optional_callbacks([remove_expired_messages/1, remove_old_messages/2]). + depends(_Host, _Opts) -> []. @@ -365,7 +367,6 @@ remove_msg_by_node(To, Seq) -> -spec need_to_store(binary(), message()) -> boolean(). need_to_store(_LServer, #message{type = error}) -> false; -need_to_store(_LServer, #message{type = groupchat}) -> false; need_to_store(LServer, #message{type = Type} = Packet) -> case xmpp:has_subtag(Packet, #offline{}) of false -> @@ -374,16 +375,25 @@ need_to_store(LServer, #message{type = Type} = Packet) -> true; no_store -> false; - none when Type == headline -> - false; none -> - case gen_mod:get_module_opt( - LServer, ?MODULE, store_empty_body) of - true -> + Store = case Type of + groupchat -> + gen_mod:get_module_opt( + LServer, ?MODULE, store_groupchat); + headline -> + false; + _ -> + true + end, + case {Store, gen_mod:get_module_opt( + LServer, ?MODULE, store_empty_body)} of + {false, _} -> + false; + {_, true} -> true; - false -> + {_, false} -> Packet#message.body /= []; - unless_chat_state -> + {_, unless_chat_state} -> not misc:is_standalone_chat_state(Packet) end end; @@ -543,12 +553,18 @@ privacy_check_packet(#{lserver := LServer} = State, Pkt, Dir) -> remove_expired_messages(Server) -> LServer = jid:nameprep(Server), Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:remove_expired_messages(LServer). + case erlang:function_exported(Mod, remove_expired_messages, 1) of + true -> Mod:remove_expired_messages(LServer); + false -> erlang:error(not_implemented) + end. remove_old_messages(Days, Server) -> LServer = jid:nameprep(Server), Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:remove_old_messages(Days, LServer). + case erlang:function_exported(Mod, remove_old_messages, 2) of + true -> Mod:remove_old_messages(Days, LServer); + false -> erlang:error(not_implemented) + end. -spec remove_user(binary(), binary()) -> ok. remove_user(User, Server) -> @@ -837,6 +853,8 @@ import(LServer, {sql, _}, DBType, <<"spool">>, mod_opt_type(access_max_user_messages) -> fun acl:shaper_rules_validator/1; mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end; +mod_opt_type(store_groupchat) -> + fun(V) when is_boolean(V) -> V end; mod_opt_type(store_empty_body) -> fun (V) when is_boolean(V) -> V; (unless_chat_state) -> unless_chat_state @@ -845,4 +863,5 @@ mod_opt_type(store_empty_body) -> mod_options(Host) -> [{db_type, ejabberd_config:default_db(Host, ?MODULE)}, {access_max_user_messages, max_user_offline_messages}, - {store_empty_body, unless_chat_state}]. + {store_empty_body, unless_chat_state}, + {store_groupchat, false}]. diff --git a/src/mod_offline_mnesia.erl b/src/mod_offline_mnesia.erl index a7f0cd02f..77c5b2e44 100644 --- a/src/mod_offline_mnesia.erl +++ b/src/mod_offline_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 15 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_offline_riak.erl b/src/mod_offline_riak.erl index 2c03df366..db86767ce 100644 --- a/src/mod_offline_riak.erl +++ b/src/mod_offline_riak.erl @@ -4,7 +4,7 @@ %%% Created : 15 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_offline_sql.erl b/src/mod_offline_sql.erl index f2cc682d6..cb0efa51e 100644 --- a/src/mod_offline_sql.erl +++ b/src/mod_offline_sql.erl @@ -4,7 +4,7 @@ %%% Created : 15 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_ping.erl b/src/mod_ping.erl index e0b4a36a9..25d2b60ed 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -5,7 +5,7 @@ %%% Created : 11 Jul 2009 by Brian Cully <bjc@kublai.com> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -122,30 +122,31 @@ handle_cast({start_ping, JID}, State) -> handle_cast({stop_ping, JID}, State) -> Timers = del_timer(JID, State#state.timers), {noreply, State#state{timers = Timers}}; -handle_cast({iq_reply, timeout, JID}, State) -> - ejabberd_hooks:run(user_ping_timeout, State#state.host, - [JID]), - Timers = case State#state.timeout_action of - kill -> - #jid{user = User, server = Server, - resource = Resource} = - JID, - case ejabberd_sm:get_session_pid(User, Server, Resource) - of - Pid when is_pid(Pid) -> ejabberd_c2s:close(Pid, ping_timeout); - _ -> ok - end, - del_timer(JID, State#state.timers); - _ -> - State#state.timers - end, - {noreply, State#state{timers = Timers}}; -handle_cast({iq_reply, #iq{}, _JID}, State) -> - {noreply, State}; handle_cast(Msg, State) -> ?WARNING_MSG("unexpected cast: ~p", [Msg]), {noreply, State}. +handle_info({iq_reply, #iq{type = error}, JID}, State) -> + handle_info({iq_reply, timeout, JID}, State); +handle_info({iq_reply, #iq{}, _JID}, State) -> + {noreply, State}; +handle_info({iq_reply, timeout, JID}, State) -> + Timers = del_timer(JID, State#state.timers), + ejabberd_hooks:run(user_ping_timeout, State#state.host, + [JID]), + case State#state.timeout_action of + kill -> + #jid{user = User, server = Server, + resource = Resource} = + JID, + case ejabberd_sm:get_session_pid(User, Server, Resource) + of + Pid when is_pid(Pid) -> ejabberd_c2s:close(Pid, ping_timeout); + _ -> ok + end; + _ -> ok + end, + {noreply, State#state{timers = Timers}}; handle_info({timeout, _TRef, {ping, JID}}, State) -> Host = State#state.host, From = jid:remove_resource(JID), diff --git a/src/mod_pres_counter.erl b/src/mod_pres_counter.erl index 6c58d2641..c1473e344 100644 --- a/src/mod_pres_counter.erl +++ b/src/mod_pres_counter.erl @@ -5,7 +5,7 @@ %%% Created : 23 Sep 2010 by Ahmed Omar %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 6cb573439..0b534d272 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -5,7 +5,7 @@ %%% Created : 21 Jul 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_privacy_mnesia.erl b/src/mod_privacy_mnesia.erl index a28910c0f..1be9912fb 100644 --- a/src/mod_privacy_mnesia.erl +++ b/src/mod_privacy_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_privacy_riak.erl b/src/mod_privacy_riak.erl index 71d744c8a..51caaafe7 100644 --- a/src/mod_privacy_riak.erl +++ b/src/mod_privacy_riak.erl @@ -4,7 +4,7 @@ %%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_privacy_sql.erl b/src/mod_privacy_sql.erl index 4ee0984a8..e5a97c96b 100644 --- a/src/mod_privacy_sql.erl +++ b/src/mod_privacy_sql.erl @@ -4,7 +4,7 @@ %%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_private.erl b/src/mod_private.erl index b32fff98e..f69f2cc96 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -5,7 +5,7 @@ %%% Created : 16 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -255,7 +255,7 @@ publish_data(JID, Data) -> {access_model, whitelist}], case mod_pubsub:publish_item( LBJID, LServer, ?NS_STORAGE_BOOKMARKS, JID, - <<>>, [El], PubOpts, all) of + <<"current">>, [El], PubOpts, all) of {result, _} -> ok; {error, _} = Err -> Err end diff --git a/src/mod_private_mnesia.erl b/src/mod_private_mnesia.erl index b981a803a..03d98b1ca 100644 --- a/src/mod_private_mnesia.erl +++ b/src/mod_private_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_private_riak.erl b/src/mod_private_riak.erl index 6ddf9cc10..c0a225a14 100644 --- a/src/mod_private_riak.erl +++ b/src/mod_private_riak.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_private_sql.erl b/src/mod_private_sql.erl index a0ec03c6a..1fa91a9d4 100644 --- a/src/mod_private_sql.erl +++ b/src/mod_private_sql.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_privilege.erl b/src/mod_privilege.erl index 5f2fa3297..abb38456a 100644 --- a/src/mod_privilege.erl +++ b/src/mod_privilege.erl @@ -4,7 +4,7 @@ %%% Purpose : XEP-0356: Privileged Entity %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl index c911dd7aa..0fca1cdcb 100644 --- a/src/mod_proxy65.erl +++ b/src/mod_proxy65.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Evgeniy Khramtsov <xram@jabber.ru> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_lib.erl b/src/mod_proxy65_lib.erl index 23e1108ad..70a762413 100644 --- a/src/mod_proxy65_lib.erl +++ b/src/mod_proxy65_lib.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Evgeniy Khramtsov <xram@jabber.ru> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_mnesia.erl b/src/mod_proxy65_mnesia.erl index 7423697c1..89dd24800 100644 --- a/src/mod_proxy65_mnesia.erl +++ b/src/mod_proxy65_mnesia.erl @@ -2,7 +2,7 @@ %%% Created : 16 Jan 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_redis.erl b/src/mod_proxy65_redis.erl index 99eda70bd..a3f7bb5a7 100644 --- a/src/mod_proxy65_redis.erl +++ b/src/mod_proxy65_redis.erl @@ -3,7 +3,7 @@ %%% Created : 31 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_riak.erl b/src/mod_proxy65_riak.erl index 543015654..ec1015772 100644 --- a/src/mod_proxy65_riak.erl +++ b/src/mod_proxy65_riak.erl @@ -3,7 +3,7 @@ %%% Created : 15 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 9510ff4b2..433371240 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Evgeniy Khramtsov <xram@jabber.ru> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_sql.erl b/src/mod_proxy65_sql.erl index 0f51adb55..20fed2209 100644 --- a/src/mod_proxy65_sql.erl +++ b/src/mod_proxy65_sql.erl @@ -3,7 +3,7 @@ %%% Created : 30 Mar 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl index 668817868..7e5c180ae 100644 --- a/src/mod_proxy65_stream.erl +++ b/src/mod_proxy65_stream.erl @@ -4,7 +4,7 @@ %%% Purpose : Bytestream process. %%% Created : 12 Oct 2006 by Evgeniy Khramtsov <xram@jabber.ru> %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 72edea9ce..b332dd321 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_push.erl b/src/mod_push.erl index 5e75e0f9d..1a12f6029 100644 --- a/src/mod_push.erl +++ b/src/mod_push.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jul 2017 by Holger Weiss <holger@zedat.fu-berlin.de> %%% %%% -%%% ejabberd, Copyright (C) 2017-2018 ProcessOne +%%% ejabberd, Copyright (C) 2017-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -441,14 +441,32 @@ notify(#{jid := #jid{luser = LUser, lserver = LServer}, notify(LUser, LServer, Clients, Pkt, Dir) -> lists:foreach( fun({TS, PushLJID, Node, XData}) -> - HandleResponse = fun(#iq{type = result}) -> - ok; - (#iq{type = error}) -> - spawn(?MODULE, delete_session, - [LUser, LServer, TS]); - (timeout) -> - ok % Hmm. - end, + HandleResponse = + fun(#iq{type = result}) -> + ?DEBUG("~s accepted notification for ~s@~s (~s)", + [jid:encode(PushLJID), LUser, LServer, Node]); + (#iq{type = error} = IQ) -> + case inspect_error(IQ) of + {wait, Reason} -> + ?INFO_MSG("~s rejected notification for " + "~s@~s (~s) temporarily: ~s", + [jid:encode(PushLJID), LUser, + LServer, Node, Reason]); + {Type, Reason} -> + spawn(?MODULE, delete_session, + [LUser, LServer, TS]), + ?WARNING_MSG("~s rejected notification for " + "~s@~s (~s), disabling push: ~s " + "(~s)", + [jid:encode(PushLJID), LUser, + LServer, Node, Reason, Type]) + end; + (timeout) -> + ?DEBUG("Timeout sending notification for ~s@~s (~s) " + "to ~s", + [LUser, LServer, Node, jid:encode(PushLJID)]), + ok % Hmm. + end, notify(LServer, PushLJID, Node, XData, Pkt, Dir, HandleResponse) end, Clients). @@ -667,6 +685,15 @@ get_body_text(#message{body = Body} = Msg) -> body_is_encrypted(#message{sub_els = SubEls}) -> lists:keyfind(<<"encrypted">>, #xmlel.name, SubEls) /= false. +-spec inspect_error(iq()) -> {atom(), binary()}. +inspect_error(IQ) -> + case xmpp:get_error(IQ) of + #stanza_error{type = Type} = Err -> + {Type, xmpp:format_stanza_error(Err)}; + undefined -> + {undefined, <<"unrecognized error">>} + end. + %%-------------------------------------------------------------------- %% Caching. %%-------------------------------------------------------------------- diff --git a/src/mod_push_keepalive.erl b/src/mod_push_keepalive.erl index 779fd0006..a7a7d8c92 100644 --- a/src/mod_push_keepalive.erl +++ b/src/mod_push_keepalive.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jul 2017 by Holger Weiss <holger@zedat.fu-berlin.de> %%% %%% -%%% ejabberd, Copyright (C) 2017-2018 ProcessOne +%%% ejabberd, Copyright (C) 2017-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_push_mnesia.erl b/src/mod_push_mnesia.erl index 3b7f9aae4..ee3891e07 100644 --- a/src/mod_push_mnesia.erl +++ b/src/mod_push_mnesia.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jul 2017 by Holger Weiss <holger@zedat.fu-berlin.de> %%% %%% -%%% ejabberd, Copyright (C) 2017-2018 ProcessOne +%%% ejabberd, Copyright (C) 2017-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_push_sql.erl b/src/mod_push_sql.erl index 5879e163a..50ad30684 100644 --- a/src/mod_push_sql.erl +++ b/src/mod_push_sql.erl @@ -5,7 +5,7 @@ %%% Created : 26 Oct 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2017-2018 ProcessOne +%%% ejabberd, Copyright (C) 2017-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_register.erl b/src/mod_register.erl index 3785c9c00..841053a43 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -5,7 +5,7 @@ %%% Created : 8 Dec 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index ae659ddc8..1e188d333 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -5,7 +5,7 @@ %%% Created : 4 May 2008 by Badlop <badlop@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 1f42b69e0..c67f5bb32 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -5,7 +5,7 @@ %%% Created : 11 Dec 2002 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -53,14 +53,11 @@ depends/2]). -include("logger.hrl"). - -include("xmpp.hrl"). - -include("mod_roster.hrl"). - -include("ejabberd_http.hrl"). - -include("ejabberd_web_admin.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(ROSTER_CACHE, roster_cache). -define(ROSTER_ITEM_CACHE, roster_item_cache). @@ -231,7 +228,7 @@ roster_version(LServer, LUser) -> case roster_version_on_db(LServer) of true -> case read_roster_version(LUser, LServer) of - error -> not_found; + error -> undefined; {ok, V} -> V end; false -> @@ -320,10 +317,9 @@ process_iq_get(#iq{to = To, lang = Lang, #roster_query{items = Items, ver = Version} end) - catch E:R -> - St = erlang:get_stacktrace(), + catch ?EX_RULE(E, R, St) -> ?ERROR_MSG("failed to process roster get for ~s: ~p", - [jid:encode(To), {E, {R, St}}]), + [jid:encode(To), {E, {R, ?EX_STACK(St)}}]), Txt = <<"Roster module has failed">>, xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang)) end. @@ -481,7 +477,8 @@ push_item(To, OldItem, NewItem) -> #jid{luser = LUser, lserver = LServer} = To, Ver = case roster_versioning_enabled(LServer) of true -> roster_version(LServer, LUser); - false -> undefined + false -> undefined; + undefined -> undefined end, lists:foreach( fun(Resource) -> diff --git a/src/mod_roster_mnesia.erl b/src/mod_roster_mnesia.erl index 01e671b43..c67d7d5e4 100644 --- a/src/mod_roster_mnesia.erl +++ b/src/mod_roster_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_roster_riak.erl b/src/mod_roster_riak.erl index 1f65d384c..d267856c3 100644 --- a/src/mod_roster_riak.erl +++ b/src/mod_roster_riak.erl @@ -4,7 +4,7 @@ %%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_roster_sql.erl b/src/mod_roster_sql.erl index 85019e21d..91242f610 100644 --- a/src/mod_roster_sql.erl +++ b/src/mod_roster_sql.erl @@ -4,7 +4,7 @@ %%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_s2s_dialback.erl b/src/mod_s2s_dialback.erl index ff4174ebf..55854a82b 100644 --- a/src/mod_s2s_dialback.erl +++ b/src/mod_s2s_dialback.erl @@ -2,7 +2,7 @@ %%% Created : 16 Dec 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_service_log.erl b/src/mod_service_log.erl index d8c9c565e..62b5e289f 100644 --- a/src/mod_service_log.erl +++ b/src/mod_service_log.erl @@ -5,7 +5,7 @@ %%% Created : 24 Aug 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 79b782e17..d80258db7 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -5,7 +5,7 @@ %%% Created : 5 Mar 2005 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -303,10 +303,10 @@ get_jid_info({Subscription, Ask, Groups}, User, Server, US1 = {U1, S1}, DisplayedGroups = get_user_displayed_groups(US), SRUsers = lists:foldl(fun (Group, Acc1) -> + GroupName = get_group_name(LServer, Group), lists:foldl(fun (User1, Acc2) -> dict:append(User1, - get_group_name(LServer, - Group), + GroupName, Acc2) end, Acc1, @@ -451,18 +451,24 @@ get_group_name(Host1, Group1) -> %% Get list of names of groups that have @all@/@online@/etc in the memberlist get_special_users_groups(Host) -> - lists:filter(fun (Group) -> - get_group_opt(Host, Group, all_users, false) orelse - get_group_opt(Host, Group, online_users, false) - end, - list_groups(Host)). + lists:filtermap(fun ({Group, Opts}) -> + case proplists:get_value(all_users, Opts, false) orelse + proplists:get_value(online_users, Opts, false) of + true -> {true, Group}; + false -> false + end + end, + groups_with_opts(Host)). %% Get list of names of groups that have @online@ in the memberlist get_special_users_groups_online(Host) -> - lists:filter(fun (Group) -> - get_group_opt(Host, Group, online_users, false) - end, - list_groups(Host)). + lists:filtermap(fun ({Group, Opts}) -> + case proplists:get_value(online_users, Opts, false) of + true -> {true, Group}; + false -> false + end + end, + groups_with_opts(Host)). %% Given two lists of groupnames and their options, %% return the list of displayed groups to the second list @@ -656,8 +662,13 @@ push_user_to_group(LUser, LServer, Group, Host, when (U == LUser) and (S == LServer) -> ok; ({U, S}) -> - push_roster_item(U, S, LUser, LServer, GroupName, - Subscription) + case lists:member(S, ejabberd_config:get_myhosts()) of + true -> + push_roster_item(U, S, LUser, LServer, GroupName, + Subscription); + _ -> + ok + end end, get_group_users(Host, Group)). diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index b50ad93d0..327ec0a9d 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -7,7 +7,7 @@ %%% Created : 5 Mar 2005 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_shared_roster_mnesia.erl b/src/mod_shared_roster_mnesia.erl index 2995c2230..a54b9687f 100644 --- a/src/mod_shared_roster_mnesia.erl +++ b/src/mod_shared_roster_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_shared_roster_riak.erl b/src/mod_shared_roster_riak.erl index 94ed737ec..87bdd80c1 100644 --- a/src/mod_shared_roster_riak.erl +++ b/src/mod_shared_roster_riak.erl @@ -4,7 +4,7 @@ %%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_shared_roster_sql.erl b/src/mod_shared_roster_sql.erl index 00714fca9..39ca9fb0d 100644 --- a/src/mod_shared_roster_sql.erl +++ b/src/mod_shared_roster_sql.erl @@ -4,7 +4,7 @@ %%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_sic.erl b/src/mod_sic.erl index 765b9adcd..3ca8e6da9 100644 --- a/src/mod_sic.erl +++ b/src/mod_sic.erl @@ -5,7 +5,7 @@ %%% Created : 6 Mar 2010 by Karim Gemayel <karim.gemayel@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_sip.erl b/src/mod_sip.erl index 814b9df6f..3cb2ac13e 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -5,7 +5,7 @@ %%% Created : 21 Apr 2014 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2014-2018 ProcessOne +%%% ejabberd, Copyright (C) 2014-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl index 3ee0a6fee..5efc238e0 100644 --- a/src/mod_sip_proxy.erl +++ b/src/mod_sip_proxy.erl @@ -5,7 +5,7 @@ %%% Created : 21 Apr 2014 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2014-2018 ProcessOne +%%% ejabberd, Copyright (C) 2014-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_sip_registrar.erl b/src/mod_sip_registrar.erl index dfb9a50f0..787ec0cb8 100644 --- a/src/mod_sip_registrar.erl +++ b/src/mod_sip_registrar.erl @@ -5,7 +5,7 @@ %%% Created : 23 Apr 2014 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2014-2018 ProcessOne +%%% ejabberd, Copyright (C) 2014-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_stats.erl b/src/mod_stats.erl index 706c22a70..772d51098 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -5,7 +5,7 @@ %%% Created : 11 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_stream_mgmt.erl b/src/mod_stream_mgmt.erl index 5adeaf8c2..4c38b87af 100644 --- a/src/mod_stream_mgmt.erl +++ b/src/mod_stream_mgmt.erl @@ -3,7 +3,7 @@ %%% Created : 25 Dec 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_time.erl b/src/mod_time.erl index 78c75f8af..6c4a0bae5 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -6,7 +6,7 @@ %%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 39da3472e..5caecae50 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -5,7 +5,7 @@ %%% Created : 2 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index acfd0a052..2d00d4465 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -4,7 +4,7 @@ %%% Created : 29 Jul 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_vcard_mnesia.erl b/src/mod_vcard_mnesia.erl index af361dbb3..31e9f6d43 100644 --- a/src/mod_vcard_mnesia.erl +++ b/src/mod_vcard_mnesia.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_vcard_riak.erl b/src/mod_vcard_riak.erl index 49a303c88..ec43cc8d1 100644 --- a/src/mod_vcard_riak.erl +++ b/src/mod_vcard_riak.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_vcard_sql.erl b/src/mod_vcard_sql.erl index 57d2052a0..93ef2e948 100644 --- a/src/mod_vcard_sql.erl +++ b/src/mod_vcard_sql.erl @@ -4,7 +4,7 @@ %%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index 2f3853357..a674598b8 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -5,7 +5,7 @@ %%% Created : 9 Mar 2007 by Igor Goryachev <igor@goryachev.org> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_version.erl b/src/mod_version.erl index da0f736eb..7c1f28aea 100644 --- a/src/mod_version.erl +++ b/src/mod_version.erl @@ -5,7 +5,7 @@ %%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_buddy.erl b/src/node_buddy.erl index 485675253..a975cb3eb 100644 --- a/src/node_buddy.erl +++ b/src/node_buddy.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_club.erl b/src/node_club.erl index 8aa8380a2..953aca117 100644 --- a/src/node_club.erl +++ b/src/node_club.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_dag.erl b/src/node_dag.erl index 9d84c484e..d1d8ccd8e 100644 --- a/src/node_dag.erl +++ b/src/node_dag.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jun 2009 by Brian Cully <bjc@kublai.com> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_dispatch.erl b/src/node_dispatch.erl index 1cc96c22a..d0c1b6165 100644 --- a/src/node_dispatch.erl +++ b/src/node_dispatch.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_flat.erl b/src/node_flat.erl index 11e0785c0..2c0d7869a 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_flat_sql.erl b/src/node_flat_sql.erl index ebe164a15..cdf7fe3a9 100644 --- a/src/node_flat_sql.erl +++ b/src/node_flat_sql.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_hometree.erl b/src/node_hometree.erl index 1e4bc0cf7..c55c696f4 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_hometree_sql.erl b/src/node_hometree_sql.erl index c2776e126..8e0a8f281 100644 --- a/src/node_hometree_sql.erl +++ b/src/node_hometree_sql.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_mb.erl b/src/node_mb.erl index 615ccadec..9042f27cf 100644 --- a/src/node_mb.erl +++ b/src/node_mb.erl @@ -5,7 +5,7 @@ %%% Created : 25 Sep 2008 by Eric Cestari <ecestari@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_mb_sql.erl b/src/node_mb_sql.erl index 78122b72d..bc06be24d 100644 --- a/src/node_mb_sql.erl +++ b/src/node_mb_sql.erl @@ -5,7 +5,7 @@ %%% Created : 6 Sep 2016 by Holger Weiss <holger@zedat.fu-berlin.de> %%% %%% -%%% ejabberd, Copyright (C) 2016-2018 ProcessOne +%%% ejabberd, Copyright (C) 2016-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_mix.erl b/src/node_mix.erl index 0cd6f84e9..4d2741a5e 100644 --- a/src/node_mix.erl +++ b/src/node_mix.erl @@ -4,7 +4,7 @@ %%% Created : 8 Mar 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_mix_sql.erl b/src/node_mix_sql.erl index 4ac01c62e..961d34da8 100644 --- a/src/node_mix_sql.erl +++ b/src/node_mix_sql.erl @@ -4,7 +4,7 @@ %%% Created : 8 Mar 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_online.erl b/src/node_online.erl index a9a39be3b..0bdcb60c3 100644 --- a/src/node_online.erl +++ b/src/node_online.erl @@ -5,7 +5,7 @@ %%% Created : 15 Dec 2015 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_pep.erl b/src/node_pep.erl index e98cde81b..3baafc10d 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_pep_sql.erl b/src/node_pep_sql.erl index e5ceb1e8c..4e6dd4872 100644 --- a/src/node_pep_sql.erl +++ b/src/node_pep_sql.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_private.erl b/src/node_private.erl index 22f966dbd..d98669372 100644 --- a/src/node_private.erl +++ b/src/node_private.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_public.erl b/src/node_public.erl index 63468dbf3..28dafa791 100644 --- a/src/node_public.erl +++ b/src/node_public.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/nodetree_dag.erl b/src/nodetree_dag.erl index 93f414f31..1185ed817 100644 --- a/src/nodetree_dag.erl +++ b/src/nodetree_dag.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jun 2009 by Brian Cully <bjc@kublai.com> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/nodetree_tree.erl b/src/nodetree_tree.erl index c0da117b0..084fa322a 100644 --- a/src/nodetree_tree.erl +++ b/src/nodetree_tree.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/nodetree_tree_sql.erl b/src/nodetree_tree_sql.erl index c311ea3ab..311bbbf07 100644 --- a/src/nodetree_tree_sql.erl +++ b/src/nodetree_tree_sql.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/nodetree_virtual.erl b/src/nodetree_virtual.erl index 4d0485eff..c27efe44b 100644 --- a/src/nodetree_virtual.erl +++ b/src/nodetree_virtual.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/prosody2ejabberd.erl b/src/prosody2ejabberd.erl index b8d9f4da1..3fc3cc8b5 100644 --- a/src/prosody2ejabberd.erl +++ b/src/prosody2ejabberd.erl @@ -4,7 +4,7 @@ %%% Created : 20 Jan 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -189,7 +189,11 @@ convert_data(Host, "vcard", User, [Data]) -> ok end; convert_data(_Host, "config", _User, [Data]) -> - RoomJID = jid:decode(proplists:get_value(<<"jid">>, Data, <<"">>)), + RoomJID1 = case proplists:get_value(<<"jid">>, Data, not_found) of + not_found -> proplists:get_value(<<"_jid">>, Data, room_jid_not_found); + A when is_binary(A) -> A + end, + RoomJID = jid:decode(RoomJID1), Config = proplists:get_value(<<"_data">>, Data, []), RoomCfg = convert_room_config(Data), case proplists:get_bool(<<"persistent">>, Config) of @@ -303,22 +307,24 @@ convert_roster_item(LUser, LServer, JIDstring, LuaList) -> InitR = #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID}, - Roster = - lists:foldl( - fun({<<"groups">>, Val}, R) -> + lists:foldl( + fun({<<"groups">>, Val}, [R]) -> Gs = lists:flatmap( fun({G, true}) -> [G]; (_) -> [] end, Val), - R#roster{groups = Gs}; - ({<<"subscription">>, Sub}, R) -> - R#roster{subscription = misc:binary_to_atom(Sub)}; - ({<<"ask">>, <<"subscribe">>}, R) -> - R#roster{ask = out}; - ({<<"name">>, Name}, R) -> - R#roster{name = Name} - end, InitR, LuaList), - [Roster] + [R#roster{groups = Gs}]; + ({<<"subscription">>, Sub}, [R]) -> + [R#roster{subscription = misc:binary_to_atom(Sub)}]; + ({<<"ask">>, <<"subscribe">>}, [R]) -> + [R#roster{ask = out}]; + ({<<"name">>, Name}, [R]) -> + [R#roster{name = Name}]; + ({<<"persist">>, false}, _) -> + []; + (_, []) -> + [] + end, [InitR], LuaList) catch _:{bad_jid, _} -> [] end. @@ -358,9 +364,11 @@ convert_room_config(Data) -> end, [{affiliations, convert_room_affiliations(Data)}, {allow_change_subj, proplists:get_bool(<<"changesubject">>, Config)}, + {mam, proplists:get_bool(<<"archiving">>, Config)}, {description, proplists:get_value(<<"description">>, Config, <<"">>)}, {members_only, proplists:get_bool(<<"members_only">>, Config)}, {moderated, proplists:get_bool(<<"moderated">>, Config)}, + {persistent, proplists:get_bool(<<"persistent">>, Config)}, {anonymous, Anonymous}] ++ Pass ++ Subj. convert_privacy_item({_, Item}) -> @@ -517,6 +525,11 @@ el_to_offline_msg(LUser, LServer, #xmlel{attrs = Attrs} = El) -> deserialize(L) -> deserialize(L, #xmlel{}, []). +deserialize([{Other, _}|T], El, Acc) + when (Other == <<"key">>) + or (Other == <<"when">>) + or (Other == <<"with">>) -> + deserialize(T, El, Acc); deserialize([{<<"attr">>, Attrs}|T], El, Acc) -> deserialize(T, El#xmlel{attrs = Attrs ++ El#xmlel.attrs}, Acc); deserialize([{<<"name">>, Name}|T], El, Acc) -> diff --git a/src/proxy_protocol.erl b/src/proxy_protocol.erl index 2103a4004..5c33b130d 100644 --- a/src/proxy_protocol.erl +++ b/src/proxy_protocol.erl @@ -5,7 +5,7 @@ %%% Created : 27 Nov 2018 by Paweł Chmielowski <pawel@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_db_sql.erl b/src/pubsub_db_sql.erl index 6a13054a8..a709ce8b2 100644 --- a/src/pubsub_db_sql.erl +++ b/src/pubsub_db_sql.erl @@ -5,7 +5,7 @@ %%% Created : 7 Aug 2009 by Pablo Polvorin <pablo.polvorin@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_index.erl b/src/pubsub_index.erl index 9c80e265f..de71b6395 100644 --- a/src/pubsub_index.erl +++ b/src/pubsub_index.erl @@ -5,7 +5,7 @@ %%% Created : 30 Apr 2009 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_migrate.erl b/src/pubsub_migrate.erl index 0728da765..da7d5b997 100644 --- a/src/pubsub_migrate.erl +++ b/src/pubsub_migrate.erl @@ -5,7 +5,7 @@ %%% Created : 26 Jul 2014 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl index 615ab322f..88a19c3c6 100644 --- a/src/pubsub_subscription.erl +++ b/src/pubsub_subscription.erl @@ -5,7 +5,7 @@ %%% Created : 29 May 2009 by Brian Cully <bjc@kublai.com> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_subscription_sql.erl b/src/pubsub_subscription_sql.erl index 2fcfb0f19..194b2676a 100644 --- a/src/pubsub_subscription_sql.erl +++ b/src/pubsub_subscription_sql.erl @@ -6,7 +6,7 @@ %%% Created : 7 Aug 2009 by Pablo Polvorin <pablo.polvorin@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/rest.erl b/src/rest.erl index 16fa20eb0..8aab0a5ae 100644 --- a/src/rest.erl +++ b/src/rest.erl @@ -5,7 +5,7 @@ %%% Created : 16 Oct 2014 by Christophe Romain <christophe.romain@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/str.erl b/src/str.erl index b314acf5b..bbf0d6a6e 100644 --- a/src/str.erl +++ b/src/str.erl @@ -5,7 +5,7 @@ %%% Created : 23 Feb 2012 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/translate.erl b/src/translate.erl index 5a1e13e82..b2c3e4481 100644 --- a/src/translate.erl +++ b/src/translate.erl @@ -5,7 +5,7 @@ %%% Created : 6 Jan 2003 by Alexey Shchepin <alexey@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/win32_dns.erl b/src/win32_dns.erl index fe1ba5395..dcb1d34eb 100644 --- a/src/win32_dns.erl +++ b/src/win32_dns.erl @@ -5,7 +5,7 @@ %%% Created : 5 Mar 2009 by Geoff Cant %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/xml_compress.erl b/src/xml_compress.erl index 673b25c14..a85ec56b2 100644 --- a/src/xml_compress.erl +++ b/src/xml_compress.erl @@ -506,8 +506,8 @@ decode_child(<<2:8, Rest/binary>>, PNs, J1, J2) -> {Children, Rest4} = decode_children(Rest3, PNs, J1, J2), {{xmlel, Name, Attrs, Children}, Rest4}; decode_child(<<3:8, Rest/binary>>, PNs, J1, J2) -> - {Name, Rest2} = decode_string(Rest), - {Ns, Rest3} = decode_string(Rest2), + {Ns, Rest2} = decode_string(Rest), + {Name, Rest3} = decode_string(Rest2), {Attrs, Rest4} = decode_attrs(Rest3), {Children, Rest5} = decode_children(Rest4, Ns, J1, J2), {{xmlel, Name, add_ns(PNs, Ns, Attrs), Children}, Rest5}; diff --git a/test/acl_test.exs b/test/acl_test.exs deleted file mode 100644 index ee2b37ab9..000000000 --- a/test/acl_test.exs +++ /dev/null @@ -1,389 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule ACLTest do - @author "mremond@process-one.net" - - use ExUnit.Case, async: false - - setup_all do - :ok = :mnesia.start - :ejabberd_mnesia.start - :jid.start - :ejabberd_hooks.start_link - :stringprep.start - :ok = :ejabberd_config.start(["domain1", "domain2"], []) - {:ok, _} = :acl.start_link - :ok - end - - setup do - :acl.clear - end - - test "access rule match with user part ACL" do - :acl.add(:global, :basic_acl_1, {:user, "test1"}) - :acl.add(:global, :basic_acl_1, {:user, "test2"}) - :acl.add_access(:global, :basic_rule_1, [{:allow, [{:acl, :basic_acl_1}]}]) - # JID can only be passes as jid record. - # => TODO: Support passing JID as binary. - assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test1@domain1")) == :allow - assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test1@domain2")) == :allow - assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test2@domain1")) == :allow - assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test2@domain2")) == :allow - # We match on user part only for local domain. As an implicit rule remote domain are not matched - assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test1@otherdomain")) == :deny - assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test2@otherdomain")) == :deny - assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test11@domain1")) == :deny - - :acl.add(:global, :basic_acl_2, {:user, {"test2", "domain1"}}) - :acl.add_access(:global, :basic_rule_2, [{:allow, [{:acl, :basic_acl_2}]}]) - assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@domain1")) == :allow - assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@domain2")) == :deny - assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@otherdomain")) == :deny - assert :acl.match_rule(:global, :basic_rule_2, {127,0,0,1}) == :deny - end - - test "IP based ACL" do - :acl.add(:global, :ip_acl_1, {:ip, "127.0.0.0/24"}) - :acl.add_access(:global, :ip_rule_1, [{:allow, [{:acl, :ip_acl_1}]}]) - # IP must be expressed as a tuple when calling match rule - assert :acl.match_rule(:global, :ip_rule_1, {127,0,0,1}) == :allow - assert :acl.match_rule(:global, :ip_rule_1, {127,0,1,1}) == :deny - assert :acl.match_rule(:global, :ip_rule_1, :jid.from_string("test1@domain1")) == :deny - end - - test "Access rule are evaluated sequentially" do - :acl.add(:global, :user_acl_1, {:user, {"test1", "domain2"}}) - :acl.add(:global, :user_acl_2, {:user, "test1"}) - :acl.add_access(:global, :user_rule_1, [{:deny, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :user_acl_2}]}]) - assert :acl.match_rule(:global, :user_rule_1, :jid.from_string("test1@domain1")) == :allow - assert :acl.match_rule(:global, :user_rule_1, :jid.from_string("test1@domain2")) == :deny - end - - # Access rules are sometimes used to provide values (i.e.: max_s2s_connections, max_user_sessions) - test "Access rules providing values" do - :acl.add(:global, :user_acl, {:user_regexp, ""}) - :acl.add(:global, :admin_acl, {:user, "admin"}) - :acl.add_access(:global, :value_rule_1, [{10, [{:acl, :admin_acl}]}, {5, [{:acl, :user_acl}]}]) - assert :acl.match_rule(:global, :value_rule_1, :jid.from_string("test1@domain1")) == 5 - assert :acl.match_rule(:global, :value_rule_1, :jid.from_string("admin@domain1")) == 10 - - # If we have no match, :deny is still the default value - # => TODO maybe we should have a match rule which allow passing custom default value ? - assert :acl.match_rule(:global, :value_rule_1, :jid.from_string("user@otherdomain")) == :deny - end - - - # At the moment IP and user rules to no go well together: There is - # no way to combine IP and user restrictions. - # => TODO we need to implement access rules that implement both and will deny the access - # if either IP or user returns deny - test "mixing IP and user access rules" do - :acl.add(:global, :user_acl_1, {:user, "test1"}) - :acl.add(:global, :ip_acl_1, {:ip, "127.0.0.0/24"}) - :acl.add_access(:global, :mixed_rule_1, [{:allow, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :ip_acl_1}]}]) - assert :acl.match_rule(:global, :mixed_rule_1, :jid.from_string("test1@domain1")) == :allow - assert :acl.match_rule(:global, :mixed_rule_1, {127,0,0,1}) == :allow - - :acl.add_access(:global, :mixed_rule_2, [{:deny, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :ip_acl_1}]}]) - assert :acl.match_rule(:global, :mixed_rule_2, :jid.from_string("test1@domain1")) == :deny - assert :acl.match_rule(:global, :mixed_rule_2, {127,0,0,1}) == :allow - end - - test "access_matches works with predefined access rules" do - :acl.add(:global, :user_acl_2, {:user, "user"}) - :acl.add_access(:global, :user_rule_2, [{:allow, [{:acl, :user_acl_2}]}, {:deny, [:all]}]) - - assert :acl.access_matches(:user_rule_2, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - assert :acl.access_matches(:user_rule_2, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches rule all always matches" do - assert :acl.access_matches(:all, %{}, :global) == :allow - assert :acl.access_matches(:all, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - end - - test "access_matches rule none never matches" do - assert :acl.access_matches(:none, %{}, :global) == :deny - assert :acl.access_matches(:none, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches with not existing rule never matches" do - assert :acl.access_matches(:bleble, %{}, :global) == :deny - assert :acl.access_matches(:bleble, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches works with inlined access rules" do - :acl.add(:global, :user_acl_3, {:user, "user"}) - - assert :acl.access_matches([{:allow, [{:acl, :user_acl_3}]}, {:deny, [:all]}], - %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - assert :acl.access_matches([{:allow, [{:acl, :user_acl_3}]}, {:deny, [:all]}], - %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches allow to have acl rules inlined" do - assert :acl.access_matches([{:allow, [{:user, "user"}]}, {:deny, [:all]}], - %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - assert :acl.access_matches([{:allow, [{:user, "user"}]}, {:deny, [:all]}], - %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches test have implicit deny at end" do - assert :acl.access_matches([{:allow, [{:user, "user"}]}], - %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - assert :acl.access_matches([{:allow, [{:user, "user"}]}], - %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches requires that all subrules match" do - rules = [{:allow, [{:user, "user"}, {:ip, {{127,0,0,1}, 32}}]}] - assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,2}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches rules are matched in order" do - rules = [{:allow, [{:user, "user"}]}, {:deny, [{:user, "user2"}]}, {:allow, [{:user_regexp, "user"}]}] - assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user22", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - end - - test "access_matches rules that require ip but no one is provided don't crash" do - rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]}, - {:allow, [{:user, "user"}]}, - {:allow, [{:user, "user2"}, {:ip, {{127,0,0,1}, 32}}]}] - assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}}, :global) == :deny - end - - test "access_matches rules that require usr but no one is provided don't crash" do - rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]}, - {:allow, [{:user, "user"}]}, - {:allow, [{:user, "user2"}, {:ip, {{127,0,0,2}, 32}}]}] - assert :acl.access_matches(rules, %{ip: {127,0,0,1}}, :global) == :allow - assert :acl.access_matches(rules, %{ip: {127,0,0,2}}, :global) == :deny - end - - test "access_matches rules with all always matches" do - rules = [{:allow, [:all]}, {:deny, {:user, "user"}}] - assert :acl.access_matches(rules, %{}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - end - - test "access_matches rules with {acl, all} always matches" do - rules = [{:allow, [{:acl, :all}]}, {:deny, {:user, "user"}}] - assert :acl.access_matches(rules, %{}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow - end - - test "access_matches rules with none never matches" do - rules = [{:allow, [:none]}, {:deny, [:all]}] - assert :acl.access_matches(rules, %{}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches with no rules never matches" do - assert :acl.access_matches([], %{}, :global) == :deny - assert :acl.access_matches([], %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny - end - - test "access_matches ip rule accepts {ip, port}" do - rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]}] - assert :acl.access_matches(rules, %{ip: {{127,0,0,1}, 5000}}, :global) == :allow - assert :acl.access_matches(rules, %{ip: {{127,0,0,2}, 5000}}, :global) == :deny - end - - test "access_matches user rule works" do - rules = [{:allow, [{:user, "user1"}]}] - assert :acl.access_matches(rules, %{usr: {"user1", "domain1", ""}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user1", "domain3", ""}}, :global) == :deny - end - - test "access_matches 2 arg user rule works" do - rules = [{:allow, [{:user, {"user1", "server1"}}]}] - assert :acl.access_matches(rules, %{usr: {"user1", "server1", ""}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user1", "server2", ""}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user2", "server1", ""}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user2", "server2", ""}}, :global) == :deny - end - - test "access_matches server rule works" do - rules = [{:allow, [{:server, "server1"}]}] - assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "server2", ""}}, :global) == :deny - end - - test "access_matches resource rule works" do - rules = [{:allow, [{:resource, "res1"}]}] - assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res2"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow - end - - test "access_matches user_regexp rule works" do - rules = [{:allow, [{:user_regexp, "user[0-9]"}]}] - assert :acl.access_matches(rules, %{usr: {"user1", "domain1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"userA", "domain1", "res1"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user1", "domain3", "res1"}}, :global) == :deny - end - - test "access_matches 2 arg user_regexp rule works" do - rules = [{:allow, [{:user_regexp, {"user[0-9]", "server1"}}]}] - assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"userA", "server1", "res1"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user1", "server2", "res1"}}, :global) == :deny - end - - test "access_matches server_regexp rule works" do - rules = [{:allow, [{:server_regexp, "server[0-9]"}]}] - assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "serverA", ""}}, :global) == :deny - end - - test "access_matches resource_regexp rule works" do - rules = [{:allow, [{:resource_regexp, "res[0-9]"}]}] - assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "domain1", "resA"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow - end - - test "access_matches node_regexp rule works" do - rules = [{:allow, [{:node_regexp, {"user[0-9]", "server[0-9]"}}]}] - assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"userA", "server1", "res1"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user1", "serverA", "res1"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"userA", "serverA", "res1"}}, :global) == :deny - end - - test "access_matches user_glob rule works" do - rules = [{:allow, [{:user_glob, "user?"}]}] - assert :acl.access_matches(rules, %{usr: {"user1", "domain1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user11", "domain1", "res1"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user1", "domain3", "res1"}}, :global) == :deny - end - - test "access_matches 2 arg user_glob rule works" do - rules = [{:allow, [{:user_glob, {"user?", "server1"}}]}] - assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user11", "server1", "res1"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user1", "server2", "res1"}}, :global) == :deny - end - - test "access_matches server_glob rule works" do - rules = [{:allow, [{:server_glob, "server?"}]}] - assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "server11", ""}}, :global) == :deny - end - - test "access_matches resource_glob rule works" do - rules = [{:allow, [{:resource_glob, "res?"}]}] - assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res11"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow - end - - test "access_matches node_glob rule works" do - rules = [{:allow, [{:node_glob, {"user?", "server?"}}]}] - assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow - assert :acl.access_matches(rules, %{usr: {"user11", "server1", "res1"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user1", "server11", "res1"}}, :global) == :deny - assert :acl.access_matches(rules, %{usr: {"user11", "server11", "res1"}}, :global) == :deny - end - - test "transform_access_rules_config expands allow rule" do - assert :acl.transform_access_rules_config([:allow]) == [{:allow, [:all]}] - end - - test "transform_access_rules_config expands deny rule" do - assert :acl.transform_access_rules_config([:deny]) == [{:deny, [:all]}] - end - - test "transform_access_rules_config expands <integer> rule" do - assert :acl.transform_access_rules_config([100]) == [{100, [:all]}] - end - - test "transform_access_rules_config expands <shaper_name> rule" do - assert :acl.transform_access_rules_config([:fast]) == [{:fast, [:all]}] - end - - test "transform_access_rules_config expands allow: <acl_name> rule" do - assert :acl.transform_access_rules_config([{:allow, :test1}]) == [{:allow, [{:acl, :test1}]}] - end - - test "transform_access_rules_config expands deny: <acl_name> rule" do - assert :acl.transform_access_rules_config([{:deny, :test1}]) == [{:deny, [{:acl, :test1}]}] - end - - test "transform_access_rules_config expands integer: <acl_name> rule" do - assert :acl.transform_access_rules_config([{100, :test1}]) == [{100, [{:acl, :test1}]}] - end - - test "transform_access_rules_config expands <shaper_name>: <acl_name> rule" do - assert :acl.transform_access_rules_config([{:fast, :test1}]) == [{:fast, [{:acl, :test1}]}] - end - - test "transform_access_rules_config expands allow rule (no list)" do - assert :acl.transform_access_rules_config(:allow) == [{:allow, [:all]}] - end - - test "transform_access_rules_config expands deny rule (no list)" do - assert :acl.transform_access_rules_config(:deny) == [{:deny, [:all]}] - end - - test "transform_access_rules_config expands <integer> rule (no list)" do - assert :acl.transform_access_rules_config(100) == [{100, [:all]}] - end - - test "transform_access_rules_config expands <shaper_name> rule (no list)" do - assert :acl.transform_access_rules_config(:fast) == [{:fast, [:all]}] - end - - test "access_rules_validator works with <AccessName>" do - assert :acl.access_rules_validator(:my_access) == :my_access - end - - test "shapes_rules_validator works with <AccessName>" do - assert :acl.shaper_rules_validator(:my_access) == :my_access - end - - ## Checking ACL on both user pattern and IP - ## ======================================== - - # Typical example is mod_register - - # Deprecated approach - test "module can test both IP and user through two independent :acl.match_rule check (deprecated)" do - :acl.add(:global, :user_acl, {:user, {"test1", "domain1"}}) - :acl.add(:global, :ip_acl, {:ip, "127.0.0.0/24"}) - :acl.add_access(:global, :user_rule, [{:allow, [{:acl, :user_acl}]}]) - :acl.add_access(:global, :ip_rule, [{:allow, [{:acl, :ip_acl}]}]) - - # acl module in 16.03 is not able to provide a function for compound result: - assert :acl.match_rule(:global, :user_rule, :jid.from_string("test1@domain1")) == :allow - assert :acl.match_rule(:global, :ip_rule, {127,0,0,1}) == :allow - assert :acl.match_rule(:global, :user_rule, :jid.from_string("test2@domain1")) == :deny - assert :acl.match_rule(:global, :ip_rule, {127,0,1,1}) == :deny - end - -end diff --git a/test/announce_tests.erl b/test/announce_tests.erl index 7b621a3d1..1a08f317f 100644 --- a/test/announce_tests.erl +++ b/test/announce_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/carbons_tests.erl b/test/carbons_tests.erl index 55bbc9270..5142346c1 100644 --- a/test/carbons_tests.erl +++ b/test/carbons_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/csi_tests.erl b/test/csi_tests.erl index 2b346e275..027cd66c0 100644 --- a/test/csi_tests.erl +++ b/test/csi_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 1d8de7b8e..77e6ebdfb 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -3,7 +3,7 @@ %%% Created : 2 Jun 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -65,13 +65,13 @@ init_per_suite(Config) -> start_ejabberd(Config) -> case proplists:get_value(backends, Config) of all -> - ok = application:start(ejabberd, transient); + {ok, _} = application:ensure_all_started(ejabberd, transient); Backends when is_list(Backends) -> Hosts = lists:map(fun(Backend) -> Backend ++ ".localhost" end, Backends), application:load(ejabberd), AllHosts = Hosts ++ ["localhost"], %% We always need localhost for the generic no_db tests application:set_env(ejabberd, hosts, AllHosts), - ok = application:start(ejabberd, transient) + {ok, _} = application:ensure_all_started(ejabberd, transient) end. end_per_suite(_Config) -> diff --git a/test/ejabberd_admin_test.exs b/test/ejabberd_admin_test.exs deleted file mode 100644 index 1090eff17..000000000 --- a/test/ejabberd_admin_test.exs +++ /dev/null @@ -1,88 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule EjabberdAdminTest do - use ExUnit.Case, async: false - - @author "jsautret@process-one.net" - - setup_all do - :mnesia.start - :ejabberd_mnesia.start - # For some myterious reason, :ejabberd_commands.init mays - # sometimes fails if module is not loaded before - :ejabberd_config.start(["domain"], []) - {:module, :ejabberd_commands} = Code.ensure_loaded(:ejabberd_commands) - :ejabberd_hooks.start_link - {:ok, _} = :acl.start_link - {:ok, _} = :ejabberd_access_permissions.start_link() - :ejabberd_commands.start_link - :ejabberd_admin.start_link - :ok - end - - setup do - :ok - end - - test "Logvel can be set and retrieved" do - :ejabberd_logger.start() - - assert :lager == call_command(:set_loglevel, [1]) - assert {1, :critical, 'Critical'} == - call_command(:get_loglevel, []) - - assert :lager == call_command(:set_loglevel, [2]) - assert {2, :error, 'Error'} == - call_command(:get_loglevel, []) - - assert :lager == call_command(:set_loglevel, [3]) - assert {3, :warning, 'Warning'} == - call_command(:get_loglevel, []) - -# assert {:wrong_loglevel, 6} == -# catch_throw call_command(:set_loglevel, [6]) -# assert {3, :warning, 'Warning'} == -# call_command(:get_loglevel, []) - - assert :lager == call_command(:set_loglevel, [4]) - assert {4, :info, 'Info'} == - call_command(:get_loglevel, []) - - assert :lager == call_command(:set_loglevel, [5]) - assert {5, :debug, 'Debug'} == - call_command(:get_loglevel, []) - - assert :lager == call_command(:set_loglevel, [0]) - assert {0, :no_log, 'No log'} == - call_command(:get_loglevel, []) - - end - - defp call_command(name, args) do - :ejabberd_commands.execute_command2(name, args, %{:caller_module => :ejabberd_ctl}) - end - - test "command status works with ejabberd stopped" do - assert :ejabberd_not_running == - elem(call_command(:status, []), 0) - end - -end diff --git a/test/ejabberd_auth_mock.exs b/test/ejabberd_auth_mock.exs deleted file mode 100644 index 10daf03dc..000000000 --- a/test/ejabberd_auth_mock.exs +++ /dev/null @@ -1,74 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule EjabberdAuthMock do - - @author "jsautret@process-one.net" - @agent __MODULE__ - - def init do - try do - Agent.stop(@agent) - catch - :exit, _e -> :ok - end - - {:ok, _pid} = Agent.start_link(fn -> %{} end, name: @agent) - - mock(:ejabberd_auth, :user_exists, - fn (user, domain) -> - Agent.get(@agent, fn users -> Map.get(users, {user, domain}) end) != nil - end) - mock(:ejabberd_auth, :get_password_s, - fn (user, domain) -> - Agent.get(@agent, fn users -> Map.get(users, {user, domain}, "") end ) - end) - mock(:ejabberd_auth, :check_password, - fn (user, _authzid, domain, password) -> - Agent.get(@agent, fn users -> - Map.get(users, {user, domain}) end) == password - end) - mock(:ejabberd_auth, :set_password, - fn (user, domain, password) -> - Agent.update(@agent, fn users -> - Map.put(users, {user, domain}, password) end) - end) - end - - def create_user(user, domain, password) do - Agent.update(@agent, fn users -> Map.put(users, {user, domain}, password) end) - end - - #################################################################### - # Helpers - #################################################################### - - # TODO refactor: Move to ejabberd_test_mock - def mock(module, function, fun) do - try do - :meck.new(module) - catch - :error, {:already_started, _pid} -> :ok - end - - :meck.expect(module, function, fun) - end - -end diff --git a/test/ejabberd_hooks_test.exs b/test/ejabberd_hooks_test.exs deleted file mode 100644 index 90624147c..000000000 --- a/test/ejabberd_hooks_test.exs +++ /dev/null @@ -1,203 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -# Notes on the tests: -# -# This test suite will print out errors in logs for tests: -# -# test "Error in run_fold is ignored" -# test "Throw in run_fold is ignored" -# test "Exit in run_fold is ignored" -# -# Those tests are not failing and we can safely ignore those errors in -# log as we are exercising hook handler recovery from that situation. - -defmodule EjabberdHooksTest do - use ExUnit.Case, async: false - - @author "mremond@process-one.net" - @host <<"domain.net">> - @self __MODULE__ - - setup_all do - {:ok, _pid} = :ejabberd_hooks.start_link - :ok - end - - setup do - :meck.unload - :true = :ejabberd_hooks.delete_all_hooks - :ok - end - - test "An anonymous function can be added as a hook" do - hookname = :test_fun_hook - :ok = :ejabberd_hooks.add(hookname, @host, fn _ -> :ok end, 50) - [{50, :undefined, _}] = :ejabberd_hooks.get_handlers(hookname, @host) - end - - test "A module function can be added as a hook" do - hookname = :test_mod_hook - callback = :hook_callback - :ok = :ejabberd_hooks.add(hookname, @host, @self, callback, 40) - [{40, @self, _callback}] = :ejabberd_hooks.get_handlers(hookname, @host) - end - - test "An anonymous function can be removed from hook handlers" do - hookname = :test_fun_hook - anon_fun = fn _ -> :ok end - :ok = :ejabberd_hooks.add(hookname, @host, anon_fun, 50) - :ok = :ejabberd_hooks.delete(hookname, @host, anon_fun, 50) - [] = :ejabberd_hooks.get_handlers(hookname, @host) - end - - test "An module function can be removed from hook handlers" do - hookname = :test_mod_hook - callback = :hook_callback - :ok = :ejabberd_hooks.add(hookname, @host, @self, callback, 40) - :ok = :ejabberd_hooks.delete(hookname, @host, @self, callback, 40) - [] = :ejabberd_hooks.get_handlers(hookname, @host) - # TODO: Check that removed function is not call anymore - end - - test "'Run hook' call registered handler once" do - test_result = :hook_result - run_hook([], fn -> test_result end, test_result) - end - - test "'Run hook' can call registered handler with parameters" do - test_result = :hook_result_with_params - run_hook([:hook_params], fn _ -> test_result end, test_result) - end - - # TODO test "Several handlers are run in order by hook" - - test "Hook run chain is stopped when handler return 'stop'" do - # setup test - hookname = :test_mod_hook - modulename = :hook_module - mock(modulename, :hook_callback1, fn _ -> :stop end) - mock(modulename, :hook_callback2, fn _ -> :end_result end) - - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 50) - - :ok = :ejabberd_hooks.run(hookname, @host, [:hook_params]) - # callback2 is never run: - [{_pid, {^modulename, _callback, [:hook_params]}, :stop}] = :meck.history(modulename) - end - - test "Run fold hooks accumulate state in correct order through handlers" do - # setup test - hookname = :test_mod_hook - modulename = :hook_module - mock(modulename, :hook_callback1, fn(list, user) -> [user|list] end) - mock(modulename, :hook_callback2, fn(list, _user) -> ["jid2"|list] end) - - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback2, 50) - - ["jid2", "jid1"] = :ejabberd_hooks.run_fold(hookname, @host, [], ["jid1"]) - end - - test "Hook run_fold are executed based on priority order, not registration order" do - # setup test - hookname = :test_mod_hook - modulename = :hook_module - mock(modulename, :hook_callback1, fn(_acc) -> :first end) - mock(modulename, :hook_callback2, fn(_acc) -> :second end) - - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback2, 50) - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) - - :second = :ejabberd_hooks.run_fold(hookname, @host, :started, []) - # Both module have been called: - 2 = length(:meck.history(modulename)) - end - - # TODO: Test with ability to stop and return a value - test "Hook run_fold chain is stopped when handler return 'stop'" do - # setup test - hookname = :test_mod_hook - modulename = :hook_module - mock(modulename, :hook_callback1, fn(_acc) -> :stop end) - mock(modulename, :hook_callback2, fn(_acc) -> :executed end) - - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback2, 50) - - :stopped = :ejabberd_hooks.run_fold(hookname, @host, :started, []) - # Only one module has been called - [{_pid, {^modulename, :hook_callback1, [:started]}, :stop}] = :meck.history(modulename) - end - - test "Error in run_fold is ignored" do - run_fold_crash(fn(_acc) -> raise "crashed" end) - end - - test "Throw in run_fold is ignored" do - run_fold_crash(fn(_acc) -> throw :crashed end) - end - - test "Exit in run_fold is ignored" do - run_fold_crash(fn(_acc) -> exit :crashed end) - end - - # test for run hook with various number of params - def run_hook(params, fun, result) do - # setup test - hookname = :test_mod_hook - modulename = :hook_module - callback = :hook_callback - mock(modulename, callback, fun) - - # Then check - :ok = :ejabberd_hooks.add(hookname, @host, modulename, callback, 40) - :ok = :ejabberd_hooks.run(hookname, @host, params) - [{_pid, {^modulename, ^callback, ^params}, ^result}] = :meck.history(modulename) - end - - def run_fold_crash(crash_fun) do - # setup test - hookname = :test_mod_hook - modulename = :hook_module - mock(modulename, :hook_callback1, crash_fun) - mock(modulename, :hook_callback2, fn(_acc) -> :final end) - - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) - :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback2, 50) - - :final = :ejabberd_hooks.run_fold(hookname, @host, :started, []) - # Both handlers were called - 2 = length(:meck.history(modulename)) - end - - # TODO refactor: Move to ejabberd_test_mock - def mock(module, function, fun) do - try do - :meck.new(module, [:non_strict]) - catch - :error, {:already_started, _pid} -> :ok - end - - :meck.expect(module, function, fun) - end - -end diff --git a/test/ejabberd_oauth_mock.exs b/test/ejabberd_oauth_mock.exs deleted file mode 100644 index 8f1f11843..000000000 --- a/test/ejabberd_oauth_mock.exs +++ /dev/null @@ -1,50 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule EjabberdOauthMock do - - @author "jsautret@process-one.net" - - def init() do - :mnesia.start - :mnesia.create_table(:oauth_token, - [ram_copies: [node], - attributes: [:oauth_token, :us, :scope, :expire]]) - :application.start(:cache_tab) - :cache_tab.new(:oauth_token, - [{:max_size, 1000}, {:life_time, 3600}]) - end - - def get_token(user, domain, command, expiration \\ 3600) do - now = {megasecs, secs, _} = :os.timestamp - expire = 1000000 * megasecs + secs + expiration - :random.seed now - token = to_string :random.uniform(100000000) - - {:ok, _} = :ejabberd_oauth.associate_access_token(token, - [{"resource_owner", - {:user, user, domain}}, - {"scope", [to_string command]}, - {"expiry_time", expire}], - []) - token - end - -end diff --git a/test/ejabberd_sm_mock.exs b/test/ejabberd_sm_mock.exs deleted file mode 100644 index 9ac739ba5..000000000 --- a/test/ejabberd_sm_mock.exs +++ /dev/null @@ -1,121 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule EjabberdSmMock do - @author "jsautret@process-one.net" - - require Record - Record.defrecord :session, Record.extract(:session, from_lib: "ejabberd/include/ejabberd_sm.hrl") - Record.defrecord :jid, Record.extract(:jid, from_lib: "xmpp/include/jid.hrl") - - @agent __MODULE__ - - def init do - ModLastMock.init - - try do - Agent.stop(@agent) - catch - :exit, _e -> :ok - end - - {:ok, _pid} = Agent.start_link(fn -> [] end, name: @agent) - - mock(:ejabberd_sm, :get_user_resources, - fn (user, domain) -> for s <- get_sessions(user, domain), do: s.resource end) - - mock(:ejabberd_sm, :route, - fn (to, {:exit, _reason}) -> - user = jid(to, :user) - domain = jid(to, :server) - resource = jid(to, :resource) - disconnect_resource(user, domain, resource) - :ok - (_, _) -> :ok - end) - - end - - def connect_resource(user, domain, resource, - opts \\ [priority: 1, conn: :c2s]) do - Agent.update(@agent, fn sessions -> - session = %{user: user, domain: domain, resource: resource, - timestamp: :os.timestamp, pid: self, node: node, - auth_module: :ejabberd_auth, ip: :undefined, - priority: opts[:priority], conn: opts[:conn]} - [session | sessions] - end) - end - - def disconnect_resource(user, domain, resource) do - disconnect_resource(user, domain, resource, ModLastMock.now) - end - - def disconnect_resource(user, domain, resource, timestamp) do - Agent.update(@agent, fn sessions -> - for s <- sessions, - s.user != user or s.domain != domain or s.resource != resource, do: s - end) - ModLastMock.set_last user, domain, "", timestamp - end - - def get_sessions() do - Agent.get(@agent, fn sessions -> sessions end) - end - - def get_sessions(user, domain) do - Agent.get(@agent, fn sessions -> - for s <- sessions, s.user == user, s.domain == domain, do: s - end) - end - - def get_session(user, domain, resource) do - Agent.get(@agent, fn sessions -> - for s <- sessions, - s.user == user, s.domain == domain, s.resource == resource, do: s - end) - end - - def to_record(s) do - session(usr: {s.user, s.domain, s.ressource}, - us: {s.user, s.domain}, - sid: {s.timestamp, s.pid}, - priority: s.priority, - info: [conn: s.conn, ip: s.ip, node: s.node, - oor: false, auth_module: s.auth_module]) - end - - #################################################################### - # Helpers - #################################################################### - - - # TODO refactor: Move to ejabberd_test_mock - def mock(module, function, fun) do - try do - :meck.new(module) - catch - :error, {:already_started, _pid} -> :ok - end - - :meck.expect(module, function, fun) - end - -end diff --git a/test/elixir_SUITE.erl b/test/elixir_SUITE.erl deleted file mode 100644 index b869e00f7..000000000 --- a/test/elixir_SUITE.erl +++ /dev/null @@ -1,119 +0,0 @@ -%%%------------------------------------------------------------------- -%%% Author : Mickael Remond <mremond@process-one.net> -%%% Created : 19 Feb 2015 by Mickael Remond <mremond@process-one.net> -%%% -%%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne -%%% -%%% This program is free software; you can redistribute it and/or -%%% modify it under the terms of the GNU General Public License as -%%% published by the Free Software Foundation; either version 2 of the -%%% License, or (at your option) any later version. -%%% -%%% This program is distributed in the hope that it will be useful, -%%% but WITHOUT ANY WARRANTY; without even the implied warranty of -%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%%% General Public License for more details. -%%% -%%% You should have received a copy of the GNU General Public License along -%%% with this program; if not, write to the Free Software Foundation, Inc., -%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -%%% -%%%---------------------------------------------------------------------- - -%%% This is a common test wrapper to run our ejabberd tests written in -%%% Elixir from standard common test code. -%%% -%%% Example: Is run with: -%%% ./rebar skip_deps=true ct suites=elixir -%%% or from ejabber overall test suite: -%%% make quicktest - --module(elixir_SUITE). - --compile(export_all). - -init_per_suite(Config) -> - suite:setup_ejabberd_lib_path(Config), - check_meck(), - code:add_pathz(filename:join(test_dir(), "../include")), - Config. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - process_flag(error_handler, ?MODULE), - Config. - -all() -> - case is_elixir_available() of - true -> - Dir = test_dir(), - filelib:fold_files(Dir, ".*test\.exs$", false, - fun(Filename, Acc) -> [list_to_atom(filename:basename(Filename)) | Acc] end, - []); - false -> - [] - end. - -check_meck() -> - case catch meck:module_info(module) of - meck -> - ok; - {'EXIT',{undef, _}} -> - ct:print("meck is not available. Please make sure you configured ejabberd with --enable-elixir --enable-tools"), - ok - end. - -is_elixir_available() -> - case catch elixir:module_info() of - {'EXIT',{undef,_}} -> - ct:print("ejabberd has not been build with Elixir support, skipping Elixir tests."), - false; - ModInfo when is_list(ModInfo) -> - true - end. - -undefined_function(?MODULE, Func, Args) -> - case lists:suffix(".exs", atom_to_list(Func)) of - true -> - run_elixir_test(Func); - false -> - error_handler:undefined_function(?MODULE, Func, Args) - end; -undefined_function(Module, Func, Args) -> - error_handler:undefined_function(Module, Func,Args). - -run_elixir_test(Func) -> - %% Elixir tests can be tagged as follow to be ignored (place before test start) - %% @tag pending: true - 'Elixir.ExUnit':start([{exclude, [{pending, true}]}, - {formatters, - ['Elixir.ExUnit.CLIFormatter', - 'Elixir.ExUnit.CTFormatter']}, - {autorun, false}]), - - filelib:fold_files(test_dir(), ".*mock\.exs\$", true, - fun (File, N) -> - 'Elixir.Code':load_file(list_to_binary(File)), - N+1 - end, 0), - - 'Elixir.Code':load_file(list_to_binary(filename:join(test_dir(), atom_to_list(Func)))), - %% I did not use map syntax, so that this file can still be build under R16 - catch 'Elixir.ExUnit.Server':cases_loaded(), - ResultMap = 'Elixir.ExUnit':run(), - case maps:find(failures, ResultMap) of - {ok, 0} -> - %% Zero failures - ok; - {ok, Failures} -> - ct:print("Tests failed in module '~s': ~.10B failures.~nSee logs for details", [Func, Failures]), - ct:fail(elixir_test_failure), - error - end. - -test_dir() -> - {ok, CWD} = file:get_cwd(), - filename:join(CWD, "../../test"). diff --git a/test/example_tests.erl b/test/example_tests.erl index 61b84cc2d..b93e0ccbb 100644 --- a/test/example_tests.erl +++ b/test/example_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/jid_test.exs b/test/jid_test.exs deleted file mode 100644 index aa3563bea..000000000 --- a/test/jid_test.exs +++ /dev/null @@ -1,45 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule JidTest do - @author "mremond@process-one.net" - - use ExUnit.Case, async: true - - require Record - Record.defrecord :jid, Record.extract(:jid, from_lib: "xmpp/include/jid.hrl") - - setup_all do - :stringprep.start - :jid.start - :ok - end - - test "create a jid from a binary" do - jid = :jid.from_string("test@localhost/resource") - assert jid(jid, :user) == "test" - assert jid(jid, :server) == "localhost" - assert jid(jid, :resource) == "resource" - end - - test "Check that sending a list to from_string/1 does not crash the jid process" do - {:error, :need_jid_as_binary} = :jid.from_string('test@localhost/resource') - end -end diff --git a/test/ldap_srv.erl b/test/ldap_srv.erl index f601827c4..8ac5a7b89 100644 --- a/test/ldap_srv.erl +++ b/test/ldap_srv.erl @@ -3,7 +3,7 @@ %%% Created : 21 Jun 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/mam_tests.erl b/test/mam_tests.erl index e46a13ff0..128df2fe8 100644 --- a/test/mam_tests.erl +++ b/test/mam_tests.erl @@ -3,7 +3,7 @@ %%% Created : 14 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -377,7 +377,7 @@ recv_fin(Config, I, QueryID, NS, IsComplete) when NS == ?NS_MAM_1; NS == ?NS_MAM complete = Complete, rsm = RSM}]} = recv_iq(Config), ct:comment("Checking if complete is ~s", [IsComplete]), - Complete = IsComplete, + ?match(IsComplete, Complete), RSM; recv_fin(Config, I, QueryID, ?NS_MAM_TMP = NS, _IsComplete) -> ct:comment("Receiving fin iq for namespace '~s'", [NS]), @@ -394,7 +394,7 @@ recv_fin(Config, _, QueryID, ?NS_MAM_0 = NS, IsComplete) -> complete = Complete, rsm = RSM} = xmpp:get_subtag(FinMsg, #mam_fin{xmlns = NS}), ct:comment("Checking if complete is ~s", [IsComplete]), - Complete = IsComplete, + ?match(IsComplete, Complete), RSM. send_messages_to_room(Config, Range) -> @@ -417,7 +417,6 @@ recv_messages_from_room(Config, Range) -> MyNickJID = jid:replace_resource(Room, MyNick), MyJID = my_jid(Config), QID = p1_rand:get_string(), - Count = length(Range), I = send(Config, #iq{type = set, to = Room, sub_els = [#mam_query{xmlns = ?NS_MAM_2, id = QID}]}), lists:foreach( @@ -440,8 +439,9 @@ recv_messages_from_room(Config, Range) -> #iq{from = Room, id = I, type = result, sub_els = [#mam_fin{xmlns = ?NS_MAM_2, id = QID, - rsm = #rsm_set{count = Count}, - complete = true}]} = recv_iq(Config). + rsm = RSM, + complete = true}]} = recv_iq(Config), + match_rsm_count(RSM, length(Range)). query_all(Config, From, To) -> lists:foreach( @@ -454,7 +454,8 @@ query_all(Config, From, To, NS) -> Range = lists:seq(1, 5), ID = send_query(Config, #mam_query{xmlns = NS, id = QID}), recv_archived_messages(Config, From, To, QID, Range), - #rsm_set{count = 5} = recv_fin(Config, ID, QID, NS, _Complete = true). + RSM = recv_fin(Config, ID, QID, NS, _Complete = true), + match_rsm_count(RSM, 5). query_with(Config, From, To) -> lists:foreach( @@ -480,7 +481,8 @@ query_with(Config, From, To, NS) -> end, ID = send_query(Config, Query), recv_archived_messages(Config, From, To, QID, Range), - #rsm_set{count = 5} = recv_fin(Config, ID, QID, NS, true) + RSM = recv_fin(Config, ID, QID, NS, true), + match_rsm_count(RSM, 5) end, [Peer, BarePeer]). query_rsm_max(Config, From, To) -> @@ -498,7 +500,8 @@ query_rsm_max(Config, From, To, NS) -> ID = send_query(Config, Query), recv_archived_messages(Config, From, To, QID, Range), IsComplete = Max >= 5, - #rsm_set{count = 5} = recv_fin(Config, ID, QID, NS, IsComplete) + RSM = recv_fin(Config, ID, QID, NS, IsComplete), + match_rsm_count(RSM, 5) end, lists:seq(0, 6)). query_rsm_after(Config, From, To) -> @@ -517,8 +520,9 @@ query_rsm_after(Config, From, To, NS) -> rsm = #rsm_set{'after' = After}}, ID = send_query(Config, Query), recv_archived_messages(Config, From, To, QID, Range), - #rsm_set{count = 5, first = First} = + RSM = #rsm_set{first = First} = recv_fin(Config, ID, QID, NS, true), + match_rsm_count(RSM, 5), First end, #rsm_first{data = undefined}, [lists:seq(N, 5) || N <- lists:seq(1, 6)]). @@ -539,7 +543,15 @@ query_rsm_before(Config, From, To, NS) -> rsm = #rsm_set{before = Before}}, ID = send_query(Config, Query), recv_archived_messages(Config, From, To, QID, Range), - #rsm_set{count = 5, last = Last} = + RSM = #rsm_set{last = Last} = recv_fin(Config, ID, QID, NS, true), + match_rsm_count(RSM, 5), Last end, <<"">>, lists:reverse([lists:seq(1, N) || N <- lists:seq(0, 5)])). + +match_rsm_count(#rsm_set{count = undefined}, _) -> + %% The backend doesn't support counting + ok; +match_rsm_count(#rsm_set{count = Count1}, Count2) -> + ct:comment("Checking if RSM 'count' is ~p", [Count2]), + ?match(Count2, Count1). diff --git a/test/mix_tests.erl b/test/mix_tests.erl deleted file mode 100644 index 864150661..000000000 --- a/test/mix_tests.erl +++ /dev/null @@ -1,154 +0,0 @@ -%%%------------------------------------------------------------------- -%%% Author : Evgeny Khramtsov <ekhramtsov@process-one.net> -%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> -%%% -%%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne -%%% -%%% This program is free software; you can redistribute it and/or -%%% modify it under the terms of the GNU General Public License as -%%% published by the Free Software Foundation; either version 2 of the -%%% License, or (at your option) any later version. -%%% -%%% This program is distributed in the hope that it will be useful, -%%% but WITHOUT ANY WARRANTY; without even the implied warranty of -%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%%% General Public License for more details. -%%% -%%% You should have received a copy of the GNU General Public License along -%%% with this program; if not, write to the Free Software Foundation, Inc., -%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -%%% -%%%---------------------------------------------------------------------- - --module(mix_tests). - -%% API --compile(export_all). --import(suite, [mix_jid/1, mix_room_jid/1, my_jid/1, is_feature_advertised/3, - disconnect/1, send_recv/2, recv_message/1, send/2, - put_event/2, get_event/1]). --include("suite.hrl"). - -%%%=================================================================== -%%% API -%%%=================================================================== -%%%=================================================================== -%%% Single user tests -%%%=================================================================== -single_cases() -> - {mix_single, [sequence], - [single_test(feature_enabled)]}. - -feature_enabled(Config) -> - MIX = mix_jid(Config), - ct:comment("Checking if ~s is set", [?NS_MIX_0]), - true = is_feature_advertised(Config, ?NS_MIX_0, MIX), - disconnect(Config). - -%%%=================================================================== -%%% Master-slave tests -%%%=================================================================== -master_slave_cases() -> - {mix_master_slave, [sequence], - [master_slave_test(all)]}. - -all_master(Config) -> - MIX = mix_jid(Config), - Room = mix_room_jid(Config), - MyJID = my_jid(Config), - MyBareJID = jid:remove_resource(MyJID), - #iq{type = result, - sub_els = - [#disco_info{ - identities = [#identity{category = <<"conference">>, - type = <<"text">>}], - xdata = [#xdata{type = result, fields = XFields}]}]} = - send_recv(Config, #iq{type = get, to = MIX, sub_els = [#disco_info{}]}), - true = lists:any( - fun(#xdata_field{var = <<"FORM_TYPE">>, - values = [?NS_MIX_SERVICEINFO_0]}) -> true; - (_) -> false - end, XFields), - %% Joining - Nodes = [?NS_MIX_NODES_MESSAGES, ?NS_MIX_NODES_PRESENCE, - ?NS_MIX_NODES_PARTICIPANTS, ?NS_MIX_NODES_SUBJECT, - ?NS_MIX_NODES_CONFIG], - #iq{type = result, - sub_els = [#mix_join{subscribe = Nodes, jid = MyBareJID}]} = - send_recv(Config, #iq{type = set, to = Room, - sub_els = [#mix_join{subscribe = Nodes}]}), - #message{from = Room, - sub_els = - [#ps_event{ - items = #ps_items{ - node = ?NS_MIX_NODES_PARTICIPANTS, - items = [#ps_item{ - id = ParticipantID, - sub_els = [PXML]}]}}]} = - recv_message(Config), - #mix_participant{jid = MyBareJID} = xmpp:decode(PXML), - %% Coming online - PresenceID = p1_rand:get_string(), - Presence = xmpp:encode(#presence{}), - #iq{type = result, - sub_els = - [#pubsub{ - publish = #ps_publish{ - node = ?NS_MIX_NODES_PRESENCE, - items = [#ps_item{id = PresenceID}]}}]} = - send_recv( - Config, - #iq{type = set, to = Room, - sub_els = - [#pubsub{ - publish = #ps_publish{ - node = ?NS_MIX_NODES_PRESENCE, - items = [#ps_item{ - id = PresenceID, - sub_els = [Presence]}]}}]}), - #message{from = Room, - sub_els = - [#ps_event{ - items = #ps_items{ - node = ?NS_MIX_NODES_PRESENCE, - items = [#ps_item{ - id = PresenceID, - sub_els = [Presence]}]}}]} = - recv_message(Config), - %% Coming offline - send(Config, #presence{type = unavailable, to = Room}), - %% Receiving presence retract event - #message{from = Room, - sub_els = [#ps_event{ - items = #ps_items{ - node = ?NS_MIX_NODES_PRESENCE, - retract = PresenceID}}]} = - recv_message(Config), - %% Leaving - #iq{type = result, sub_els = []} = - send_recv(Config, #iq{type = set, to = Room, sub_els = [#mix_leave{}]}), - #message{from = Room, - sub_els = - [#ps_event{ - items = #ps_items{ - node = ?NS_MIX_NODES_PARTICIPANTS, - retract = ParticipantID}}]} = - recv_message(Config), - put_event(Config, disconnect), - disconnect(Config). - -all_slave(Config) -> - disconnect = get_event(Config), - disconnect(Config). - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== -single_test(T) -> - list_to_atom("mix_" ++ atom_to_list(T)). - -master_slave_test(T) -> - {list_to_atom("mix_" ++ atom_to_list(T)), [parallel], - [list_to_atom("mix_" ++ atom_to_list(T) ++ "_master"), - list_to_atom("mix_" ++ atom_to_list(T) ++ "_slave")]}. diff --git a/test/mod_admin_extra_test.exs b/test/mod_admin_extra_test.exs deleted file mode 100644 index 7b1bc21de..000000000 --- a/test/mod_admin_extra_test.exs +++ /dev/null @@ -1,374 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule EjabberdModAdminExtraTest do - use ExUnit.Case, async: false - - require EjabberdAuthMock - require EjabberdSmMock - require ModLastMock - require ModRosterMock - - @author "jsautret@process-one.net" - - @user "user" - @domain "domain" - @password "password" - @resource "resource" - - require Record - Record.defrecord :jid, Record.extract(:jid, from_lib: "xmpp/include/jid.hrl") - - setup_all do - try do - :jid.start - :stringprep.start - :mnesia.start - :ejabberd_mnesia.start - :p1_sha.load_nif - :ejabberd_hooks.start_link - rescue - _ -> :ok - end - :ok = :ejabberd_config.start(["domain"], []) - :gen_mod.start_link - :acl.start_link - :ejabberd_access_permissions.start_link() - :ejabberd_commands.start_link - :mod_admin_extra.start(@domain, []) - :ejabberd_hooks.start_link - :ok - end - - setup do - :meck.unload - EjabberdAuthMock.init - EjabberdSmMock.init - ModRosterMock.init(@domain, :mod_admin_extra) - :ok - end - - ###################### Accounts - test "check_account works" do - EjabberdAuthMock.create_user @user, @domain, @password - - assert call_command(:check_account, [@user, @domain]) - refute call_command(:check_account, [@user, "bad_domain"]) - refute call_command(:check_account, ["bad_user", @domain]) - - assert :meck.validate :ejabberd_auth - end - - test "check_password works" do - - EjabberdAuthMock.create_user @user, @domain, @password - - assert call_command(:check_password, - [@user, @domain, @password]) - refute call_command(:check_password, - [@user, @domain, "bad_password"]) - refute call_command(:check_password, - [@user, "bad_domain", @password]) - refute call_command(:check_password, - ["bad_user", @domain, @password]) - - assert :meck.validate :ejabberd_auth - - end - - test "check_password_hash works" do - - EjabberdAuthMock.create_user @user, @domain, @password - hash = "5F4DCC3B5AA765D61D8327DEB882CF99" # echo -n password|md5 - - assert call_command(:check_password_hash, - [@user, @domain, hash, "md5"]) - refute call_command(:check_password_hash, - [@user, @domain, "bad_hash", "md5"]) - refute call_command(:check_password_hash, - [@user, "bad_domain", hash, "md5"]) - refute call_command(:check_password_hash, - ["bad_user", @domain, hash, "md5"]) - - hash = "5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8" # echo -n password|shasum - assert call_command(:check_password_hash, - [@user, @domain, hash, "sha"]) - - assert :unkown_hash_method == - catch_throw call_command(:check_password_hash, - [@user, @domain, hash, "bad_method"]) - - assert :meck.validate :ejabberd_auth - - end - - test "set_password works" do - EjabberdAuthMock.create_user @user, @domain, @password - - assert call_command(:change_password, - [@user, @domain, "new_password"]) - refute call_command(:check_password, - [@user, @domain, @password]) - assert call_command(:check_password, - [@user, @domain, "new_password"]) - assert {:not_found, 'unknown_user'} == - catch_throw call_command(:change_password, - ["bad_user", @domain, - @password]) - assert :meck.validate :ejabberd_auth - end - - ###################### Sessions - - test "num_resources works" do - assert 0 == call_command(:num_resources, - [@user, @domain]) - - EjabberdSmMock.connect_resource @user, @domain, @resource - assert 1 == call_command(:num_resources, - [@user, @domain]) - - EjabberdSmMock.connect_resource @user, @domain, @resource<>"2" - assert 2 == call_command(:num_resources, - [@user, @domain]) - - EjabberdSmMock.connect_resource @user<>"1", @domain, @resource - assert 2 == call_command(:num_resources, - [@user, @domain]) - - EjabberdSmMock.disconnect_resource @user, @domain, @resource - assert 1 == call_command(:num_resources, - [@user, @domain]) - - assert :meck.validate :ejabberd_sm - end - - test "resource_num works" do - EjabberdSmMock.connect_resource @user, @domain, @resource<>"3" - EjabberdSmMock.connect_resource @user, @domain, @resource<>"2" - EjabberdSmMock.connect_resource @user, @domain, @resource<>"1" - - assert :bad_argument == - elem(catch_throw(call_command(:resource_num, - [@user, @domain, 0])), 0) - assert @resource<>"1" == - call_command(:resource_num, [@user, @domain, 1]) - assert @resource<>"3" == - call_command(:resource_num, [@user, @domain, 3]) - assert :bad_argument == - elem(catch_throw(call_command(:resource_num, - [@user, @domain, 4])), 0) - assert :meck.validate :ejabberd_sm - end - - test "kick_session works" do - EjabberdSmMock.connect_resource @user, @domain, @resource<>"1" - EjabberdSmMock.connect_resource @user, @domain, @resource<>"2" - EjabberdSmMock.connect_resource @user, @domain, @resource<>"3" - - assert 3 == length EjabberdSmMock.get_sessions @user, @domain - assert 1 == length EjabberdSmMock.get_session @user, @domain, @resource<>"2" - - assert :ok == - call_command(:kick_session, - [@user, @domain, - @resource<>"2", "kick"]) - - assert 2 == length EjabberdSmMock.get_sessions @user, @domain - assert 0 == length EjabberdSmMock.get_session @user, @domain, @resource<>"2" - - assert :meck.validate :ejabberd_sm - end - - ###################### Last - - test "get_last works" do - - assert {_, 'NOT FOUND'} = - call_command(:get_last, [@user, @domain]) - - EjabberdSmMock.connect_resource @user, @domain, @resource<>"1" - EjabberdSmMock.connect_resource @user, @domain, @resource<>"2" - - assert {_, 'ONLINE'} = - call_command(:get_last, [@user, @domain]) - - EjabberdSmMock.disconnect_resource @user, @domain, @resource<>"1" - - assert {_, 'ONLINE'} = - call_command(:get_last, [@user, @domain]) - - now = {megasecs, secs, _microsecs} = :os.timestamp - timestamp = megasecs * 1000000 + secs - EjabberdSmMock.disconnect_resource(@user, @domain, @resource<>"2", - timestamp) - {{year, month, day}, {hour, minute, second}} = :calendar.now_to_universal_time now - result = IO.iodata_to_binary(:io_lib.format( - "~w-~.2.0w-~.2.0wT~.2.0w:~.2.0w:~.2.0wZ", - [year, month, day, hour, minute, second])) - assert {result, ""} == - call_command(:get_last, [@user, @domain]) - - assert :meck.validate :mod_last - end - - ###################### Roster - - @tag :skip - test "add_rosteritem and delete_rosteritem work" do - # Connect user - # Add user1 & user2 to user's roster - # Remove user1 & user2 from user's roster - - EjabberdSmMock.connect_resource @user, @domain, @resource - - assert [] == ModRosterMock.get_roster(@user, @domain) - - assert :ok == - call_command(:add_rosteritem, [@user, @domain, - @user<>"1", @domain, - "nick1", - "group1", - "both"]) - # Check that user1 is the only item of the user's roster - result = ModRosterMock.get_roster(@user, @domain) - assert 1 == length result - [{{@user, @domain, jid}, opts}] = result - assert @user<>"1@"<>@domain == jid - assert "nick1" == opts.nick - assert ["group1"] == opts.groups - assert :both == opts.subs - - # Check that the item roster user1 was pushed with subscription - # 'both' to user online ressource - jid = :jlib.make_jid(@user, @domain, @resource) - assert 1 == - :meck.num_calls(:ejabberd_sm, :route, - [jid, - {:item, {@user<>"1", @domain, ""}, :both}]) - - assert :ok == - call_command(:add_rosteritem, [@user, @domain, - @user<>"2", @domain, - "nick2", - "group2", - "both"]) - result = ModRosterMock.get_roster(@user, @domain) - assert 2 == length result - - - # Check that the item roster user2 was pushed with subscription - # 'both' to user online ressource - assert 1 == - :meck.num_calls(:ejabberd_sm, :route, - [jid, - {:item, {@user<>"2", @domain, ""}, :both}]) - - - call_command(:delete_rosteritem, [@user, @domain, - @user<>"1", @domain]) - result = ModRosterMock.get_roster(@user, @domain) - assert 1 == length result - [{{@user, @domain, jid}, opts}] = result - assert @user<>"2@"<>@domain == jid - assert "nick2" == opts.nick - assert ["group2"] == opts.groups - assert :both == opts.subs - - # Check that the item roster user1 was pushed with subscription - # 'none' to user online ressource - jid = :jlib.make_jid(@user, @domain, @resource) - assert 1 == - :meck.num_calls(:ejabberd_sm, :route, - [jid, - {:item, {@user<>"1", @domain, ""}, :none}]) - - call_command(:delete_rosteritem, [@user, @domain, - @user<>"2", @domain]) - - # Check that the item roster user2 was pushed with subscription - # 'none' to user online ressource - assert 1 == - :meck.num_calls(:ejabberd_sm, :route, - [jid, - {:item, {@user<>"2", @domain, ""}, :none}]) - - # Check that nothing else was pushed to user resource - jid = jid(user: @user, server: @domain, resource: :_, - luser: @user, lserver: @domain, lresource: :_) - assert 4 == - :meck.num_calls(:ejabberd_sm, :route, - [jid, - {:item, :_, :_}]) - - assert [] == ModRosterMock.get_roster(@user, @domain) - assert :meck.validate :ejabberd_sm - - end - - @tag :skip - test "get_roster works" do - assert [] == ModRosterMock.get_roster(@user, @domain) - assert [] == call_command(:get_roster, [@user, @domain], - :admin) - - assert :ok == - call_command(:add_rosteritem, [@user, @domain, - @user<>"1", @domain, - "nick1", - "group1", - "both"]) - assert [{@user<>"1@"<>@domain, "", 'both', 'none', "group1"}] == - call_command(:get_roster, [@user, @domain], :admin) - assert :ok == - call_command(:add_rosteritem, [@user, @domain, - @user<>"2", @domain, - "nick2", - "group2", - "none"]) - result = call_command(:get_roster, [@user, @domain], :admin) - assert 2 == length result - assert Enum.member?(result, {@user<>"1@"<>@domain, "", 'both', 'none', "group1"}) - assert Enum.member?(result, {@user<>"2@"<>@domain, "", 'none', 'none', "group2"}) - - end - - defp call_command(name, args) do - :ejabberd_commands.execute_command2(name, args, %{:caller_module => :ejabberd_ctl}) - end - - defp call_command(name, args, mode) do - call_command(name, args) - end - -# kick_user command is defined in ejabberd_sm, move to extra? -# test "kick_user works" do -# assert 0 == call_command(:num_resources, -# [@user, @domain]) -# EjabberdSmMock.connect_resource(@user, @domain, @resource<>"1") -# EjabberdSmMock.connect_resource(@user, @domain, @resource<>"2") -# assert 2 == -# call_command(:kick_user, [@user, @domain]) -# assert 0 == call_command(:num_resources, -# [@user, @domain]) -# assert :meck.validate :ejabberd_sm -# end - -end diff --git a/test/mod_http_api_mock_test.exs b/test/mod_http_api_mock_test.exs deleted file mode 100644 index ceda2bb0f..000000000 --- a/test/mod_http_api_mock_test.exs +++ /dev/null @@ -1,270 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule ModHttpApiMockTest do - use ExUnit.Case, async: false - - @author "jsautret@process-one.net" - - # Admin user - @admin "admin" - @adminpass "adminpass" - # Non admin user - @user "user" - @userpass "userpass" - # XMPP domain - @domain "domain" - # mocked command - @command "command_test" - @acommand String.to_atom(@command) - # default API version - @version 0 - - require Record - Record.defrecord :request, Record.extract(:request, from_lib: "ejabberd/include/ejabberd_http.hrl") - - setup_all do - try do - :jid.start - :mnesia.start - :ejabberd_mnesia.start - :stringprep.start - :ejabberd_hooks.start_link - :ejabberd_config.start([@domain], []) - {:ok, _} = :ejabberd_access_permissions.start_link() - :ejabberd_commands.start_link - rescue - _ -> :ok - end - :mod_http_api.start(@domain, []) - EjabberdOauthMock.init - :ok - end - - setup do - :meck.unload - :meck.new :ejabberd_commands - :meck.new(:acl, [:passthrough]) # Need to fake acl to allow oauth - EjabberdAuthMock.init - :ok - end - - test "HTTP GET simple command call with Basic Auth" do - EjabberdAuthMock.create_user @user, @domain, @userpass - - # Mock a simple command() -> :ok - :meck.expect(:ejabberd_commands, :get_command_format, - fn (@acommand, %{usr: {@user, @domain, _}}, @version) -> - {[], {:res, :rescode}} - end) - :meck.expect(:ejabberd_commands, :get_exposed_commands, - fn () -> [@acommand] end) - :meck.expect(:ejabberd_commands, :execute_command2, - fn (@acommand, [], %{usr: {@user, @domain, _}}, @version) -> - :ok - end) - - :ejabberd_config.add_local_option(:commands, [[{:add_commands, [@acommand]}]]) - - # Correct Basic Auth call - req = request(method: :GET, - path: ["api", @command], - q: [nokey: ""], - # Basic auth - auth: {@user<>"@"<>@domain, @userpass}, - ip: {{127,0,0,1},60000}, - host: @domain) - result = :mod_http_api.process([@command], req) - - # history = :meck.history(:ejabberd_commands) - - assert 200 == elem(result, 0) # HTTP code - assert "0" == elem(result, 2) # command result - - # Bad password - req = request(method: :GET, - path: ["api", @command], - q: [nokey: ""], - # Basic auth - auth: {@user<>"@"<>@domain, @userpass<>"bad"}, - ip: {{127,0,0,1},60000}, - host: @domain) - result = :mod_http_api.process([@command], req) - assert 401 == elem(result, 0) # HTTP code - - # Check that the command was executed only once - assert 1 == - :meck.num_calls(:ejabberd_commands, :execute_command2, :_) - - assert :meck.validate :ejabberd_auth - assert :meck.validate :ejabberd_commands - end - - test "HTTP GET simple command call with OAuth" do - EjabberdAuthMock.create_user @user, @domain, @userpass - - # Mock a simple command() -> :ok - :meck.expect(:ejabberd_commands, :get_command_format, - fn (@acommand, %{usr: {@user, @domain, _}}, @version) -> - {[], {:res, :rescode}} - end) - :meck.expect(:ejabberd_commands, :get_exposed_commands, - fn () -> [@acommand] end) - :meck.expect(:ejabberd_commands, :execute_command2, - fn (@acommand, [], %{usr: {@user, @domain, _}, oauth_scope: ["ejabberd:user"]}, @version) -> - :ok - (@acommand, [], %{usr: {@user, @domain, _}, oauth_scope: [@command]}, @version) -> - :ok - (@acommand, [], %{usr: {@user, @domain, _}, oauth_scope: _}, @version) -> - throw({:error, :access_rules_unauthorized}) - end) - - - # Correct OAuth call using specific scope - token = EjabberdOauthMock.get_token @user, @domain, @command - req = request(method: :GET, - path: ["api", @command], - q: [nokey: ""], - # OAuth - auth: {:oauth, token, []}, - ip: {{127,0,0,1},60000}, - host: @domain) - result = :mod_http_api.process([@command], req) - assert 200 == elem(result, 0) # HTTP code - assert "0" == elem(result, 2) # command result - - # Correct OAuth call using specific ejabberd:user scope - token = EjabberdOauthMock.get_token @user, @domain, "ejabberd:user" - req = request(method: :GET, - path: ["api", @command], - q: [nokey: ""], - # OAuth - auth: {:oauth, token, []}, - ip: {{127,0,0,1},60000}, - host: @domain) - result = :mod_http_api.process([@command], req) - assert 200 == elem(result, 0) # HTTP code - assert "0" == elem(result, 2) # command result - - # Wrong OAuth token - req = request(method: :GET, - path: ["api", @command], - q: [nokey: ""], - # OAuth - auth: {:oauth, "bad"<>token, []}, - ip: {{127,0,0,1},60000}, - host: @domain) - result = :mod_http_api.process([@command], req) - assert 401 == elem(result, 0) # HTTP code - - # Expired OAuth token - token = EjabberdOauthMock.get_token @user, @domain, @command, 1 - :timer.sleep 1500 - req = request(method: :GET, - path: ["api", @command], - q: [nokey: ""], - # OAuth - auth: {:oauth, token, []}, - ip: {{127,0,0,1},60000}, - host: @domain) - result = :mod_http_api.process([@command], req) - assert 401 == elem(result, 0) # HTTP code - - # Wrong OAuth scope - token = EjabberdOauthMock.get_token @user, @domain, "bad_command" - :timer.sleep 1500 - req = request(method: :GET, - path: ["api", @command], - q: [nokey: ""], - # OAuth - auth: {:oauth, token, []}, - ip: {{127,0,0,1},60000}, - host: @domain) - result = :mod_http_api.process([@command], req) - assert 403 == elem(result, 0) # HTTP code - - # Check that the command was executed twice - assert 3 == - :meck.num_calls(:ejabberd_commands, :execute_command2, :_) - - assert :meck.validate :ejabberd_auth - #assert :meck.validate :ejabberd_commands - #assert :ok = :meck.history(:ejabberd_commands) - end - - test "Request oauth token, resource owner password credentials" do - EjabberdAuthMock.create_user @user, @domain, @userpass - :application.set_env(:oauth2, :backend, :ejabberd_oauth) - :application.start(:oauth2) - - # Mock a simple command() -> :ok - :meck.expect(:ejabberd_commands, :get_command_format, - fn (@acommand, {@user, @domain, {:oauth, _token}, false}, @version) -> - {[], {:res, :rescode}} - end) - :meck.expect(:ejabberd_commands, :get_exposed_commands, - fn () -> [@acommand] end) - - #Mock acl to allow oauth authorizations - :meck.expect(:acl, :match_rule, fn(_Server, _Access, _Jid) -> :allow end) - - - # Correct password - req = request(method: :POST, - path: ["oauth", "token"], - q: [{"grant_type", "password"}, {"scope", @command}, {"username", @user<>"@"<>@domain}, {"ttl", "4000"}, {"password", @userpass}], - ip: {{127,0,0,1},60000}, - host: @domain) - result = :ejabberd_oauth.process([], req) - assert 200 = elem(result, 0) #http code - {kv} = :jiffy.decode(elem(result,2)) - assert {_, "bearer"} = List.keyfind(kv, "token_type", 0) - assert {_, @command} = List.keyfind(kv, "scope", 0) - assert {_, 4000} = List.keyfind(kv, "expires_in", 0) - {"access_token", _token} = List.keyfind(kv, "access_token", 0) - - #missing grant_type - req = request(method: :POST, - path: ["oauth", "token"], - q: [{"scope", @command}, {"username", @user<>"@"<>@domain}, {"password", @userpass}], - ip: {{127,0,0,1},60000}, - host: @domain) - result = :ejabberd_oauth.process([], req) - assert 400 = elem(result, 0) #http code - {kv} = :jiffy.decode(elem(result,2)) - assert {_, "unsupported_grant_type"} = List.keyfind(kv, "error", 0) - - - # incorrect user/pass - req = request(method: :POST, - path: ["oauth", "token"], - q: [{"grant_type", "password"}, {"scope", @command}, {"username", @user<>"@"<>@domain}, {"password", @userpass<>"aa"}], - ip: {{127,0,0,1},60000}, - host: @domain) - result = :ejabberd_oauth.process([], req) - assert 400 = elem(result, 0) #http code - {kv} = :jiffy.decode(elem(result,2)) - assert {_, "invalid_grant"} = List.keyfind(kv, "error", 0) - - assert :meck.validate :ejabberd_auth - assert :meck.validate :ejabberd_commands - end - -end diff --git a/test/mod_http_api_test.exs b/test/mod_http_api_test.exs deleted file mode 100644 index f7abbc004..000000000 --- a/test/mod_http_api_test.exs +++ /dev/null @@ -1,127 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule ModHttpApiTest do - @author "mremond@process-one.net" - - use ExUnit.Case, async: true - - require Record - Record.defrecord :request, Record.extract(:request, from_lib: "ejabberd/include/ejabberd_http.hrl") - Record.defrecord :ejabberd_commands, Record.extract(:ejabberd_commands, from_lib: "ejabberd/include/ejabberd_commands.hrl") - - setup_all do - :ok = :mnesia.start - :ejabberd_mnesia.start - :stringprep.start - :ejabberd_hooks.start_link - :ok = :ejabberd_config.start(["localhost"], []) - :acl.start_link - {:ok, _} = :ejabberd_access_permissions.start_link() - {:ok, _} = :ejabberd_commands.start_link - :ok = :ejabberd_commands.register_commands(cmds) - on_exit fn -> - :meck.unload - unregister_commands(cmds) end - end - - test "We can expose several commands to API at a time" do - setup_mocks() - assert :ok == :ejabberd_commands.expose_commands([:open_cmd, :user_cmd]) - commands = :ejabberd_commands.get_exposed_commands() - assert Enum.member?(commands, :open_cmd) - assert Enum.member?(commands, :user_cmd) - end - -# test "We can call open commands without authentication" do -# setup_mocks() -# :ejabberd_commands.expose_commands([:open_cmd]) -# request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]") -# {200, _, _} = :mod_http_api.process(["open_cmd"], request) -# end - - # This related to the commands config file option - test "Attempting to access a command that is not exposed as HTTP API returns 403" do - setup_mocks() - assert :ok == :ejabberd_commands.expose_commands([]) - request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "{}") - {403, _, _} = :mod_http_api.process(["open_cmd"], request) - end - - test "Call to user, admin or restricted commands without authentication are rejected" do - setup_mocks() - assert :ok == :ejabberd_commands.expose_commands([:user_cmd, :admin_cmd, :restricted]) - request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "{}") - {400, _, _} = :mod_http_api.process(["user_cmd"], request) - {403, _, _} = :mod_http_api.process(["admin_cmd"], request) - {403, _, _} = :mod_http_api.process(["restricted_cmd"], request) - end - - @tag pending: true - test "If admin_ip_access is enabled, we can call restricted API without authentication from that IP" do - setup_mocks() - end - - # Define a set of test commands that we expose through API - # We define one for each policy type - defp cmds do - [:open, :user, :admin, :restricted] - |> Enum.map(&({&1, String.to_atom(to_string(&1) <> "_cmd")})) - |> Enum.map(fn({cmd_type, cmd}) -> - ejabberd_commands(name: cmd, tags: [:test], - policy: cmd_type, - module: __MODULE__, - function: cmd, - args: [], - result: {:res, :rescode}) - end) - end - - def open_cmd, do: :ok - def user_cmd(_, _), do: :ok - def admin_cmd, do: :ok - def restricted_cmd, do: :ok - - defp setup_mocks() do - :meck.unload - mock(:gen_mod, :get_module_opt, - fn (_server, :mod_http_api, _admin_ip_access, _, _) -> - [{:allow, [{:ip, {{127,0,0,2}, 32}}]}] - end) - end - - defp mock(module, function, fun) do - try do - :meck.new(module) - catch - :error, {:already_started, _pid} -> :ok - end - :meck.expect(module, function, fun) - end - - defp unregister_commands(commands) do - try do - :ejabberd_commands.unregister_commands(commands) - catch - _,_ -> :ok - end - end - -end diff --git a/test/mod_last_mock.exs b/test/mod_last_mock.exs deleted file mode 100644 index 25f2bd473..000000000 --- a/test/mod_last_mock.exs +++ /dev/null @@ -1,79 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule ModLastMock do - - require Record - Record.defrecord :session, Record.extract(:session, from_lib: "ejabberd/include/ejabberd_sm.hrl") - Record.defrecord :jid, Record.extract(:jid, from_lib: "xmpp/include/jid.hrl") - - @author "jsautret@process-one.net" - @agent __MODULE__ - - def init do - try do - Agent.stop(@agent) - catch - :exit, _e -> :ok - end - - {:ok, _pid} = Agent.start_link(fn -> %{} end, name: @agent) - - mock(:mod_last, :get_last_info, - fn (user, domain) -> - Agent.get(@agent, fn last -> - case Map.get(last, {user, domain}, :not_found) do - {ts, status} -> {:ok, ts, status} - result -> result - end - end) - end) - end - - def set_last(user, domain, status) do - set_last(user, domain, status, now) - end - - def set_last(user, domain, status, timestamp) do - Agent.update(@agent, fn last -> - Map.put(last, {user, domain}, {timestamp, status}) - end) - end - - #################################################################### - # Helpers - #################################################################### - def now() do - {megasecs, secs, _microsecs} = :os.timestamp - megasecs * 1000000 + secs - end - - # TODO refactor: Move to ejabberd_test_mock - def mock(module, function, fun) do - try do - :meck.new(module) - catch - :error, {:already_started, _pid} -> :ok - end - - :meck.expect(module, function, fun) - end - -end diff --git a/test/mod_roster_mock.exs b/test/mod_roster_mock.exs deleted file mode 100644 index 70f273898..000000000 --- a/test/mod_roster_mock.exs +++ /dev/null @@ -1,159 +0,0 @@ -# ---------------------------------------------------------------------- -# -# ejabberd, Copyright (C) 2002-2017 ProcessOne -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ---------------------------------------------------------------------- - -defmodule ModRosterMock do - @author "jsautret@process-one.net" - - require Record - Record.defrecord :roster, Record.extract(:roster, from_lib: "ejabberd/include/mod_roster.hrl") - Record.defrecord :roster_version, Record.extract(:roster_version, from_lib: "ejabberd/include/mod_roster.hrl") - - @agent __MODULE__ - - def init(domain, module) do - try do - Agent.stop(@agent) - catch - :exit, _e -> :ok - end - - {:ok, _pid} = Agent.start_link(fn -> %{} end, name: @agent) - - mock_with_meck - - :ejabberd_mnesia.create(:mod_roster_mnesia, :roster, - [ram_copies: [node()], - attributes: Keyword.keys(roster(roster())), - index: [:us]]) - :ejabberd_mnesia.create(:mod_roster_mnesia, :roster_version, - [ram_copies: [node()], - attributes: Keyword.keys(roster_version(roster_version()))]) - #:mod_roster.stop(domain) - :gen_mod.start_module(domain, :mod_roster) - end - - def mock_with_meck do -# mock(:gen_mod, :db_type, -# fn (_server, :mod_roster_mnesia) -> -# :mnesia -# end) -# -# mock(:mnesia, :transaction, -# fn (_server, function) -> -# {:atomic, function.()} -# end) -# -# mock(:mnesia, :write, -# fn (Item) -> -# throw Item -# {:atomic, :ok} -# end) - - mock(:mod_roster_mnesia, :init, - fn (_server, _opts) -> - :ok - end) - mock(:mod_roster_mnesia, :transaction, - fn (_server, function) -> - {:atomic, function.()} - end) - - mock(:mod_roster_mnesia, :update_roster_t, - fn (user, domain, {u, d, _r}, item) -> - add_roster_item(user, domain, u<>"@"<>d, - roster(item, :name), - roster(item, :subscription), - roster(item, :groups), - roster(item, :ask), - roster(item, :askmessage)) - end) - - mock(:mod_roster_mnesia, :invalidate_roster_cache, - fn (_user, _server) -> - :ok - end) - - end - - def add_roster_item(user, domain, jid, nick, subs \\ :none, groups \\ [], - ask \\ :none, askmessage \\ "") - when is_binary(user) and byte_size(user) > 0 - and is_binary(domain) and byte_size(domain) > 0 - and is_binary(jid) and byte_size(jid) > 0 - and is_binary(nick) - and is_atom(subs) - and is_list(groups) - and is_atom(ask) - and is_binary(askmessage) - do - Agent.update(@agent, fn roster -> - Map.put(roster, {user, domain, jid}, %{nick: nick, - subs: subs, groups: groups, - ask: ask, askmessage: askmessage}) - end) - end - - def remove_roster_item(user, domain, jid) do - Agent.update(@agent, fn roster -> - Map.delete(roster, {user, domain, jid}) - end) - end - - def get_rosters() do - Agent.get(@agent, fn roster -> roster end) - end - - def get_roster(user, domain) do - Agent.get(@agent, fn roster -> - for {u, d, jid} <- Map.keys(roster), u == user, d == domain, - do: {{u, d, jid}, Map.fetch!(roster, {u, d, jid})} - end) - end - - def to_record({{user, domain, jid}, r}) do - roster(usj: {user, domain, jid}, - us: {user, domain}, - jid: :jid.from_string(jid), - subscription: r.subs, - ask: r.ask, - groups: r.groups, - askmessage: r.askmessage - ) - end - def to_records(rosters) do - for item <- rosters, do: to_record(item) - end - -#################################################################### -# Helpers -#################################################################### - - # TODO refactor: Move to ejabberd_test_mock - def mock(module, function, fun) do - try do - :meck.new(module, [:non_strict, :passthrough, :unstick]) - catch - :error, {:already_started, _pid} -> :ok - end - - :meck.expect(module, function, fun) - end - -end diff --git a/test/muc_tests.erl b/test/muc_tests.erl index 617ca8dd2..e744e3fc9 100644 --- a/test/muc_tests.erl +++ b/test/muc_tests.erl @@ -3,7 +3,7 @@ %%% Created : 15 Oct 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/offline_tests.erl b/test/offline_tests.erl index 4b91f818b..fbf1fbf74 100644 --- a/test/offline_tests.erl +++ b/test/offline_tests.erl @@ -3,7 +3,7 @@ %%% Created : 7 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/privacy_tests.erl b/test/privacy_tests.erl index 8cd99f513..f27a08b82 100644 --- a/test/privacy_tests.erl +++ b/test/privacy_tests.erl @@ -3,7 +3,7 @@ %%% Created : 18 Oct 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/private_tests.erl b/test/private_tests.erl index 506608670..5ae832b36 100644 --- a/test/private_tests.erl +++ b/test/private_tests.erl @@ -3,7 +3,7 @@ %%% Created : 23 Nov 2018 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -24,7 +24,7 @@ %% API -compile(export_all). --import(suite, [my_jid/1, is_feature_advertised/3, +-import(suite, [my_jid/1, server_jid/1, is_feature_advertised/3, send_recv/2, disconnect/1]). -include("suite.hrl"). @@ -43,9 +43,15 @@ single_cases() -> single_test(test_published)]}. test_features(Config) -> + Server = jid:encode(server_jid(Config)), MyJID = my_jid(Config), - true = is_feature_advertised(Config, ?NS_BOOKMARKS_CONVERSION_0, - jid:remove_resource(MyJID)), + case gen_mod:is_loaded(Server, mod_pubsub) of + true -> + true = is_feature_advertised(Config, ?NS_BOOKMARKS_CONVERSION_0, + jid:remove_resource(MyJID)); + false -> + ok + end, disconnect(Config). test_no_namespace(Config) -> @@ -73,20 +79,26 @@ test_set_get(Config) -> disconnect(Config). test_published(Config) -> - Storage = bookmark_storage(), - Node = xmpp:get_ns(Storage), - #iq{type = result, - sub_els = [#pubsub{items = #ps_items{node = Node, items = Items}}]} = - send_recv( - Config, - #iq{type = get, - sub_els = [#pubsub{items = #ps_items{node = Node}}]}), - [#ps_item{sub_els = [StorageXMLIn]}] = Items, - Storage = xmpp:decode(StorageXMLIn), - #iq{type = result, sub_els = []} = - send_recv(Config, - #iq{type = set, - sub_els = [#pubsub_owner{delete = {Node, <<>>}}]}), + Server = jid:encode(server_jid(Config)), + case gen_mod:is_loaded(Server, mod_pubsub) of + true -> + Storage = bookmark_storage(), + Node = xmpp:get_ns(Storage), + #iq{type = result, + sub_els = [#pubsub{items = #ps_items{node = Node, items = Items}}]} = + send_recv( + Config, + #iq{type = get, + sub_els = [#pubsub{items = #ps_items{node = Node}}]}), + [#ps_item{sub_els = [StorageXMLIn]}] = Items, + Storage = xmpp:decode(StorageXMLIn), + #iq{type = result, sub_els = []} = + send_recv(Config, + #iq{type = set, + sub_els = [#pubsub_owner{delete = {Node, <<>>}}]}); + false -> + ok + end, disconnect(Config). %%%=================================================================== diff --git a/test/proxy65_tests.erl b/test/proxy65_tests.erl index 5f308e744..be3c92cd4 100644 --- a/test/proxy65_tests.erl +++ b/test/proxy65_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/pubsub_tests.erl b/test/pubsub_tests.erl index ca468f779..b4950ef33 100644 --- a/test/pubsub_tests.erl +++ b/test/pubsub_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/push_tests.erl b/test/push_tests.erl index 505aa90f5..436f94d55 100644 --- a/test/push_tests.erl +++ b/test/push_tests.erl @@ -3,7 +3,7 @@ %%% Created : 15 Jul 2017 by Holger Weiss <holger@zedat.fu-berlin.de> %%% %%% -%%% ejabberd, Copyright (C) 2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/replaced_tests.erl b/test/replaced_tests.erl index 6141abd16..884852c3e 100644 --- a/test/replaced_tests.erl +++ b/test/replaced_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/roster_tests.erl b/test/roster_tests.erl index 8ef206470..38420abb7 100644 --- a/test/roster_tests.erl +++ b/test/roster_tests.erl @@ -3,7 +3,7 @@ %%% Created : 22 Oct 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/sm_tests.erl b/test/sm_tests.erl index 134a2f951..3eb2bf214 100644 --- a/test/sm_tests.erl +++ b/test/sm_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/suite.erl b/test/suite.erl index 62c394a55..b466bd02a 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -3,7 +3,7 @@ %%% Created : 27 Jun 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/test_helper.exs b/test/test_helper.exs deleted file mode 100644 index 454f2338a..000000000 --- a/test/test_helper.exs +++ /dev/null @@ -1,7 +0,0 @@ -Code.require_file "ejabberd_auth_mock.exs", __DIR__ -Code.require_file "ejabberd_oauth_mock.exs", __DIR__ -Code.require_file "ejabberd_sm_mock.exs", __DIR__ -Code.require_file "mod_last_mock.exs", __DIR__ -Code.require_file "mod_roster_mock.exs", __DIR__ - -ExUnit.start diff --git a/test/upload_tests.erl b/test/upload_tests.erl index ed1e90845..0234a8847 100644 --- a/test/upload_tests.erl +++ b/test/upload_tests.erl @@ -3,7 +3,7 @@ %%% Created : 17 May 2018 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/vcard_tests.erl b/test/vcard_tests.erl index 6f935e39b..0ee2e5459 100644 --- a/test/vcard_tests.erl +++ b/test/vcard_tests.erl @@ -3,7 +3,7 @@ %%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> %%% %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/tools/xml_compress_gen.erl b/tools/xml_compress_gen.erl index 4dad71a43..f19bcfdbd 100644 --- a/tools/xml_compress_gen.erl +++ b/tools/xml_compress_gen.erl @@ -4,7 +4,7 @@ %% Created : 14 Sep 2018 Pawel Chmielowski %% %% -%% ejabberd, Copyright (C) 2002-2018 ProcessOne +%% ejabberd, Copyright (C) 2002-2019 ProcessOne %% %% This program is free software; you can redistribute it and/or %% modify it under the terms of the GNU General Public License as @@ -117,8 +117,8 @@ gen_decode(Dev, Data, VerId) -> " {Children, Rest4} = decode_children(Rest3, PNs, J1, J2),~n" " {{xmlel, Name, Attrs, Children}, Rest4};~n", []), io:format(Dev, "decode_child(<<3:8, Rest/binary>>, PNs, J1, J2) ->~n" - " {Name, Rest2} = decode_string(Rest),~n" - " {Ns, Rest3} = decode_string(Rest2),~n" + " {Ns, Rest2} = decode_string(Rest),~n" + " {Name, Rest3} = decode_string(Rest2),~n" " {Attrs, Rest4} = decode_attrs(Rest3),~n" " {Children, Rest5} = decode_children(Rest4, Ns, J1, J2),~n" " {{xmlel, Name, add_ns(PNs, Ns, Attrs), Children}, Rest5};~n", []), diff --git a/vars.config.in b/vars.config.in index 9878ee2b4..045c0874d 100644 --- a/vars.config.in +++ b/vars.config.in @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% ejabberd, Copyright (C) 2002-2019 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -39,7 +39,6 @@ {riak, @riak@}. {redis, @redis@}. {elixir, @elixir@}. -{iconv, @iconv@}. {stun, @stun@}. {sip, @sip@}. |