Compare commits

...

29 Commits

Author SHA1 Message Date
Jerome Sautret 633b362577 Increase version to 20.3.0 2020-03-25 11:35:38 +01:00
Badlop 150b7e7219 Fix unsubscribe command result, handle_sync_event result, and dialyzer
How to reproduce the problems fixed by this commit:
Create temporary room, other account subscribes, and owner leaves
Unsubscribe that account with the command: ejabberdctl unsubscribe_room ...
2020-03-24 11:44:22 +01:00
Paweł Chmielowski e6065bf08f Update changelog 2020-03-23 17:55:11 +01:00
Paweł Chmielowski c2aa5f77bf Update mix.lock 2020-03-23 17:42:57 +01:00
Paweł Chmielowski 7caec56e96 Make bounce_message_queue wait for 100ms for incoming messages
There is possibilty that between c2s process unregistering itself from sm
and terminating, some other process could try to send something to c2s,
which could result in messages to triggering mam/offline hooks, and causing
them not to be stored in any way.
2020-03-23 15:16:33 +01:00
Paweł Chmielowski 97354426cf Make mod_muc_room:unsubscirbe handle that unsubscribe may stop room 2020-03-23 13:16:48 +01:00
Paweł Chmielowski 63e3fb92d1 Better handling of xml parse errors in send_stanza 2020-03-23 12:59:30 +01:00
Paweł Chmielowski a2d1ffffe6 Add baisc tests for webadmin 2020-03-23 10:52:07 +01:00
Paweł Chmielowski f17d4c0adc Update deps 2020-03-19 12:11:46 +01:00
Paweł Chmielowski 92a09fdb71 Also add "escape '\'" to prepared statements in pgsqllike_escape 2020-03-18 14:36:17 +01:00
Paweł Chmielowski 039d786e1f Add escape '\' to like expression in pgsql to fix problem cockroachdb
Cockroachdb doesn't properly handle escaping of _ in like expressions,
having "like ... escape '\'" makes it work, by disabling optimization that
causes this broken behaviour
2020-03-18 14:31:13 +01:00
Paweł Chmielowski 2d707cc0d2 Fix type of computed field in node_flat sql query 2020-03-18 14:05:05 +01:00
Paweł Chmielowski 0a88d03dc9 Use correct type for seconds field in mod_last sql queries 2020-03-18 14:05:05 +01:00
Paweł Chmielowski f12ee28660 Change conversion of boolean values for cockroachdb 2020-03-18 14:05:05 +01:00
Badlop 260c289d34 Fix Dialyzer warning that jid can't be 'undefined' 2020-03-18 12:02:16 +01:00
Paweł Chmielowski d8899ca9ac Add cache to mod_shared_roster
This should help with excessive queries that sql backend generates
Should fix issue #3158.
2020-03-17 14:35:43 +01:00
Paweł Chmielowski 1e456065f6 Fix issue with family field on cockroachdb 2020-03-17 11:35:54 +01:00
Paweł Chmielowski 82074190fb Replace mod_shared_roster:X call with just X inside that module 2020-03-16 14:57:55 +01:00
Paweł Chmielowski 6fe7c5cac5 Try to limit calls to groups_with_opts in mod_shared_roster 2020-03-16 13:29:05 +01:00
Badlop e9d1201ea8 Pass base path instead of level to support URL missing slash (#3177) 2020-03-11 16:26:33 +01:00
Paweł Chmielowski 9a89b360c0 fix command rooms_empty_destroy (#3183) 2020-03-05 11:41:51 +01:00
Paweł Chmielowski b39a1e2d74 Add reload handler to ejabberd_auth_ldap
This will restart ldap process with new options, and should made it
recognize new values.

This fixes issue #3181
2020-03-04 13:19:41 +01:00
Paweł Chmielowski 151b818af4 Use compilation flags used during build to compile modules in ext_mod
This fixes issue #3178
2020-03-03 11:25:17 +01:00
Paweł Chmielowski df47e2a93f Fix list parameters in sql queries on pgsql 2020-02-27 11:10:30 +01:00
Mickaël Rémond d0e93f9219 Merge pull request #3125 from area-42/enable_odbc_in_mix
enable odbc in mix build
2020-02-26 14:45:01 +01:00
Badlop 47c5aba1e5 Allow mod_register_web to be accessed from now-served vhosts (#3173) 2020-02-26 13:57:19 +01:00
Badlop 00abf5d42c Fix handle of 'http' atom in Headers, problem introduced in 357e7e11 2020-02-26 13:56:38 +01:00
Paweł Chmielowski 9c25d1024a Support ssl connection on mysql 2020-02-26 10:54:04 +01:00
Christoph Scholz 8eccbade56 enable odbc in mix build 2019-12-25 00:38:48 +01:00
25 changed files with 611 additions and 293 deletions
+20
View File
@@ -1,3 +1,23 @@
# Version 20.03
* Changes in this version
- Add support of ssl connection when connection to mysql
database (configured with `sql_ssl: true` option)
- Experimental support for cockroachdb when configured
with postgres connector
- Add cache and optimize queries issued by `mod_shared_roster`,
this should greatly improve performance of this module when
used with `sql` backend
- Fix problem with accessing webadmin
- Make webadmin work even when url is missing trailing slash
- When compiling external modules with ext_mod, use flags
that were detected during compilation of ejabberd
- Make config changed to ldap options be updated when issued
`reload_config` command
- Fix `room_empty_destory` command
- Fix reporting errors in `send_stanza` command when xml
passed to it couldn't be passed correctly
# Version 20.02
* Changes in this version
+18 -4
View File
@@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do
def project do
[app: :ejabberd,
version: "20.2.0",
version: "20.3.0",
description: description(),
elixir: "~> 1.4",
elixirc_paths: ["lib"],
@@ -51,12 +51,25 @@ defmodule Ejabberd.Mixfile do
end
end
defp if_version_below(ver, okResult) do
if :erlang.system_info(:otp_release) < ver do
okResult
else
[]
end
end
defp erlc_options do
# Use our own includes + includes from all dependencies
includes = ["include"] ++ deps_include(["fast_xml", "xmpp", "p1_utils"])
[:debug_info, {:d, :ELIXIR_ENABLED}] ++ cond_options() ++ Enum.map(includes, fn(path) -> {:i, path} end) ++
if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
if_function_exported(:erl_error, :format_exception, 6, [{:d, :HAVE_ERL_ERROR}])
result = [:debug_info, {:d, :ELIXIR_ENABLED}] ++
cond_options() ++
Enum.map(includes, fn (path) -> {:i, path} end) ++
if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
if_version_below('22', [{:d, :LAGER}]) ++
if_function_exported(:erl_error, :format_exception, 6, [{:d, :HAVE_ERL_ERROR}])
defines = for {:d, value} <- result, do: {:d, value}
result ++ [{:d, :ALL_DEFS, defines}]
end
defp cond_options do
@@ -120,6 +133,7 @@ defmodule Ejabberd.Mixfile do
defp cond_apps do
for {:true, app} <- [{config(:redis), :eredis},
{config(:mysql), :p1_mysql},
{config(:odbc), :odbc},
{config(:pgsql), :p1_pgsql},
{config(:sqlite), :sqlite3},
{config(:zlib), :ezlib}], do:
+32 -32
View File
@@ -1,38 +1,38 @@
%{
"artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm"},
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
"cache_tab": {:hex, :cache_tab, "1.0.22", "ad16577e7f26709cacdcb86e6a4960c8d158cab9d189cdf49cc1e2dc33106a70", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm"},
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm"},
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm", "514586f4312ef3709a3ccbd8e55f69455add235c1729656687bb781d10d0afdb"},
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm", "fab09b20e3f5db886725544cbcf875b8e73ec93363954eb8a1a9ed834aa8c1f9"},
"cache_tab": {:hex, :cache_tab, "1.0.22", "ad16577e7f26709cacdcb86e6a4960c8d158cab9d189cdf49cc1e2dc33106a70", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "53ed75e7c289434953a4407eb0a40b8675c5046b057313f97cf10e196efd8d79"},
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm", "bbc7008b0161a6f130d8d903b5b3232351fccc9c31a991f8fcbf2a12ace22995"},
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"},
"epam": {:hex, :epam, "1.0.6", "6e57e1f5a330fa02a08ee0d4b16d9161f95177351e48c6dfede2f89b7e2f589f", [:rebar3], [], "hexpm"},
"eredis": {:hex, :eredis, "1.2.0", "0b8e9cfc2c00fa1374cd107ea63b49be08d933df2cf175e6a89b73dd9c380de4", [:rebar3], [], "hexpm"},
"esip": {:hex, :esip, "1.0.32", "b6d5d9eb8342b86509de02ac79e6a9a772dab011e936092441d4e92a7986ca29", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.31", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"ezlib": {:hex, :ezlib, "1.0.7", "c8adffd32e66831df77955d163d705cdcf0a3d66762e6f68f8123012e714bf05", [:rebar3], [], "hexpm"},
"fast_tls": {:hex, :fast_tls, "1.1.4", "a0320baf14be72fc9f99211543e411bb98077bf72c42e2d86fc4e2c10d60c258", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_xml": {:hex, :fast_xml, "1.1.39", "687080c0190a8c45d564a3576201f1a89f31ae413dd700a2def0821736f98d4d", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_yaml": {:hex, :fast_yaml, "1.0.23", "0c74d6274c232609467bf55563066840c265e70081ee0c23215d1f3ca2624dfc", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"jiffy": {:hex, :jiffy, "1.0.1", "4f25639772ca41202f41ba9c8f6ca0933554283dd4742c90651e03471c55e341", [:rebar3], [], "hexpm"},
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm"},
"lager": {:hex, :lager, "3.6.10", "6172b43ab720ac33914ccd0aeb21fdbdf88213847707d4b91e6af57b2ae5c4d2", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm"},
"esip": {:hex, :esip, "1.0.32", "b6d5d9eb8342b86509de02ac79e6a9a772dab011e936092441d4e92a7986ca29", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.31", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "ab083aaa144c718d5f1c06b3034947cf6a9f73aedca04015813c983478ad94ed"},
"ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0db1ee8d1547ab4877c5b5dffc6604ef9454e189928d5ba8967d4a58a801f161"},
"ezlib": {:hex, :ezlib, "1.0.7", "c8adffd32e66831df77955d163d705cdcf0a3d66762e6f68f8123012e714bf05", [:rebar3], [], "hexpm", "5634b9f7112837f9338a61da1993601f4ab81615de84ff0baddcdc5a3fe940dc"},
"fast_tls": {:hex, :fast_tls, "1.1.4", "a0320baf14be72fc9f99211543e411bb98077bf72c42e2d86fc4e2c10d60c258", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "027fc2a726d6f3ad36c7fa230780000e8d3fc72dc8b397c9bff2018d3f5ff06a"},
"fast_xml": {:hex, :fast_xml, "1.1.39", "687080c0190a8c45d564a3576201f1a89f31ae413dd700a2def0821736f98d4d", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "2521816ed30b9c76befd85e477b5173c0329bd08fc8429f970b668c14bddb3f9"},
"fast_yaml": {:hex, :fast_yaml, "1.0.24", "d304799e6b961a21a509449830193154870b2b526cfc2e7046e9953ad413765f", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "71f4d5f868a2cfd4794e6bbd89495c4e4c54c45c6cb65b7f12d96271d6c02c84"},
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm", "99cb4128cffcb3227581e5d4d803d5413fa643f4eb96523f77d9e6937d994ceb"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
"jiffy": {:hex, :jiffy, "1.0.1", "4f25639772ca41202f41ba9c8f6ca0933554283dd4742c90651e03471c55e341", [:rebar3], [], "hexpm", "2568927f6f5e383cb775f6fd87bc6e80ea5f7d813418de450aa644b02c7f7112"},
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm", "6429c4fee52b2dda7861ee19a4f09c8c1ffa213bee3a1ec187828fde95d447ed"},
"lager": {:hex, :lager, "3.6.10", "6172b43ab720ac33914ccd0aeb21fdbdf88213847707d4b91e6af57b2ae5c4d2", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm", "5d10499461826b79c5abee18bb594b3949cbdf76d9d9fd7e66d0a558137c21c9"},
"luerl": {:hex, :luerl, "0.3.1", "5412807630aac1aaf59ffe5a1bc09259c447b4faeb1d3fe2d4ef41b87676cb04", [:rebar3], [], "hexpm"},
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
"mqtree": {:hex, :mqtree, "1.0.7", "0d8f6101eb2bb6a6e27f0e5a60cfad04b27dd552e75f30294e565605ce7cd0d2", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm"},
"p1_acme": {:hex, :p1_acme, "1.0.4", "2d118dbc38e7bc8eda34f4c5bf7afa6bce1345affc022bba514f42e194818820", [:rebar3], [{:idna, "~>6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~>1.0.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~>1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~>1.0.3", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm"},
"p1_mysql": {:hex, :p1_mysql, "1.0.13", "6a17bfd7a33d035673d633572e93370bdd2fcf4077362ed13b1a8fd8176a1643", [:rebar3], [], "hexpm"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.6", "b17053bd7a34621f9a1a7327285a3e37abd38eb1d176afccc8cfc39882ff0a44", [:rebar3], [], "hexpm"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.9", "07ff9b037954dec06b4e30e33a82ac69a5a513e2860d2e59b7f6f4af23493c45", [:rebar3], [], "hexpm"},
"p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm"},
"pkix": {:hex, :pkix, "1.0.5", "407c02c70191d0791cd9b422ac2380df5f7f8304ec26a6d3b06e0e02be688fca", [:rebar3], [], "hexpm"},
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"},
"mqtree": {:hex, :mqtree, "1.0.7", "0d8f6101eb2bb6a6e27f0e5a60cfad04b27dd552e75f30294e565605ce7cd0d2", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "317db0349a8d9695bc89ef7062e9654e93347cd9576f827739650e26482825bb"},
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
"p1_acme": {:hex, :p1_acme, "1.0.5", "de54353100ed82d0c820fbc011b7a7ad54f65af052eb8112922ad8be8eadf8f1", [:rebar3], [{:idna, "~>6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~>1.0.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~>1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~>1.0.4", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "cbecfc70ce11d37d679875117c685aa2a7bc2502bfa51722c8e619602c92a0c0"},
"p1_mysql": {:hex, :p1_mysql, "1.0.14", "ea2d58d0551d62fce9882f65fc7e0273ae6d683ab277aad657a661f514411198", [:rebar3], [], "hexpm", "70df0680b71118ace166e59fbf8be19058be3c3918bc3b7ede6e1f297a4a9dbe"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.6", "b17053bd7a34621f9a1a7327285a3e37abd38eb1d176afccc8cfc39882ff0a44", [:rebar3], [], "hexpm", "8a5fd16fc581a50e62176ab8b78b83b6e7cc6f76f7f59f75f58d713b7c1ca7b2"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.9", "07ff9b037954dec06b4e30e33a82ac69a5a513e2860d2e59b7f6f4af23493c45", [:rebar3], [], "hexpm", "81aab8cff0203250dd3d9cc77a0232dc9f8e56c99fd742abbaedc51a0fd633a7"},
"p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm", "1fc8773a71a15553b179c986b22fbeead19b28fe486c332d4929700ffeb71f88"},
"pkix": {:hex, :pkix, "1.0.5", "407c02c70191d0791cd9b422ac2380df5f7f8304ec26a6d3b06e0e02be688fca", [:rebar3], [], "hexpm", "b86aed212afaf019ac97bf56857366e5f01c3003f38ee050af8ba16455e13719"},
"sqlite3": {:hex, :sqlite3, "1.1.6", "4ea71af0b45908b5f02c9b09e4c87177039ef404f20accb35049cd8924cc417c", [:rebar3], [], "hexpm"},
"stringprep": {:hex, :stringprep, "1.0.19", "79761de42960a625fb0cd6d31686f6118aef30540a7abb884b92f72861b6adde", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"stun": {:hex, :stun, "1.0.31", "577d845d4b77b155bad234598c2056f6e182f178468727de083bedf275dc83a1", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
"xmpp": {:hex, :xmpp, "1.4.5", "b226baa9ad960e8de041289b94bbcb6148a7980acc0c1ec58dfc8f24acded3ad", [:rebar3], [{:ezlib, "1.0.7", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.39", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.19", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm"},
"yconf": {:hex, :yconf, "1.0.3", "7f71d0fe0e95ecb0f4004acee7b7db46c13e38c216d0bd03ef2a595a898d21a3", [:rebar3], [{:fast_yaml, "1.0.23", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm"},
"stringprep": {:hex, :stringprep, "1.0.19", "79761de42960a625fb0cd6d31686f6118aef30540a7abb884b92f72861b6adde", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "3f77edbcb530899faffe95d57b6e2bac704a5a6ea1ead5957387f9e4ed8c5f07"},
"stun": {:hex, :stun, "1.0.31", "577d845d4b77b155bad234598c2056f6e182f178468727de083bedf275dc83a1", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "c7edd93d823c0e1438bfe70adf99c39cf4cbca73cbd3c086c6e461ad00c6f8d4"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"},
"xmpp": {:hex, :xmpp, "1.4.5", "b226baa9ad960e8de041289b94bbcb6148a7980acc0c1ec58dfc8f24acded3ad", [:rebar3], [{:ezlib, "1.0.7", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.39", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.19", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "7bd21dd10ff3369f65128fcf730595073f1b6288a8b563d165874aecb2220317"},
"yconf": {:hex, :yconf, "1.0.4", "f08dcc2ad041f68580e98753f70453976d256f2c1a40a29a985465ab16d489a6", [:rebar3], [{:fast_yaml, "1.0.24", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "44570111ad224ee4eec6e2bffa1e7223ef4b76f91f9dd2f768eee214d2dcabe2"},
}
+4 -4
View File
@@ -26,20 +26,20 @@
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.39"}}},
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.4.5"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.23"}}},
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.3"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.24"}}},
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.4"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.0.1"}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.6"}}},
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.5"}}},
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.9.0"}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.14"}}},
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.7"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.4"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.5"}}},
{base64url, ".*", {git, "https://github.com/dvv/base64url.git", {tag, "v1.0"}}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.31"}}}},
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.32"}}}},
{if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql",
{tag, "1.0.13"}}}},
{tag, "1.0.14"}}}},
{if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql",
{tag, "1.1.9"}}}},
{if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3",
+4 -2
View File
@@ -304,12 +304,14 @@ fun(Hooks) ->
end,
ProcessErlOpt = fun(Vals) ->
lists:map(
R = lists:map(
fun({i, Path}) ->
{i, ResolveDepPath(Path)};
(ErlOpt) ->
ErlOpt
end, Vals)
end, Vals),
M = lists:filter(fun({d, M}) -> true; (_) -> false end, R),
[{d, 'ALL_DEFS', M} | R]
end,
ProcssXrefExclusions = fun(Items) ->
+6 -1
View File
@@ -37,7 +37,8 @@
-export([start/1, stop/1, start_link/1, set_password/3,
check_password/4, user_exists/2,
get_users/2, count_users/2,
store_type/1, plain_password_required/1]).
store_type/1, plain_password_required/1,
reload/1]).
-include("logger.hrl").
@@ -109,6 +110,10 @@ init(Host) ->
State#state.password, State#state.tls_options),
{ok, State}.
reload(Host) ->
stop(Host),
start(Host).
plain_password_required(_) -> true.
store_type(_) -> external.
+1 -1
View File
@@ -902,7 +902,7 @@ bounce_message_queue({_, Pid} = SID, JID) ->
receive {route, Pkt} ->
ejabberd_router:route(Pkt),
bounce_message_queue(SID, JID)
after 0 ->
after 100 ->
ok
end
end.
+6 -2
View File
@@ -857,9 +857,13 @@ parse_urlencoded(<<>>, Last, Cur, _State) ->
parse_urlencoded(undefined, _, _, _) -> [].
apply_custom_headers(Headers, CustomHeaders) ->
M = maps:merge(maps:from_list(Headers),
{Doctype, Headers2} = case Headers -- [html] of
Headers -> {[], Headers};
Other -> {[html], Other}
end,
M = maps:merge(maps:from_list(Headers2),
maps:from_list(CustomHeaders)),
maps:to_list(M).
Doctype ++ maps:to_list(M).
% The following code is mostly taken from yaws_ssl.erl
+21 -11
View File
@@ -253,7 +253,7 @@ to_list(EscapeFun, Val) ->
to_array(EscapeFun, Val) ->
Escaped = lists:join(<<",">>, lists:map(EscapeFun, Val)),
[<<"{">>, Escaped, <<"}">>].
lists:flatten([<<"{">>, Escaped, <<"}">>]).
to_string_literal(odbc, S) ->
<<"'", (escape(S))/binary, "'">>;
@@ -736,11 +736,11 @@ pgsql_sql_query_format(SQLQuery) ->
pgsql_escape() ->
#sql_escape{string = fun(X) -> <<"E'", (escape(X))/binary, "'">> end,
integer = fun(X) -> misc:i2l(X) end,
boolean = fun(true) -> <<"1">>;
(false) -> <<"0">>
boolean = fun(true) -> <<"'t'">>;
(false) -> <<"'f'">>
end,
in_array_string = fun(X) -> <<"E'", (escape(X))/binary, "'">> end,
like_escape = fun() -> <<"">> end
like_escape = fun() -> <<"ESCAPE E'\\\\'">> end
}.
sqlite_sql_query(SQLQuery) ->
@@ -776,11 +776,13 @@ pgsql_prepare(SQLQuery, State) ->
like_escape = fun() -> escape end},
{RArgs, _} =
lists:foldl(
fun(arg, {Acc, I}) ->
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1};
(escape, {Acc, I}) ->
{[<<"">> | Acc], I}
end, {[], 1}, (SQLQuery#sql_query.args)(Escape)),
fun(arg, {Acc, I}) ->
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1};
(escape, {Acc, I}) ->
{[<<"ESCAPE E'\\\\'">> | Acc], I};
(List, {Acc, I}) when is_list(List) ->
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1}
end, {[], 1}, (SQLQuery#sql_query.args)(Escape)),
Args = lists:reverse(RArgs),
%N = length((SQLQuery#sql_query.args)(Escape)),
%Args = [<<$$, (integer_to_binary(I))/binary>> || I <- lists:seq(1, N)],
@@ -1001,12 +1003,18 @@ pgsql_execute_to_odbc(_) -> {updated, undefined}.
%% part of init/1
%% Open a database connection to MySQL
mysql_connect(Server, Port, DB, Username, Password, ConnectTimeout, _, _) ->
mysql_connect(Server, Port, DB, Username, Password, ConnectTimeout, Transport, _) ->
SSLOpts = case Transport of
ssl ->
[ssl_required];
_ ->
[]
end,
case p1_mysql_conn:start(binary_to_list(Server), Port,
binary_to_list(Username),
binary_to_list(Password),
binary_to_list(DB),
ConnectTimeout, fun log/3)
ConnectTimeout, fun log/3, SSLOpts)
of
{ok, Ref} ->
p1_mysql_conn:fetch(
@@ -1112,6 +1120,8 @@ warn_if_ssl_unsupported(tcp, _) ->
ok;
warn_if_ssl_unsupported(ssl, pgsql) ->
ok;
warn_if_ssl_unsupported(ssl, mysql) ->
ok;
warn_if_ssl_unsupported(ssl, Type) ->
?WARNING_MSG("SSL connection is not supported for ~ts", [Type]).
+5 -1
View File
@@ -648,7 +648,11 @@ make_sql_upsert_insert(Table, ParseRes) ->
]),
State.
make_sql_upsert_pgsql901(Table, ParseRes) ->
make_sql_upsert_pgsql901(Table, ParseRes0) ->
ParseRes = lists:map(
fun({"family", A2, A3}) -> {"\"family\"", A2, A3};
(Other) -> Other
end, ParseRes0),
Update = make_sql_upsert_update(Table, ParseRes),
Vals =
lists:map(
+107 -124
View File
@@ -29,8 +29,8 @@
-author('alexey@process-one.net').
-export([process/2, list_users/4,
list_users_in_diapason/4, pretty_print_xml/1,
-export([process/2, list_users/5,
list_users_in_diapason/5, pretty_print_xml/1,
term_to_id/1]).
-include("logger.hrl").
@@ -95,20 +95,20 @@ get_jid(Auth, HostHTTP, Method) ->
throw({unauthorized, Auth})
end.
get_menu_items(global, cluster, Lang, JID, Level) ->
{_Base, _, Items} = make_server_menu([], [], Lang, JID, Level),
get_menu_items(global, cluster, Lang, JID, Base) ->
{_BaseURL, _, Items} = make_server_menu([], [], Lang, JID, Base),
lists:map(fun ({URI, Name}) ->
{<<URI/binary, "/">>, Name};
{<<Base/binary, URI/binary, "/">>, Name};
({URI, Name, _SubMenu}) ->
{<<URI/binary, "/">>, Name}
{<<Base/binary, URI/binary, "/">>, Name}
end,
Items);
get_menu_items(Host, cluster, Lang, JID, Level) ->
{_Base, _, Items} = make_host_menu(Host, [], Lang, JID, Level),
get_menu_items(Host, cluster, Lang, JID, Base) ->
{_BaseURL, _, Items} = make_host_menu(Host, [], Lang, JID, Base),
lists:map(fun ({URI, Name}) ->
{<<URI/binary, "/">>, Name};
{<<Base/binary, URI/binary, "/">>, Name};
({URI, Name, _SubMenu}) ->
{<<URI/binary, "/">>, Name}
{<<Base/binary, URI/binary, "/">>, Name}
end,
Items).
@@ -123,10 +123,10 @@ get_menu_items(Host, cluster, Lang, JID, Level) ->
%% Items
%% ).
is_allowed_path(BasePath, {Path, _}, JID) ->
is_allowed_path(BasePath ++ [Path], JID);
is_allowed_path(BasePath, {Path, _, _}, JID) ->
is_allowed_path(BasePath ++ [Path], JID).
is_allowed_path(Base, {Path, _}, JID) ->
is_allowed_path(Base ++ [Path], JID);
is_allowed_path(Base, {Path, _, _}, JID) ->
is_allowed_path(Base ++ [Path], JID).
is_allowed_path([<<"admin">> | Path], JID) ->
is_allowed_path(Path, JID);
@@ -152,7 +152,7 @@ url_to_path(URL) -> str:tokens(URL, <<"/">>).
process([<<"server">>, SHost | RPath] = Path,
#request{auth = Auth, lang = Lang, host = HostHTTP,
method = Method} =
path = RequestPath, method = Method} =
Request) ->
Host = jid:nameprep(SHost),
case ejabberd_router:is_my_host(Host) of
@@ -160,7 +160,8 @@ process([<<"server">>, SHost | RPath] = Path,
case get_auth_admin(Auth, HostHTTP, Path, Method) of
{ok, {User, Server}} ->
AJID = get_jid(Auth, HostHTTP, Method),
process_admin(Host,
Base = extract_base_path(RequestPath, Path),
process_admin(Base, Host,
Request#request{path = RPath,
us = {User, Server}},
AJID);
@@ -187,12 +188,13 @@ process([<<"server">>, SHost | RPath] = Path,
end;
process(RPath,
#request{auth = Auth, lang = Lang, host = HostHTTP,
method = Method} =
path = Path, method = Method} =
Request) ->
Base = extract_base_path(Path, RPath),
case get_auth_admin(Auth, HostHTTP, RPath, Method) of
{ok, {User, Server}} ->
AJID = get_jid(Auth, HostHTTP, Method),
process_admin(global,
process_admin(Base, global,
Request#request{path = RPath,
us = {User, Server}},
AJID);
@@ -266,16 +268,15 @@ get_auth_account2(HostOfRule, AccessRule, User, Server,
%%%==================================
%%%% make_xhtml
make_xhtml(Els, Host, Lang, JID, Level) ->
make_xhtml(Els, Host, cluster, Lang, JID, Level).
make_xhtml(Els, Host, Lang, JID, Base) ->
make_xhtml(Els, Host, cluster, Lang, JID, Base).
%% @spec (Els, Host, Node, Lang, JID) -> {200, [html], xmlelement()}
%% where Host = global | string()
%% Node = cluster | atom()
%% JID = jid()
make_xhtml(Els, Host, Node, Lang, JID, Level) ->
Base = get_base_path_sum(0, 0, Level),
MenuItems = make_navigation(Host, Node, Lang, JID, Level),
make_xhtml(Els, Host, Node, Lang, JID, Base) ->
MenuItems = make_navigation(Host, Node, Lang, JID, Base),
{200, [html],
#xmlel{name = <<"html">>,
attrs =
@@ -333,19 +334,19 @@ make_xhtml(Els, Host, Node, Lang, JID, Level) ->
direction(<<"he">>) -> [{<<"dir">>, <<"rtl">>}];
direction(_) -> [].
get_base_path(Host, Node, Level) ->
SumHost = case Host of
global -> 0;
_ -> -2
end,
SumNode = case Node of
cluster -> 0;
_ -> -2
end,
get_base_path_sum(SumHost, SumNode, Level).
extract_base_path(Path, RPath) ->
Base = lists:sublist(Path, length(Path)-length(RPath)),
iolist_to_binary("/" ++ lists:join("/", Base) ++ "/").
get_base_path_sum(SumHost, SumNode, Level) ->
iolist_to_binary(lists:duplicate(Level + SumHost + SumNode, "../")).
get_base_path(global, cluster, Base) -> Base;
get_base_path(Host, cluster, Base) ->
<<Base/binary, "/server/", Host/binary, "/">>;
get_base_path(global, Node, Base) ->
<<Base/binary, "/node/",
(iolist_to_binary(atom_to_list(Node)))/binary, "/">>;
get_base_path(Host, Node, Base) ->
<<Base/binary, "/server/", Host/binary, "/node/",
(iolist_to_binary(atom_to_list(Node)))/binary, "/">>.
%%%==================================
%%%% css & images
@@ -356,11 +357,11 @@ additions_js() ->
{error, _} -> <<>>
end.
css(Host) ->
css(Base, Host) ->
case misc:read_css("admin.css") of
{ok, CSS} ->
Base = get_base_path(Host, cluster, 0),
re:replace(CSS, <<"@BASE@">>, Base, [{return, binary}]);
BP = get_base_path(Host, cluster, Base),
re:replace(CSS, <<"@BASE@">>, BP, [{return, binary}]);
{error, _} ->
<<>>
end.
@@ -386,73 +387,73 @@ logo_fill() ->
%%%==================================
%%%% process_admin
process_admin(global, #request{path = [], lang = Lang}, AJID) ->
process_admin(Base, global, #request{path = [], lang = Lang}, AJID) ->
make_xhtml((?H1GL((translate:translate(Lang, ?T("Administration"))), <<"">>,
<<"Contents">>))
++
[?XE(<<"ul">>,
[?LI([?ACT(MIU, MIN)])
|| {MIU, MIN}
<- get_menu_items(global, cluster, Lang, AJID, 0)])],
global, Lang, AJID, 0);
process_admin(Host, #request{path = [], lang = Lang}, AJID) ->
<- get_menu_items(global, cluster, Lang, AJID, Base)])],
global, Lang, AJID, Base);
process_admin(Base, Host, #request{path = [], lang = Lang}, AJID) ->
make_xhtml([?XCT(<<"h1">>, ?T("Administration")),
?XE(<<"ul">>,
[?LI([?ACT(MIU, MIN)])
|| {MIU, MIN}
<- get_menu_items(Host, cluster, Lang, AJID, 2)])],
Host, Lang, AJID, 2);
process_admin(Host, #request{path = [<<"style.css">>]}, _) ->
<- get_menu_items(Host, cluster, Lang, AJID, Base)])],
Host, Lang, AJID, Base);
process_admin(Base, Host, #request{path = [<<"style.css">>]}, _) ->
{200,
[{<<"Content-Type">>, <<"text/css">>}, last_modified(),
cache_control_public()],
css(Host)};
process_admin(_Host, #request{path = [<<"favicon.ico">>]}, _) ->
css(Base, Host)};
process_admin(_Base, _Host, #request{path = [<<"favicon.ico">>]}, _) ->
{200,
[{<<"Content-Type">>, <<"image/x-icon">>},
last_modified(), cache_control_public()],
favicon()};
process_admin(_Host, #request{path = [<<"logo.png">>]}, _) ->
process_admin(_Base, _Host, #request{path = [<<"logo.png">>]}, _) ->
{200,
[{<<"Content-Type">>, <<"image/png">>}, last_modified(),
cache_control_public()],
logo()};
process_admin(_Host, #request{path = [<<"logo-fill.png">>]}, _) ->
process_admin(_Base, _Host, #request{path = [<<"logo-fill.png">>]}, _) ->
{200,
[{<<"Content-Type">>, <<"image/png">>}, last_modified(),
cache_control_public()],
logo_fill()};
process_admin(_Host, #request{path = [<<"additions.js">>]}, _) ->
process_admin(_Base, _Host, #request{path = [<<"additions.js">>]}, _) ->
{200,
[{<<"Content-Type">>, <<"text/javascript">>},
last_modified(), cache_control_public()],
additions_js()};
process_admin(global, #request{path = [<<"vhosts">>], lang = Lang}, AJID) ->
process_admin(Base, global, #request{path = [<<"vhosts">>], lang = Lang}, AJID) ->
Res = list_vhosts(Lang, AJID),
make_xhtml((?H1GL((translate:translate(Lang, ?T("Virtual Hosts"))),
<<"virtual-hosting">>, ?T("Virtual Hosting")))
++ Res,
global, Lang, AJID, 1);
process_admin(Host, #request{path = [<<"users">>], q = Query,
global, Lang, AJID, Base);
process_admin(Base, Host, #request{path = [<<"users">>], q = Query,
lang = Lang}, AJID)
when is_binary(Host) ->
Res = list_users(Host, Query, Lang, fun url_func/1),
Res = list_users(Base, Host, Query, Lang, fun url_func/1),
make_xhtml([?XCT(<<"h1">>, ?T("Users"))] ++ Res, Host,
Lang, AJID, 3);
process_admin(Host, #request{path = [<<"users">>, Diap],
Lang, AJID, Base);
process_admin(Base, Host, #request{path = [<<"users">>, Diap],
lang = Lang}, AJID)
when is_binary(Host) ->
Res = list_users_in_diapason(Host, Diap, Lang,
Res = list_users_in_diapason(Base, Host, Diap, Lang,
fun url_func/1),
make_xhtml([?XCT(<<"h1">>, ?T("Users"))] ++ Res, Host,
Lang, AJID, 4);
process_admin(Host, #request{path = [<<"online-users">>],
Lang, AJID, Base);
process_admin(Base, Host, #request{path = [<<"online-users">>],
lang = Lang}, AJID)
when is_binary(Host) ->
Res = list_online_users(Host, Lang),
make_xhtml([?XCT(<<"h1">>, ?T("Online Users"))] ++ Res,
Host, Lang, AJID, 3);
process_admin(Host, #request{path = [<<"last-activity">>],
Host, Lang, AJID, Base);
process_admin(Base, Host, #request{path = [<<"last-activity">>],
q = Query, lang = Lang}, AJID)
when is_binary(Host) ->
?DEBUG("Query: ~p", [Query]),
@@ -493,49 +494,37 @@ process_admin(Host, #request{path = [<<"last-activity">>],
?INPUTT(<<"submit">>, <<"integral">>,
?T("Show Integral Table"))])]
++ Res,
Host, Lang, AJID, 3);
process_admin(Host, #request{path = [<<"stats">>], lang = Lang}, AJID) ->
Host, Lang, AJID, Base);
process_admin(Base, Host, #request{path = [<<"stats">>], lang = Lang}, AJID) ->
Res = get_stats(Host, Lang),
PageH1 = ?H1GL(translate:translate(Lang, ?T("Statistics")), <<"mod-stats">>, <<"mod_stats">>),
Level = case Host of
global -> 1;
_ -> 3
end,
make_xhtml(PageH1 ++ Res, Host, Lang, AJID, Level);
process_admin(Host, #request{path = [<<"user">>, U],
make_xhtml(PageH1 ++ Res, Host, Lang, AJID, Base);
process_admin(Base, Host, #request{path = [<<"user">>, U],
q = Query, lang = Lang}, AJID) ->
case ejabberd_auth:user_exists(U, Host) of
true ->
Res = user_info(U, Host, Query, Lang),
make_xhtml(Res, Host, Lang, AJID, 4);
make_xhtml(Res, Host, Lang, AJID, Base);
false ->
make_xhtml([?XCT(<<"h1">>, ?T("Not Found"))], Host,
Lang, AJID, 4)
Lang, AJID, Base)
end;
process_admin(Host, #request{path = [<<"nodes">>], lang = Lang}, AJID) ->
process_admin(Base, Host, #request{path = [<<"nodes">>], lang = Lang}, AJID) ->
Res = get_nodes(Lang),
Level = case Host of
global -> 1;
_ -> 3
end,
make_xhtml(Res, Host, Lang, AJID, Level);
process_admin(Host, #request{path = [<<"node">>, SNode | NPath],
make_xhtml(Res, Host, Lang, AJID, Base);
process_admin(Base, Host, #request{path = [<<"node">>, SNode | NPath],
q = Query, lang = Lang}, AJID) ->
case search_running_node(SNode) of
false ->
make_xhtml([?XCT(<<"h1">>, ?T("Node not found"))], Host,
Lang, AJID, 2);
Lang, AJID, Base);
Node ->
Res = get_node(Host, Node, NPath, Query, Lang),
Level = case Host of
global -> 2 + length(NPath);
_ -> 4 + length(NPath)
end,
make_xhtml(Res, Host, Node, Lang, AJID, Level)
Res = get_node(Base, Host, Node, NPath, Query, Lang),
make_xhtml(Res, Host, Node, Lang, AJID, Base)
end;
%%%==================================
%%%% process_admin default case
process_admin(Host, #request{lang = Lang} = Request, AJID) ->
process_admin(Base, Host, #request{lang = Lang} = Request, AJID) ->
Res = case Host of
global ->
ejabberd_hooks:run_fold(
@@ -544,17 +533,13 @@ process_admin(Host, #request{lang = Lang} = Request, AJID) ->
ejabberd_hooks:run_fold(
webadmin_page_host, Host, [], [Host, Request])
end,
Level = case Host of
global -> length(Request#request.path);
_ -> 2 + length(Request#request.path)
end,
case Res of
[] ->
setelement(1,
make_xhtml([?XC(<<"h1">>, <<"Not Found">>)], Host, Lang,
AJID, Level),
AJID, Base),
404);
_ -> make_xhtml(Res, Host, Lang, AJID, Level)
_ -> make_xhtml(Res, Host, Lang, AJID, Base)
end.
term_to_id(T) -> base64:encode((term_to_binary(T))).
@@ -601,13 +586,13 @@ list_vhosts2(Lang, Hosts) ->
%%%==================================
%%%% list_users
list_users(Host, Query, Lang, URLFunc) ->
list_users(Base, Host, Query, Lang, URLFunc) ->
Res = list_users_parse_query(Query, Host),
Users = ejabberd_auth:get_users(Host),
SUsers = lists:sort([{S, U} || {U, S} <- Users]),
FUsers = case length(SUsers) of
N when N =< 100 ->
[list_given_users(Host, SUsers, <<"../">>, Lang,
[list_given_users(Host, SUsers, Base, Lang,
URLFunc)];
N ->
NParts = trunc(math:sqrt(N * 6.17999999999999993783e-1))
@@ -683,17 +668,18 @@ list_users_parse_query(Query, Host) ->
false -> nothing
end.
list_users_in_diapason(Host, Diap, Lang, URLFunc) ->
list_users_in_diapason(Base, Host, Diap, Lang, URLFunc) ->
Users = ejabberd_auth:get_users(Host),
SUsers = lists:sort([{S, U} || {U, S} <- Users]),
[S1, S2] = ejabberd_regexp:split(Diap, <<"-">>),
N1 = binary_to_integer(S1),
N2 = binary_to_integer(S2),
Sub = lists:sublist(SUsers, N1, N2 - N1 + 1),
[list_given_users(Host, Sub, <<"../../">>, Lang,
[list_given_users(Host, Sub, Base, Lang,
URLFunc)].
list_given_users(Host, Users, Prefix, Lang, URLFunc) ->
list_given_users(Host, Users, Base, Lang, URLFunc) ->
Prefix = get_base_path(Host, cluster, Base),
ModOffline = get_offlinemsg_module(Host),
?XE(<<"table">>,
[?XE(<<"thead">>,
@@ -1075,10 +1061,10 @@ search_running_node(SNode, [Node | Nodes]) ->
_ -> search_running_node(SNode, Nodes)
end.
get_node(global, Node, [], Query, Lang) ->
get_node(Base, global, Node, [], Query, Lang) ->
Res = node_parse_query(Node, Query),
Base = get_base_path(global, Node, 2),
MenuItems2 = make_menu_items(global, Node, Base, Lang),
BP = get_base_path(global, Node, Base),
MenuItems2 = make_menu_items(global, Node, BP, Lang),
[?XC(<<"h1">>,
(str:format(translate:translate(Lang, ?T("Node ~p")), [Node])))]
++
@@ -1099,12 +1085,12 @@ get_node(global, Node, [], Query, Lang) ->
[?INPUTT(<<"submit">>, <<"restart">>, ?T("Restart")),
?C(<<" ">>),
?INPUTT(<<"submit">>, <<"stop">>, ?T("Stop"))])];
get_node(Host, Node, [], _Query, Lang) ->
Base = get_base_path(Host, Node, 4),
MenuItems2 = make_menu_items(Host, Node, Base, Lang),
get_node(Base, Host, Node, [], _Query, Lang) ->
BP = get_base_path(Host, Node, Base),
MenuItems2 = make_menu_items(Host, Node, BP, Lang),
[?XC(<<"h1">>, (str:format(translate:translate(Lang, ?T("Node ~p")), [Node]))),
?XE(<<"ul">>, MenuItems2)];
get_node(global, Node, [<<"db">>], Query, Lang) ->
get_node(_Base, global, Node, [<<"db">>], Query, Lang) ->
case ejabberd_cluster:call(Node, mnesia, system_info, [tables]) of
{badrpc, _Reason} ->
[?XCT(<<"h1">>, ?T("RPC Call Error"))];
@@ -1182,7 +1168,7 @@ get_node(global, Node, [<<"db">>], Query, Lang) ->
<<"submit">>,
?T("Submit"))])])]))])])]
end;
get_node(global, Node, [<<"backup">>], Query, Lang) ->
get_node(_Base, global, Node, [<<"backup">>], Query, Lang) ->
HomeDirRaw = case {os:getenv("HOME"), os:type()} of
{EnvHome, _} when is_list(EnvHome) -> list_to_binary(EnvHome);
{false, {win32, _Osname}} -> <<"C:/">>;
@@ -1332,7 +1318,7 @@ get_node(global, Node, [<<"backup">>], Query, Lang) ->
?XE(<<"td">>,
[?INPUTT(<<"submit">>, <<"import_dir">>,
?T("OK"))])])])])])];
get_node(global, Node, [<<"stats">>], _Query, Lang) ->
get_node(_Base, global, Node, [<<"stats">>], _Query, Lang) ->
UpTime = ejabberd_cluster:call(Node, erlang, statistics,
[wall_clock]),
UpTimeS = (str:format("~.3f",
@@ -1381,7 +1367,7 @@ get_node(global, Node, [<<"stats">>], _Query, Lang) ->
[?XCT(<<"td">>, ?T("Transactions Logged:")),
?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}],
(pretty_string_int(TransactionsLogged)))])])])];
get_node(global, Node, [<<"update">>], Query, Lang) ->
get_node(_Base, global, Node, [<<"update">>], Query, Lang) ->
ejabberd_cluster:call(Node, code, purge, [ejabberd_update]),
Res = node_update_parse_query(Node, Query),
ejabberd_cluster:call(Node, code, load_file, [ejabberd_update]),
@@ -1437,7 +1423,7 @@ get_node(global, Node, [<<"update">>], Query, Lang) ->
?XC(<<"pre">>, (misc:atom_to_binary(Check))),
?BR,
?INPUTT(<<"submit">>, <<"update">>, ?T("Update"))])];
get_node(Host, Node, NPath, Query, Lang) ->
get_node(_Base, Host, Node, NPath, Query, Lang) ->
Res = case Host of
global ->
ejabberd_hooks:run_fold(webadmin_page_node, Host, [],
@@ -1749,19 +1735,19 @@ make_navigation_menu(Host, Node, Lang, JID, Level) ->
make_server_menu(HostMenu, NodeMenu, Lang, JID, Level).
%% @spec (Host, Node, Base, Lang) -> [LI]
make_menu_items(global, cluster, Base, Lang) ->
make_menu_items(global, cluster, BP, Lang) ->
HookItems = get_menu_items_hook(server, Lang),
make_menu_items(Lang, {Base, <<"">>, HookItems});
make_menu_items(global, Node, Base, Lang) ->
make_menu_items(Lang, {BP, <<"">>, HookItems});
make_menu_items(global, Node, BP, Lang) ->
HookItems = get_menu_items_hook({node, Node}, Lang),
make_menu_items(Lang, {Base, <<"">>, HookItems});
make_menu_items(Host, cluster, Base, Lang) ->
make_menu_items(Lang, {BP, <<"">>, HookItems});
make_menu_items(Host, cluster, BP, Lang) ->
HookItems = get_menu_items_hook({host, Host}, Lang),
make_menu_items(Lang, {Base, <<"">>, HookItems});
make_menu_items(Host, Node, Base, Lang) ->
make_menu_items(Lang, {BP, <<"">>, HookItems});
make_menu_items(Host, Node, BP, Lang) ->
HookItems = get_menu_items_hook({hostnode, Host, Node},
Lang),
make_menu_items(Lang, {Base, <<"">>, HookItems}).
make_menu_items(Lang, {BP, <<"">>, HookItems}).
make_host_node_menu(global, _, _Lang, _JID, _Level) ->
{<<"">>, <<"">>, []};
@@ -1803,22 +1789,19 @@ make_node_menu(global, Node, Lang, Level) ->
{<<"stats">>, ?T("Statistics")},
{<<"update">>, ?T("Update")}]
++ get_menu_items_hook({node, Node}, Lang),
{NodeBase, iolist_to_binary(atom_to_list(Node)),
NodeFixed};
make_node_menu(_Host, _Node, _Lang, _Level) ->
{<<"">>, <<"">>, []}.
{NodeBase, iolist_to_binary(atom_to_list(Node)), NodeFixed}.
make_server_menu(HostMenu, NodeMenu, Lang, JID, Level) ->
Base = get_base_path(global, cluster, Level),
BP = get_base_path(global, cluster, Level),
Fixed = [{<<"vhosts">>, ?T("Virtual Hosts"), HostMenu},
{<<"nodes">>, ?T("Nodes"), NodeMenu},
{<<"stats">>, ?T("Statistics")}]
++ get_menu_items_hook(server, Lang),
BasePath = url_to_path(Base),
Base = url_to_path(BP),
Fixed2 = [Tuple
|| Tuple <- Fixed,
is_allowed_path(BasePath, Tuple, JID)],
{Base, <<"">>, Fixed2}.
is_allowed_path(Base, Tuple, JID)],
{BP, <<"">>, Fixed2}.
get_menu_items_hook({hostnode, Host, Node}, Lang) ->
ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host,
+1 -1
View File
@@ -570,7 +570,7 @@ compile_result(Results) ->
end.
compile_options() ->
[verbose, report_errors, report_warnings]
[verbose, report_errors, report_warnings, ?ALL_DEFS]
++ [{i, filename:join(app_dir(App), "include")}
|| App <- [fast_xml, xmpp, p1_utils, ejabberd]]
++ [{i, filename:join(mod_dir(Mod), "include")}
+3
View File
@@ -1513,6 +1513,9 @@ send_stanza(FromString, ToString, Stanza) ->
catch _:{xmpp_codec, Why} ->
io:format("incorrect stanza: ~ts~n", [xmpp:format_error(Why)]),
{error, Why};
_:{badmatch, {error, {Code, Why}}} when is_integer(Code) ->
io:format("invalid xml: ~p~n", [Why]),
{error, Why};
_:{badmatch, {error, Why}} ->
io:format("invalid xml: ~p~n", [Why]),
{error, Why};
+1 -1
View File
@@ -268,7 +268,7 @@ is_received_muc_invite(Msg, received) ->
#muc_user{invites = [_|_]} ->
true;
_ ->
xmpp:has_subtag(Msg, #x_conference{})
xmpp:has_subtag(Msg, #x_conference{jid = jid:make(<<"">>)})
end.
-spec is_received_muc_pm(jid(), message(), direction()) -> boolean().
+4 -2
View File
@@ -55,10 +55,11 @@ get_last(LUser, LServer) ->
end.
store_last_info(LUser, LServer, TimeStamp, Status) ->
TS = integer_to_binary(TimeStamp),
case ?SQL_UPSERT(LServer, "last",
["!username=%(LUser)s",
"!server_host=%(LServer)s",
"seconds=%(TimeStamp)d",
"seconds=%(TS)s",
"state=%(Status)s"]) of
ok ->
ok;
@@ -76,11 +77,12 @@ export(_Server) ->
fun(Host, #last_activity{us = {LUser, LServer},
timestamp = TimeStamp, status = Status})
when LServer == Host ->
TS = integer_to_binary(TimeStamp),
[?SQL("delete from last where username=%(LUser)s and %(LServer)H;"),
?SQL_INSERT("last",
["username=%(LUser)s",
"server_host=%(LServer)s",
"seconds=%(TimeStamp)d",
"seconds=%(TS)s",
"state=%(Status)s"])];
(_Host, _R) ->
[]
+1 -1
View File
@@ -805,7 +805,7 @@ get_rooms(ServiceArg) ->
Hosts = find_services(ServiceArg),
lists:flatmap(
fun(Host) ->
[{RoomName, RoomHost, Host, Pid}
[{RoomName, RoomHost, ejabberd_router:host_of_route(Host), Pid}
|| {RoomName, RoomHost, Pid} <- mod_muc:get_online_rooms(Host)]
end, Hosts).
+7 -2
View File
@@ -217,6 +217,8 @@ unsubscribe(Pid, JID) ->
try p1_fsm:sync_send_all_state_event(Pid, {muc_unsubscribe, JID})
catch _:{timeout, {p1_fsm, _, _}} ->
{error, ?T("Request has timed out")};
exit:{normal, {p1_fsm, _, _}} ->
ok;
_:{_, {p1_fsm, _, _}} ->
{error, ?T("Conference room does not exist")}
end.
@@ -741,10 +743,13 @@ handle_sync_event({muc_subscribe, From, Nick, Nodes}, _From,
{error, Err} ->
{reply, {error, get_error_text(Err)}, StateName, StateData}
end;
handle_sync_event({muc_unsubscribe, From}, _From, StateName, StateData) ->
handle_sync_event({muc_unsubscribe, From}, _From, StateName,
#state{config = Conf} = StateData) ->
IQ = #iq{type = set, id = p1_rand:get_string(),
from = From, sub_els = [#muc_unsubscribe{}]},
case process_iq_mucsub(From, IQ, StateData) of
{result, _, stop} ->
{stop, normal, StateData#state{config = Conf#config{persistent = false}}};
{result, _, NewState} ->
{reply, ok, StateName, NewState};
{ignore, NewState} ->
@@ -4198,7 +4203,7 @@ process_iq_vcard(From, #iq{type = set, lang = Lang, sub_els = [Pkt]},
-spec process_iq_mucsub(jid(), iq(), state()) ->
{error, stanza_error()} |
{result, undefined | muc_subscribe() | muc_subscriptions(), state()} |
{result, undefined | muc_subscribe() | muc_subscriptions(), stop | state()} |
{ignore, state()}.
process_iq_mucsub(_From, #iq{type = set, lang = Lang,
sub_els = [#muc_subscribe{}]},
+11 -22
View File
@@ -93,31 +93,20 @@ process([], #request{method = 'GET', lang = Lang}) ->
process([<<"register.css">>],
#request{method = 'GET'}) ->
serve_css();
process([<<"new">>],
process([Section],
#request{method = 'GET', lang = Lang, host = Host,
ip = IP}) ->
case ejabberd_router:is_my_host(Host) of
ip = {Addr, _Port}}) ->
Host2 = case ejabberd_router:is_my_host(Host) of
true ->
{Addr, _Port} = IP,
form_new_get(Host, Lang, Addr);
Host;
false ->
{400, [], <<"Host not served">>}
end;
process([<<"delete">>],
#request{method = 'GET', lang = Lang, host = Host}) ->
case ejabberd_router:is_my_host(Host) of
true ->
form_del_get(Host, Lang);
false ->
{400, [], <<"Host not served">>}
end;
process([<<"change_password">>],
#request{method = 'GET', lang = Lang, host = Host}) ->
case ejabberd_router:is_my_host(Host) of
true ->
form_changepass_get(Host, Lang);
false ->
{400, [], <<"Host not served">>}
<<"">>
end,
case Section of
<<"new">> -> form_new_get(Host2, Lang, Addr);
<<"delete">> -> form_del_get(Host2, Lang);
<<"change_password">> -> form_changepass_get(Host2, Lang);
_ -> {404, [], "Not Found"}
end;
process([<<"new">>],
#request{method = 'POST', q = Q, ip = {Ip, _Port},
+242 -76
View File
@@ -71,10 +71,20 @@
-callback is_user_in_group({binary(), binary()}, binary(), binary()) -> boolean().
-callback add_user_to_group(binary(), {binary(), binary()}, binary()) -> any().
-callback remove_user_from_group(binary(), {binary(), binary()}, binary()) -> {atomic, any()}.
-callback use_cache(binary()) -> boolean().
-callback cache_nodes(binary()) -> [node()].
-optional_callbacks([use_cache/1, cache_nodes/1]).
-define(GROUP_OPTS_CACHE, shared_roster_group_opts_cache).
-define(USER_GROUPS_CACHE, shared_roster_user_groups_cache).
-define(GROUP_EXPLICIT_USERS_CACHE, shared_roster_group_explicit_cache).
-define(SPECIAL_GROUPS_CACHE, shared_roster_special_groups_cache).
start(Host, Opts) ->
Mod = gen_mod:db_mod(Opts, ?MODULE),
Mod:init(Host, Opts),
init_cache(Mod, Host, Opts),
ejabberd_hooks:add(webadmin_menu_host, Host, ?MODULE,
webadmin_menu, 70),
ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE,
@@ -136,6 +146,43 @@ reload(Host, NewOpts, OldOpts) ->
depends(_Host, _Opts) ->
[].
-spec init_cache(module(), binary(), gen_mod:opts()) -> ok.
init_cache(Mod, Host, Opts) ->
case use_cache(Mod, Host) of
true ->
CacheOpts = cache_opts(Opts),
ets_cache:new(?GROUP_OPTS_CACHE, CacheOpts),
ets_cache:new(?USER_GROUPS_CACHE, CacheOpts),
ets_cache:new(?GROUP_EXPLICIT_USERS_CACHE, CacheOpts),
ets_cache:new(?SPECIAL_GROUPS_CACHE, CacheOpts);
false ->
ets_cache:delete(?GROUP_OPTS_CACHE),
ets_cache:delete(?USER_GROUPS_CACHE),
ets_cache:delete(?GROUP_EXPLICIT_USERS_CACHE),
ets_cache:delete(?SPECIAL_GROUPS_CACHE)
end.
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
cache_opts(Opts) ->
MaxSize = mod_private_opt:cache_size(Opts),
CacheMissed = mod_private_opt:cache_missed(Opts),
LifeTime = mod_private_opt:cache_life_time(Opts),
[{max_size, MaxSize}, {cache_missed, CacheMissed}, {life_time, LifeTime}].
-spec use_cache(module(), binary()) -> boolean().
use_cache(Mod, Host) ->
case erlang:function_exported(Mod, use_cache, 1) of
true -> Mod:use_cache(Host);
false -> mod_shared_roster_opt:use_cache(Host)
end.
-spec cache_nodes(module(), binary()) -> [node()].
cache_nodes(Mod, Host) ->
case erlang:function_exported(Mod, cache_nodes, 1) of
true -> Mod:cache_nodes(Host);
false -> ejabberd_cluster:get_nodes()
end.
-spec get_user_roster([#roster{}], {binary(), binary()}) -> [#roster{}].
get_user_roster(Items, US) ->
{U, S} = US,
@@ -376,24 +423,69 @@ create_group(Host, Group) ->
create_group(Host, Group, Opts) ->
Mod = gen_mod:db_mod(Host, ?MODULE),
case use_cache(Mod, Host) of
true ->
ets_cache:insert(?GROUP_OPTS_CACHE, {Host, Group}, Opts, cache_nodes(Mod, Host)),
ets_cache:clear(?SPECIAL_GROUPS_CACHE, cache_nodes(Mod, Host));
_ ->
ok
end,
Mod:create_group(Host, Group, Opts).
delete_group(Host, Group) ->
Mod = gen_mod:db_mod(Host, ?MODULE),
case use_cache(Mod, Host) of
true ->
ets_cache:delete(?GROUP_OPTS_CACHE, {Host, Group}, cache_nodes(Mod, Host)),
ets_cache:clear(?USER_GROUPS_CACHE, cache_nodes(Mod, Host)),
ets_cache:clear(?GROUP_EXPLICIT_USERS_CACHE, cache_nodes(Mod, Host)),
ets_cache:clear(?SPECIAL_GROUPS_CACHE, cache_nodes(Mod, Host));
_ ->
ok
end,
Mod:delete_group(Host, Group).
get_group_opts(Host, Group) ->
Mod = gen_mod:db_mod(Host, ?MODULE),
Mod:get_group_opts(Host, Group).
case use_cache(Mod, Host) of
true ->
ets_cache:lookup(
?GROUP_OPTS_CACHE, {Host, Group},
fun() ->
case Mod:get_group_opts(Host, Group) of
error -> error;
V -> {cache, V}
end
end);
false ->
Mod:get_group_opts(Host, Group)
end.
set_group_opts(Host, Group, Opts) ->
Mod = gen_mod:db_mod(Host, ?MODULE),
case use_cache(Mod, Host) of
true ->
ets_cache:insert(?GROUP_OPTS_CACHE, {Host, Group}, Opts, cache_nodes(Mod, Host)),
ets_cache:clear(?SPECIAL_GROUPS_CACHE, cache_nodes(Mod, Host));
_ ->
ok
end,
Mod:set_group_opts(Host, Group, Opts).
get_user_groups(US) ->
Host = element(2, US),
Mod = gen_mod:db_mod(Host, ?MODULE),
Mod:get_user_groups(US, Host) ++ get_special_users_groups(Host).
UG = case use_cache(Mod, Host) of
true ->
ets_cache:lookup(
?USER_GROUPS_CACHE, {Host, US},
fun() ->
{cache, Mod:get_user_groups(US, Host)}
end);
false ->
Mod:get_user_groups(US, Host)
end,
UG ++ get_special_users_groups(Host).
is_group_enabled(Host1, Group1) ->
{Host, Group} = split_grouphost(Host1, Group1),
@@ -419,16 +511,7 @@ get_online_users(Host) ->
get_group_users(Host1, Group1) ->
{Host, Group} = split_grouphost(Host1, Group1),
case get_group_opt(Host, Group, all_users, false) of
true -> ejabberd_auth:get_users(Host);
false -> []
end
++
case get_group_opt(Host, Group, online_users, false) of
true -> get_online_users(Host);
false -> []
end
++ get_group_explicit_users(Host, Group).
get_group_users(Host, Group, get_group_opts(Host, Group)).
get_group_users(Host, Group, GroupOpts) ->
case proplists:get_value(all_users, GroupOpts, false) of
@@ -445,7 +528,16 @@ get_group_users(Host, Group, GroupOpts) ->
get_group_explicit_users(Host, Group) ->
Mod = gen_mod:db_mod(Host, ?MODULE),
Mod:get_group_explicit_users(Host, Group).
case use_cache(Mod, Host) of
true ->
ets_cache:lookup(
?GROUP_EXPLICIT_USERS_CACHE, {Host, Group},
fun() ->
{cache, Mod:get_group_explicit_users(Host, Group)}
end);
false ->
Mod:get_group_explicit_users(Host, Group)
end.
get_group_name(Host1, Group1) ->
{Host, Group} = split_grouphost(Host1, Group1),
@@ -453,24 +545,55 @@ 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: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)).
Extract =
fun() ->
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))
end,
Mod = gen_mod:db_mod(Host, ?MODULE),
case use_cache(Mod, Host) of
true ->
ets_cache:lookup(
?SPECIAL_GROUPS_CACHE, {Host, false},
fun() ->
{cache, Extract()}
end);
false ->
Extract()
end.
%% Get list of names of groups that have @online@ in the memberlist
get_special_users_groups_online(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)).
Extract =
fun() ->
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))
end,
Mod = gen_mod:db_mod(Host, ?MODULE),
case use_cache(Mod, Host) of
true ->
ets_cache:lookup(
?SPECIAL_GROUPS_CACHE, {Host, true},
fun() ->
{cache, Extract()}
end);
false ->
Extract()
end.
%% Given two lists of groupnames and their options,
%% return the list of displayed groups to the second list
@@ -555,27 +678,32 @@ add_user_to_group2(Host, US, Group) ->
{LUser, LServer} = US,
case ejabberd_regexp:run(LUser, <<"^@.+@\$">>) of
match ->
GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
GroupOpts = get_group_opts(Host, Group),
MoreGroupOpts = case LUser of
<<"@all@">> -> [{all_users, true}];
<<"@online@">> -> [{online_users, true}];
_ -> []
end,
mod_shared_roster:set_group_opts(Host, Group,
GroupOpts ++ MoreGroupOpts);
set_group_opts(Host, Group,
GroupOpts ++ MoreGroupOpts);
nomatch ->
DisplayedToGroups = displayed_to_groups(Group, Host),
DisplayedGroups = get_displayed_groups(Group, LServer),
push_user_to_displayed(LUser, LServer, Group, Host, both, DisplayedToGroups),
push_displayed_to_user(LUser, LServer, Host, both, DisplayedGroups),
Mod = gen_mod:db_mod(Host, ?MODULE),
case use_cache(Mod, Host) of
true ->
ets_cache:delete(?USER_GROUPS_CACHE, {Host, US}, cache_nodes(Mod, Host)),
ets_cache:delete(?GROUP_EXPLICIT_USERS_CACHE, {Host, Group}, cache_nodes(Mod, Host));
false ->
ok
end,
Mod:add_user_to_group(Host, US, Group)
end.
get_displayed_groups(Group, LServer) ->
GroupsOpts = groups_with_opts(LServer),
GroupOpts = proplists:get_value(Group, GroupsOpts, []),
proplists:get_value(displayed_groups, GroupOpts, []).
get_group_opt(LServer, Group, displayed_groups, []).
push_displayed_to_user(LUser, LServer, Host, Subscription, DisplayedGroups) ->
[push_members_to_user(LUser, LServer, DGroup, Host,
@@ -586,7 +714,7 @@ remove_user_from_group(Host, US, Group) ->
{LUser, LServer} = US,
case ejabberd_regexp:run(LUser, <<"^@.+@\$">>) of
match ->
GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
GroupOpts = get_group_opts(Host, Group),
NewGroupOpts = case LUser of
<<"@all@">> ->
lists:filter(fun (X) -> X /= {all_users, true}
@@ -597,9 +725,16 @@ remove_user_from_group(Host, US, Group) ->
end,
GroupOpts)
end,
mod_shared_roster:set_group_opts(Host, Group, NewGroupOpts);
set_group_opts(Host, Group, NewGroupOpts);
nomatch ->
Mod = gen_mod:db_mod(Host, ?MODULE),
case use_cache(Mod, Host) of
true ->
ets_cache:delete(?USER_GROUPS_CACHE, {Host, US}, cache_nodes(Mod, Host)),
ets_cache:delete(?GROUP_EXPLICIT_USERS_CACHE, {Host, Group}, cache_nodes(Mod, Host));
false ->
ok
end,
Result = Mod:remove_user_from_group(Host, US, Group),
DisplayedToGroups = displayed_to_groups(Group, Host),
DisplayedGroups = get_displayed_groups(Group, LServer),
@@ -610,8 +745,7 @@ remove_user_from_group(Host, US, Group) ->
push_members_to_user(LUser, LServer, Group, Host,
Subscription) ->
GroupsOpts = groups_with_opts(LServer),
GroupOpts = proplists:get_value(Group, GroupsOpts, []),
GroupOpts = get_group_opts(LServer, Group),
GroupName = proplists:get_value(name, GroupOpts, Group),
Members = get_group_users(Host, Group),
lists:foreach(fun ({U, S}) ->
@@ -659,9 +793,7 @@ push_user_to_members(User, Server, Subscription) ->
lists:usort(SpecialGroups ++ UserGroups)).
push_user_to_displayed(LUser, LServer, Group, Host, Subscription, DisplayedToGroupsOpts) ->
GroupsOpts = groups_with_opts(Host),
GroupOpts = proplists:get_value(Group, GroupsOpts, []),
GroupName = proplists:get_value(name, GroupOpts, Group),
GroupName = get_group_opt(Host, Group, name, Group),
[push_user_to_group(LUser, LServer, GroupD, Host,
GroupName, Subscription)
|| GroupD <- DisplayedToGroupsOpts].
@@ -722,13 +854,15 @@ unset_presence(LUser, LServer, Resource, Status) ->
case length(Resources) of
0 ->
OnlineGroups = get_special_users_groups_online(LServer),
lists:foreach(fun (OG) ->
push_user_to_displayed(LUser, LServer, OG,
LServer, remove, displayed_to_groups(OG, LServer)),
push_displayed_to_user(LUser, LServer,
LServer, remove, displayed_to_groups(OG, LServer))
end,
OnlineGroups);
lists:foreach(
fun(OG) ->
DisplayedToGroups = displayed_to_groups(OG, LServer),
push_user_to_displayed(LUser, LServer, OG,
LServer, remove, DisplayedToGroups),
push_displayed_to_user(LUser, LServer,
LServer, remove, DisplayedToGroups)
end,
OnlineGroups);
_ -> ok
end.
@@ -756,7 +890,7 @@ webadmin_page(Acc, _, _) -> Acc.
list_shared_roster_groups(Host, Query, Lang) ->
Res = list_sr_groups_parse_query(Host, Query),
SRGroups = mod_shared_roster:list_groups(Host),
SRGroups = list_groups(Host),
FGroups = (?XAE(<<"table">>, [],
[?XE(<<"tbody">>,
(lists:map(fun (Group) ->
@@ -807,15 +941,17 @@ list_sr_groups_parse_query(Host, Query) ->
list_sr_groups_parse_addnew(Host, Query) ->
case lists:keysearch(<<"namenew">>, 1, Query) of
{value, {_, Group}} when Group /= <<"">> ->
mod_shared_roster:create_group(Host, Group), ok;
_ -> error
create_group(Host, Group),
ok;
_ ->
error
end.
list_sr_groups_parse_delete(Host, Query) ->
SRGroups = mod_shared_roster:list_groups(Host),
SRGroups = list_groups(Host),
lists:foreach(fun (Group) ->
case lists:member({<<"selected">>, Group}, Query) of
true -> mod_shared_roster:delete_group(Host, Group);
true -> delete_group(Host, Group);
_ -> ok
end
end,
@@ -825,15 +961,15 @@ list_sr_groups_parse_delete(Host, Query) ->
shared_roster_group(Host, Group, Query, Lang) ->
Res = shared_roster_group_parse_query(Host, Group,
Query),
GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
GroupOpts = get_group_opts(Host, Group),
Name = get_opt(GroupOpts, name, <<"">>),
Description = get_opt(GroupOpts, description, <<"">>),
AllUsers = get_opt(GroupOpts, all_users, false),
OnlineUsers = get_opt(GroupOpts, online_users, false),
DisplayedGroups = get_opt(GroupOpts, displayed_groups,
[]),
Members = mod_shared_roster:get_group_explicit_users(Host,
Group),
Members = get_group_explicit_users(Host,
Group),
FMembers = iolist_to_binary(
[if AllUsers -> <<"@all@\n">>;
true -> <<"">>
@@ -915,7 +1051,7 @@ shared_roster_group_parse_query(Host, Group, Query) ->
DispGroupsOpt = if DispGroups == [] -> [];
true -> [{displayed_groups, DispGroups}]
end,
OldMembers = mod_shared_roster:get_group_explicit_users(Host,
OldMembers = get_group_explicit_users(Host,
Group),
SJIDs = str:tokens(SMembers, <<", \r\n">>),
NewMembers = lists:foldl(fun (_SJID, error) -> error;
@@ -950,26 +1086,28 @@ shared_roster_group_parse_query(Host, Group, Query) ->
RemovedDisplayedGroups = CurrentDisplayedGroups -- DispGroups,
displayed_groups_update(OldMembers, RemovedDisplayedGroups, remove),
displayed_groups_update(OldMembers, AddedDisplayedGroups, both),
mod_shared_roster:set_group_opts(Host, Group,
NameOpt ++
DispGroupsOpt ++
DescriptionOpt ++
AllUsersOpt ++ OnlineUsersOpt),
set_group_opts(Host, Group,
NameOpt ++
DispGroupsOpt ++
DescriptionOpt ++
AllUsersOpt ++ OnlineUsersOpt),
if NewMembers == error -> error;
true ->
AddedMembers = NewMembers -- OldMembers,
RemovedMembers = OldMembers -- NewMembers,
lists:foreach(fun (US) ->
mod_shared_roster:remove_user_from_group(Host,
US,
Group)
end,
RemovedMembers),
NonAddedMembers = lists:filter(fun (US) ->
error == mod_shared_roster:add_user_to_group(Host, US,
Group)
end,
AddedMembers),
lists:foreach(
fun(US) ->
remove_user_from_group(Host,
US,
Group)
end,
RemovedMembers),
NonAddedMembers = lists:filter(
fun(US) ->
error == add_user_to_group(Host, US,
Group)
end,
AddedMembers),
case NonAddedMembers of
[] -> ok;
_ -> {error_jids, NonAddedMembers}
@@ -1027,10 +1165,22 @@ import(LServer, {sql, _}, DBType, Tab, L) ->
Mod:import(LServer, Tab, L).
mod_opt_type(db_type) ->
econf:db_type(?MODULE).
econf:db_type(?MODULE);
mod_opt_type(use_cache) ->
econf:bool();
mod_opt_type(cache_size) ->
econf:pos_int(infinity);
mod_opt_type(cache_missed) ->
econf:bool();
mod_opt_type(cache_life_time) ->
econf:timeout(second, infinity).
mod_options(Host) ->
[{db_type, ejabberd_config:default_db(Host, ?MODULE)}].
[{db_type, ejabberd_config:default_db(Host, ?MODULE)},
{use_cache, ejabberd_option:use_cache(Host)},
{cache_size, ejabberd_option:cache_size(Host)},
{cache_missed, ejabberd_option:cache_missed(Host)},
{cache_life_time, ejabberd_option:cache_life_time(Host)}].
mod_doc() ->
#{desc =>
@@ -1072,7 +1222,23 @@ mod_doc() ->
"the tables and store user information. The default is "
"the storage defined by the global option 'default_db', "
"or 'mnesia' if omitted. If 'sql' value is defined, "
"make sure you have defined the database.")}}],
"make sure you have defined the database.")}},
{use_cache,
#{value => "true | false",
desc =>
?T("Same as top-level 'use_cache' option, but applied to this module only.")}},
{cache_size,
#{value => "pos_integer() | infinity",
desc =>
?T("Same as top-level 'cache_size' option, but applied to this module only.")}},
{cache_missed,
#{value => "true | false",
desc =>
?T("Same as top-level 'cache_missed' option, but applied to this module only.")}},
{cache_life_time,
#{value => "timeout()",
desc =>
?T("Same as top-level 'cache_life_time' option, but applied to this module only.")}}],
example =>
[{?T("Take the case of a computer club that wants all its members "
"seeing each other in their rosters. To achieve this, they "
+5 -1
View File
@@ -32,7 +32,7 @@
get_user_groups/2, get_group_explicit_users/2,
get_user_displayed_groups/3, is_user_in_group/3,
add_user_to_group/3, remove_user_from_group/3, import/3]).
-export([need_transform/1, transform/1]).
-export([need_transform/1, transform/1, use_cache/1]).
-include("mod_roster.hrl").
-include("mod_shared_roster.hrl").
@@ -56,6 +56,10 @@ list_groups(Host) ->
[{#sr_group{group_host = {'$1', '$2'}, _ = '_'},
[{'==', '$2', Host}], ['$1']}]).
-spec use_cache(binary()) -> boolean().
use_cache(_Host) ->
false.
groups_with_opts(Host) ->
Gs = mnesia:dirty_select(sr_group,
[{#sr_group{group_host = {'$1', Host}, opts = '$2',
+28
View File
@@ -3,7 +3,29 @@
-module(mod_shared_roster_opt).
-export([cache_life_time/1]).
-export([cache_missed/1]).
-export([cache_size/1]).
-export([db_type/1]).
-export([use_cache/1]).
-spec cache_life_time(gen_mod:opts() | global | binary()) -> 'infinity' | pos_integer().
cache_life_time(Opts) when is_map(Opts) ->
gen_mod:get_opt(cache_life_time, Opts);
cache_life_time(Host) ->
gen_mod:get_module_opt(Host, mod_shared_roster, cache_life_time).
-spec cache_missed(gen_mod:opts() | global | binary()) -> boolean().
cache_missed(Opts) when is_map(Opts) ->
gen_mod:get_opt(cache_missed, Opts);
cache_missed(Host) ->
gen_mod:get_module_opt(Host, mod_shared_roster, cache_missed).
-spec cache_size(gen_mod:opts() | global | binary()) -> 'infinity' | pos_integer().
cache_size(Opts) when is_map(Opts) ->
gen_mod:get_opt(cache_size, Opts);
cache_size(Host) ->
gen_mod:get_module_opt(Host, mod_shared_roster, cache_size).
-spec db_type(gen_mod:opts() | global | binary()) -> atom().
db_type(Opts) when is_map(Opts) ->
@@ -11,3 +33,9 @@ db_type(Opts) when is_map(Opts) ->
db_type(Host) ->
gen_mod:get_module_opt(Host, mod_shared_roster, db_type).
-spec use_cache(gen_mod:opts() | global | binary()) -> boolean().
use_cache(Opts) when is_map(Opts) ->
gen_mod:get_opt(use_cache, Opts);
use_cache(Host) ->
gen_mod:get_module_opt(Host, mod_shared_roster, use_cache).
+4 -5
View File
@@ -896,14 +896,13 @@ select_affiliation_subscriptions(Nidx, JID, JID) ->
select_affiliation_subscriptions(Nidx, GenKey, SubKey) ->
GJ = encode_jid(GenKey),
SJ = encode_jid(SubKey),
case catch
ejabberd_sql:sql_query_t(
?SQL("select jid = %(GJ)s as @(G)d, @(affiliation)s, @(subscriptions)s from "
" pubsub_state where nodeid=%(Nidx)d and jid in (%(GJ)s, %(SJ)s)"))
case catch ejabberd_sql:sql_query_t(
?SQL("select jid = %(GJ)s as @(G)b, @(affiliation)s, @(subscriptions)s from "
" pubsub_state where nodeid=%(Nidx)d and jid in (%(GJ)s, %(SJ)s)"))
of
{selected, Res} ->
lists:foldr(
fun({1, A, S}, {_, Subs}) ->
fun({true, A, S}, {_, Subs}) ->
{decode_affiliation(A), Subs ++ decode_subscriptions(S)};
({_, _, S}, {Aff, Subs}) ->
{Aff, Subs ++ decode_subscriptions(S)}
+4
View File
@@ -259,6 +259,8 @@ init_per_testcase(TestCase, OrigConfig) ->
case Test of
"test_connect" ++ _ ->
Config;
"webadmin_" ++ _ ->
Config;
"test_legacy_auth_feature" ->
connect(Config);
"test_legacy_auth" ++ _ ->
@@ -372,6 +374,7 @@ db_tests(DB) when DB == mnesia; DB == redis ->
auth_md5,
presence_broadcast,
last,
webadmin_tests:single_cases(),
roster_tests:single_cases(),
private_tests:single_cases(),
privacy_tests:single_cases(),
@@ -401,6 +404,7 @@ db_tests(DB) ->
auth_md5,
presence_broadcast,
last,
webadmin_tests:single_cases(),
roster_tests:single_cases(),
private_tests:single_cases(),
privacy_tests:single_cases(),
+3
View File
@@ -66,6 +66,8 @@ access_rules:
acl:
local:
user_regexp: ""
admin:
user: "admin"
language: en
listen:
-
@@ -84,6 +86,7 @@ listen:
port: WEB_PORT
module: ejabberd_http
request_handlers:
"/admin": ejabberd_web_admin
"/api": mod_http_api
"/upload": mod_http_upload
"/captcha": ejabberd_captcha
+73
View File
@@ -0,0 +1,73 @@
%%%-------------------------------------------------------------------
%%% Author : Pawel Chmielowski <pawel@process-one.net>
%%% Created : 23 Mar 2020 by Pawel Chmielowski <pawel@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2020 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(webadmin_tests).
%% API
-compile(export_all).
-import(suite, [disconnect/1, is_feature_advertised/3, upload_jid/1,
my_jid/1, wait_for_slave/1, wait_for_master/1,
send_recv/2, put_event/2, get_event/1]).
-include("suite.hrl").
-include_lib("stdlib/include/assert.hrl").
%%%===================================================================
%%% API
%%%===================================================================
%%%===================================================================
%%% Single user tests
%%%===================================================================
single_cases() ->
{webadmin_single, [sequence],
[single_test(login_page),
single_test(welcome_page)]}.
login_page(Config) ->
Headers = ?match({ok, {{"HTTP/1.1", 401, _}, Headers, _}},
httpc:request(get, {page(Config, ""), []}, [],
[{body_format, binary}]),
Headers),
?match("basic realm=\"ejabberd\"", proplists:get_value("www-authenticate", Headers, none)).
welcome_page(Config) ->
Body = ?match({ok, {{"HTTP/1.1", 200, _}, _, Body}},
httpc:request(get, {page(Config, ""), [basic_auth_header(Config)]}, [],
[{body_format, binary}]),
Body),
?match({_, _}, binary:match(Body, <<"ejabberd Web Admin">>)).
%%%===================================================================
%%% Internal functions
%%%===================================================================
single_test(T) ->
list_to_atom("webadmin_" ++ atom_to_list(T)).
basic_auth_header(Config) ->
Server = ?config(server, Config),
ejabberd_auth:try_register(<<"admin">>, Server, <<"pass">>),
{"authorization", "Basic "++base64:encode_to_string(<<"admin@", Server/binary, ":pass">>)}.
page(Config, Tail) ->
Server = ?config(server_host, Config),
Port = ct:get_config(web_port, 5280),
"http://" ++ Server ++ ":" ++ integer_to_list(Port) ++ "/admin/" ++ Tail.