From 3522f3e83f85d75d0dbf5e7fa9647166a0f65507 Mon Sep 17 00:00:00 2001 From: "Tobias \"Knight\" S" Date: Sun, 5 Aug 2018 04:54:09 +0200 Subject: [PATCH 001/109] kitterman.com redirects to TLS by default curl -I http://www.kitterman.com/dmarc/assistant.html HTTP/1.1 302 Found Date: Sun, 05 Aug 2018 02:53:18 GMT Server: Apache/2.4.34 Location: https://www.kitterman.com/dmarc/assistant.html Content-Type: text/html; charset=iso-8859-1 --- data/web/inc/ajax/dns_diagnostics.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/inc/ajax/dns_diagnostics.php b/data/web/inc/ajax/dns_diagnostics.php index 45ff07e2b2..dd67dec943 100644 --- a/data/web/inc/ajax/dns_diagnostics.php +++ b/data/web/inc/ajax/dns_diagnostics.php @@ -74,7 +74,7 @@ // Init records array $spf_link = 'SPF Record Syntax
'; -$dmarc_link = 'DMARC Assistant'; +$dmarc_link = 'DMARC Assistant'; $records = array(); if ($_SESSION['mailcow_cc_role'] == "admin") { From 73f880ffba7ee709e9b20ce3c52c9ffe6c0fd5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 5 Aug 2018 22:31:53 +0200 Subject: [PATCH 002/109] [Web] Workaround for missing function when using API (fixes #1640) [Web] Fixes SQL error on admin username change --- data/web/inc/functions.inc.php | 42 ---------------------------- data/web/inc/init_db.inc.php | 4 +-- data/web/inc/prerequisites.inc.php | 44 ++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 3ca51b452a..d99661cb09 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -3,48 +3,6 @@ function hash_password($password) { $salt_str = bin2hex(openssl_random_pseudo_bytes(8)); return "{SSHA256}".base64_encode(hash('sha256', $password . $salt_str, true) . $salt_str); } -function get_remote_ip($anonymize = null) { - global $ANONYMIZE_IPS; - if ($anonymize === null) { - $anonymize = $ANONYMIZE_IPS; - } - elseif ($anonymize !== true && $anonymize !== false) { - $anonymize = true; - } - $remote = ''; - if ($_SERVER['HTTP_CLIENT_IP']) { - $remote = $_SERVER['HTTP_CLIENT_IP']; - } - elseif ($_SERVER['HTTP_X_FORWARDED_FOR']) { - $remote = $_SERVER['HTTP_X_FORWARDED_FOR']; - } - elseif ($_SERVER['HTTP_X_FORWARDED']) { - $remote = $_SERVER['HTTP_X_FORWARDED']; - } - elseif ($_SERVER['HTTP_FORWARDED_FOR']) { - $remote = $_SERVER['HTTP_FORWARDED_FOR']; - } - elseif ($_SERVER['HTTP_FORWARDED']) { - $remote = $_SERVER['HTTP_FORWARDED']; - } - elseif ($_SERVER['REMOTE_ADDR']) { - $remote = $_SERVER['REMOTE_ADDR']; - } - if (filter_var($remote, FILTER_VALIDATE_IP) === false) { - return '0.0.0.0'; - } - if ($anonymize) { - if (strlen(inet_pton($remote)) == 4) { - return inet_ntop(inet_pton($remote) & inet_pton("255.255.255.0")); - } - elseif (strlen(inet_pton($remote)) == 16) { - return inet_ntop(inet_pton($remote) & inet_pton('ffff:ffff:ffff:ffff:0000:0000:0000:0000')); - } - } - else { - return $remote; - } -} function last_login($user) { global $pdo; try { diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index a3b67283e6..b938a56b92 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "31072018_2319"; + $db_version = "05072018_2319"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -147,7 +147,7 @@ function init_db_schema() { "col" => "username", "ref" => "admin.username", "delete" => "CASCADE", - "update" => "NO ACTION" + "update" => "CASCADE" ) ) ), diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index ad201a687b..1370155e7f 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -52,6 +52,50 @@ exit; } +// TODO: Move function +function get_remote_ip($anonymize = null) { + global $ANONYMIZE_IPS; + if ($anonymize === null) { + $anonymize = $ANONYMIZE_IPS; + } + elseif ($anonymize !== true && $anonymize !== false) { + $anonymize = true; + } + $remote = ''; + if ($_SERVER['HTTP_CLIENT_IP']) { + $remote = $_SERVER['HTTP_CLIENT_IP']; + } + elseif ($_SERVER['HTTP_X_FORWARDED_FOR']) { + $remote = $_SERVER['HTTP_X_FORWARDED_FOR']; + } + elseif ($_SERVER['HTTP_X_FORWARDED']) { + $remote = $_SERVER['HTTP_X_FORWARDED']; + } + elseif ($_SERVER['HTTP_FORWARDED_FOR']) { + $remote = $_SERVER['HTTP_FORWARDED_FOR']; + } + elseif ($_SERVER['HTTP_FORWARDED']) { + $remote = $_SERVER['HTTP_FORWARDED']; + } + elseif ($_SERVER['REMOTE_ADDR']) { + $remote = $_SERVER['REMOTE_ADDR']; + } + if (filter_var($remote, FILTER_VALIDATE_IP) === false) { + return '0.0.0.0'; + } + if ($anonymize) { + if (strlen(inet_pton($remote)) == 4) { + return inet_ntop(inet_pton($remote) & inet_pton("255.255.255.0")); + } + elseif (strlen(inet_pton($remote)) == 16) { + return inet_ntop(inet_pton($remote) & inet_pton('ffff:ffff:ffff:ffff:0000:0000:0000:0000')); + } + } + else { + return $remote; + } +} + require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php'; // Set language From ff0b9246b5ca0fa8f3e37243596f8d311e8cc8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 5 Aug 2018 22:35:02 +0200 Subject: [PATCH 003/109] [ClamAV] Add whitelist file for ClamAV, fixes #1607 [ACME] Test for CAA before running script, fixes #1632 --- data/Dockerfiles/acme/docker-entrypoint.sh | 26 +++++++++++++++++++++- data/Dockerfiles/clamd/bootstrap.sh | 4 ++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/data/Dockerfiles/acme/docker-entrypoint.sh b/data/Dockerfiles/acme/docker-entrypoint.sh index 7f4f1fcbe3..08d234bf50 100755 --- a/data/Dockerfiles/acme/docker-entrypoint.sh +++ b/data/Dockerfiles/acme/docker-entrypoint.sh @@ -67,7 +67,7 @@ get_ipv4(){ local IPV4_SRCS= local TRY= IPV4_SRCS[0]="api.ipify.org" - IPV4_SRCS[1]="ifconfig.co"- + IPV4_SRCS[1]="ifconfig.co" IPV4_SRCS[2]="icanhazip.com" IPV4_SRCS[3]="v4.ident.me" IPV4_SRCS[4]="ipecho.net/plain" @@ -153,6 +153,19 @@ while true; do IPV6=$(get_ipv6) log_f "OK" no_date + # Hard-fail on CAA errors for MAILCOW_HOSTNAME + MH_PARENT_DOMAIN=$(echo ${MAILCOW_HOSTNAME} | cut -d. -f2-) + MH_CAAS=( $(dig CAA ${MH_PARENT_DOMAIN} +short | sed -n 's/\d issue "\(.*\)"/\1/p') ) + if [[ ! -z ${MH_CAAS} ]]; then + if [[ ${MH_CAAS[@]} =~ "letsencrypt.org" ]]; then + echo "Validated CAA for parent domain ${MH_PARENT_DOMAIN}" + else + echo "Skipping ACME validation: Lets Encrypt disallowed for ${MAILCOW_HOSTNAME} by CAA record, retrying in 1h..." + sleep 1h + exec $(readlink -f "$0") + fi + fi + # Container ids may have changed CONTAINERS_RESTART=($(curl --silent http://dockerapi:8080/containers/json | jq -r '.[] | {name: .Config.Labels["com.docker.compose.service"], id: .Id}' | jq -rc 'select( .name | tostring | contains("nginx-mailcow") or contains("postfix-mailcow") or contains("dovecot-mailcow")) | .id' | tr "\n" " ")) @@ -249,6 +262,17 @@ while true; do fi for SAN in "${ADDITIONAL_SAN_ARR[@]}"; do + # Skip on CAA errors for SAN + SAN_PARENT_DOMAIN=$(echo ${SAN} | cut -d. -f2-) + SAN_CAAS=( $(dig CAA ${SAN_PARENT_DOMAIN} +short | sed -n 's/\d issue "\(.*\)"/\1/p') ) + if [[ ! -z ${SAN_CAAS} ]]; then + if [[ ${SAN_CAAS[@]} =~ "letsencrypt.org" ]]; then + echo "Validated CAA for parent domain ${SAN_PARENT_DOMAIN} of ${SAN}" + else + echo "Skipping ACME validation for ${SAN}: Lets Encrypt disallowed for ${SAN} by CAA record" + continue + fi + fi if [[ ${SAN} == ${MAILCOW_HOSTNAME} ]]; then continue fi diff --git a/data/Dockerfiles/clamd/bootstrap.sh b/data/Dockerfiles/clamd/bootstrap.sh index 76a6b79bd4..ba1cee85a1 100755 --- a/data/Dockerfiles/clamd/bootstrap.sh +++ b/data/Dockerfiles/clamd/bootstrap.sh @@ -14,6 +14,10 @@ chown root:tty /dev/console chmod g+rw /dev/console # Prepare +[[ ! -f /var/lib/clamav/whitelist.ign2 ]] && touch /var/lib/clamav/whitelist.ign2 +dos2unix /var/lib/clamav/whitelist.ign2 +sed -i '/^\s*$/d' /var/lib/clamav/whitelist.ign2 + BACKGROUND_TASKS=() ( From 66d1bc12c09c519c48e5e369e8d73b301f2fde76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 5 Aug 2018 22:37:07 +0200 Subject: [PATCH 004/109] [Nginx] Set client_max_body_size = 0 --- data/conf/nginx/site.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/conf/nginx/site.conf b/data/conf/nginx/site.conf index babf5ce3f3..d25d3b6155 100644 --- a/data/conf/nginx/site.conf +++ b/data/conf/nginx/site.conf @@ -39,6 +39,8 @@ server { index index.php index.html; + client_max_body_size 0; + include /etc/nginx/conf.d/listen_plain.active; include /etc/nginx/conf.d/listen_ssl.active; include /etc/nginx/conf.d/server_name.active; From 0273f95950442425807bb9b8590982c9c10ed078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 5 Aug 2018 22:37:49 +0200 Subject: [PATCH 005/109] [Compose] New images for ClamAV (+mount whitelist file) and ACME --- docker-compose.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index c1ab99d7ad..b7fd62eb29 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -53,7 +53,7 @@ services: - redis clamd-mailcow: - image: mailcow/clamd:1.12 + image: mailcow/clamd:1.13 build: ./data/Dockerfiles/clamd restart: always tty: true @@ -62,6 +62,7 @@ services: - SKIP_CLAMD=${SKIP_CLAMD:-n} volumes: - ./data/conf/clamav/:/etc/clamav/ + - ./data/conf/clamav/whitelist.ign2:/var/lib/clamav/whitelist.ign2 dns: - ${IPV4_NETWORK:-172.22.1}.254 networks: @@ -278,7 +279,7 @@ services: depends_on: - nginx-mailcow - mysql-mailcow - image: mailcow/acme:1.35 + image: mailcow/acme:1.36 build: ./data/Dockerfiles/acme dns: - ${IPV4_NETWORK:-172.22.1}.254 From d83537cda0f34ab8f0239b6e2632c6b93b768b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 5 Aug 2018 22:38:06 +0200 Subject: [PATCH 006/109] [ClamAV] Add whitelist template for ClamAV --- data/conf/clamav/whitelist.ign2 | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/conf/clamav/whitelist.ign2 diff --git a/data/conf/clamav/whitelist.ign2 b/data/conf/clamav/whitelist.ign2 new file mode 100644 index 0000000000..70ef98b9f3 --- /dev/null +++ b/data/conf/clamav/whitelist.ign2 @@ -0,0 +1 @@ +Example-Signature.Ignore-1 From 6bd818ceeccf358be1a9beb9e589b2989149cbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Mon, 6 Aug 2018 15:15:24 +0200 Subject: [PATCH 007/109] [ACME] Remove third-party IP tools --- data/Dockerfiles/acme/docker-entrypoint.sh | 14 ++++---------- docker-compose.yml | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/data/Dockerfiles/acme/docker-entrypoint.sh b/data/Dockerfiles/acme/docker-entrypoint.sh index 08d234bf50..c9a91dfa79 100755 --- a/data/Dockerfiles/acme/docker-entrypoint.sh +++ b/data/Dockerfiles/acme/docker-entrypoint.sh @@ -66,12 +66,8 @@ get_ipv4(){ local IPV4= local IPV4_SRCS= local TRY= - IPV4_SRCS[0]="api.ipify.org" - IPV4_SRCS[1]="ifconfig.co" - IPV4_SRCS[2]="icanhazip.com" - IPV4_SRCS[3]="v4.ident.me" - IPV4_SRCS[4]="ipecho.net/plain" - IPV4_SRCS[5]="ip4.mailcow.email" + IPV4_SRCS[0]="ip4.mailcow.email" + IPV4_SRCS[1]="ip4.korves.net" until [[ ! -z ${IPV4} ]] || [[ ${TRY} -ge 10 ]]; do IPV4=$(curl --connect-timeout 3 -m 10 -L4s ${IPV4_SRCS[$RANDOM % ${#IPV4_SRCS[@]} ]} | grep -E "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$") [[ ! -z ${TRY} ]] && sleep 1 @@ -84,10 +80,8 @@ get_ipv6(){ local IPV6= local IPV6_SRCS= local TRY= - IPV6_SRCS[0]="ifconfig.co" - IPV6_SRCS[1]="icanhazip.com" - IPV6_SRCS[2]="v6.ident.me" - IPV6_SRCS[3]="ip6.mailcow.email" + IPV6_SRCS[0]="ip6.korves.net" + IPV6_SRCS[1]="ip6.mailcow.email" until [[ ! -z ${IPV6} ]] || [[ ${TRY} -ge 10 ]]; do IPV6=$(curl --connect-timeout 3 -m 10 -L6s ${IPV6_SRCS[$RANDOM % ${#IPV6_SRCS[@]} ]} | grep "^\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}$") [[ ! -z ${TRY} ]] && sleep 1 diff --git a/docker-compose.yml b/docker-compose.yml index b7fd62eb29..e01bf2d3b3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -279,7 +279,7 @@ services: depends_on: - nginx-mailcow - mysql-mailcow - image: mailcow/acme:1.36 + image: mailcow/acme:1.37 build: ./data/Dockerfiles/acme dns: - ${IPV4_NETWORK:-172.22.1}.254 From 02e567f76bedca07712d3e6e109bf5f978e7bfdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Wed, 8 Aug 2018 23:59:38 +0200 Subject: [PATCH 008/109] [Dovecot] Set CONTROL path for shared namespace and remove index --- data/conf/dovecot/dovecot.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index 820a825b4b..9b38aa3574 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -175,7 +175,7 @@ namespace { type = shared separator = / prefix = Shared/%%u/ - location = maildir:%%h/:INDEX=~/Shared/%%u:INDEXPVT=~/Shared/%%u + location = maildir:%%h/:CONTROL=~/Shared/%%u:INDEXPVT=~/Shared/%%u subscriptions = no list = children } From d5e81b987b7150046559db9ac4a6f1d7bdec6912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Mon, 13 Aug 2018 08:31:09 +0200 Subject: [PATCH 009/109] [Dovecot] Set from address for sieve generated addresses, fixes #1662 --- data/conf/dovecot/dovecot.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index 9b38aa3574..187c61b49c 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -262,6 +262,7 @@ plugin { quota_rule2 = Trash:storage=+100%% sieve = /var/vmail/sieve/%u.sieve sieve_plugins = sieve_imapsieve sieve_extprograms + sieve_vacation_send_from_recipient = yes # From elsewhere to Spam folder imapsieve_mailbox1_name = Junk imapsieve_mailbox1_causes = COPY From a11cce67654e7cd8a268b58592a25801e710861d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Mon, 13 Aug 2018 23:20:40 +0200 Subject: [PATCH 010/109] [Web] Fixes for BCC map input fields [Web] Allow to edit alias address [Web] $_SESSION['return'] now contains arrays and allows multiple returned messages and log entries [Web] Some language string changes [Web] General SQL exception handler, remove all try catch handlers [Web] Alias table now has an ID as primary key [Web] Be more aggressive with localStorage cleaning --- data/web/admin.php | 2 +- data/web/autodiscover.php | 4 +- data/web/edit.php | 20 +- data/web/inc/footer.inc.php | 6 +- .../inc/functions.address_rewriting.inc.php | 259 +- .../inc/functions.autoconfiguration.inc.php | 119 - data/web/inc/functions.customize.inc.php | 38 +- data/web/inc/functions.dkim.inc.php | 56 +- data/web/inc/functions.docker.inc.php | 8 +- data/web/inc/functions.domain_admin.inc.php | 291 +- data/web/inc/functions.fail2ban.inc.php | 56 +- data/web/inc/functions.fwdhost.inc.php | 46 +- data/web/inc/functions.inc.php | 493 +-- data/web/inc/functions.mailbox.inc.php | 3871 +++++++---------- data/web/inc/functions.policy.inc.php | 258 +- data/web/inc/functions.quarantine.inc.php | 314 +- data/web/inc/functions.relayhost.inc.php | 101 +- data/web/inc/functions.rsettings.inc.php | 84 +- data/web/inc/init_db.inc.php | 15 +- data/web/inc/prerequisites.inc.php | 19 + data/web/inc/sessions.inc.php | 4 +- data/web/js/api.js | 21 +- data/web/js/debug.js | 2 + data/web/js/mailbox.js | 7 +- data/web/json_api.php | 6 +- data/web/lang/lang.de.php | 51 +- data/web/lang/lang.en.php | 54 +- data/web/modals/admin.php | 4 +- data/web/modals/mailbox.php | 4 +- data/web/quarantine.php | 2 + 30 files changed, 2703 insertions(+), 3512 deletions(-) delete mode 100644 data/web/inc/functions.autoconfiguration.inc.php diff --git a/data/web/admin.php b/data/web/admin.php index ce3deb69ad..d97bc141d2 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -261,7 +261,7 @@ else { ?>
-
+

↳ Alias-Domain:

diff --git a/data/web/autodiscover.php b/data/web/autodiscover.php index 391b4a9303..f5bcbf8fec 100644 --- a/data/web/autodiscover.php +++ b/data/web/autodiscover.php @@ -74,7 +74,7 @@ $redis->lTrim('AUTODISCOVER_LOG', 0, 100); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'msg' => 'Redis: '.$e ); @@ -128,7 +128,7 @@ $redis->lTrim('AUTODISCOVER_LOG', 0, 100); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'msg' => 'Redis: '.$e ); diff --git a/data/web/edit.php b/data/web/edit.php index d605d3f458..1efbbed3b2 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -28,6 +28,12 @@
+
+ +
+ +
+
@@ -636,23 +642,23 @@ $result = bcc('details', $bcc); if (!empty($result)) { ?> -

BCC map

+


- +
- - BCC destination must be a single valid email address. + +
- +
diff --git a/data/web/inc/footer.inc.php b/data/web/inc/footer.inc.php index d7b8072329..cdef8e0b9d 100644 --- a/data/web/inc/footer.inc.php +++ b/data/web/inc/footer.inc.php @@ -29,7 +29,7 @@ function setLang(sel) { }); $(document).ready(function() { window.mailcow_alert_box = function(message, type) { - msg = $('').html(message).text(); + msg = $('').text(message).text(); if (type == 'danger') { auto_hide = 0; $('#' + localStorage.getItem("add_modal")).modal('show'); @@ -42,9 +42,11 @@ function setLang(sel) { - mailcow_alert_box(, ); + mailcow_alert_box(, ); diff --git a/data/web/inc/functions.address_rewriting.inc.php b/data/web/inc/functions.address_rewriting.inc.php index ce10d67671..36fc4946e7 100644 --- a/data/web/inc/functions.address_rewriting.inc.php +++ b/data/web/inc/functions.address_rewriting.inc.php @@ -8,7 +8,7 @@ function bcc($_action, $_data = null, $attr = null) { switch ($_action) { case 'add': if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'access_denied' @@ -20,7 +20,7 @@ function bcc($_action, $_data = null, $attr = null) { $active = intval($_data['active']); $type = $_data['type']; if ($type != 'sender' && $type != 'rcpt') { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'invalid_bcc_map_type' @@ -28,7 +28,7 @@ function bcc($_action, $_data = null, $attr = null) { return false; } if (empty($bcc_dest)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'bcc_empty' @@ -37,7 +37,7 @@ function bcc($_action, $_data = null, $attr = null) { } if (is_valid_domain_name($local_dest)) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'access_denied' @@ -49,7 +49,7 @@ function bcc($_action, $_data = null, $attr = null) { } elseif (filter_var($local_dest, FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'access_denied' @@ -66,29 +66,21 @@ function bcc($_action, $_data = null, $attr = null) { return false; } if (!filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'bcc_must_be_email' ); return false; } - try { - $stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps` - WHERE `local_dest` = :local_dest AND `type` = :type"); - $stmt->execute(array(':local_dest' => $local_dest_sane, ':type' => $type)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + + $stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps` + WHERE `local_dest` = :local_dest AND `type` = :type"); + $stmt->execute(array(':local_dest' => $local_dest_sane, ':type' => $type)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('bcc_exists', htmlspecialchars($local_dest_sane), $type) @@ -107,14 +99,14 @@ function bcc($_action, $_data = null, $attr = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('mysql_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'bcc_saved' @@ -122,7 +114,7 @@ function bcc($_action, $_data = null, $attr = null) { break; case 'edit': if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'access_denied' @@ -139,53 +131,45 @@ function bcc($_action, $_data = null, $attr = null) { $type = (!empty($_data['type'])) ? $_data['type'] : $is_now['type']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } $active = intval($_data['active']); if (!filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => 'bcc_must_be_email' + 'msg' => array('bcc_must_be_email', $bcc_dest) ); - return false; + continue; } if (empty($bcc_dest)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => 'bcc_empty' + 'msg' => array('bcc_must_be_email', $bcc_dest) ); - return false; + continue; } try { $stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps` WHERE `local_dest` = :local_dest AND `type` = :type"); $stmt->execute(array(':local_dest' => $local_dest, ':type' => $type)); $id_now = $stmt->fetch(PDO::FETCH_ASSOC)['id']; - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } - if (isset($id_now) && $id_now != $id) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('bcc_exists', htmlspecialchars($local_dest), $type) - ); - return false; - } - try { + + if (isset($id_now) && $id_now != $id) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('bcc_exists', htmlspecialchars($local_dest), $type) + ); + continue; + } + $stmt = $pdo->prepare("UPDATE `bcc_maps` SET `bcc_dest` = :bcc_dest, `active` = :active, `type` = :type WHERE `id`= :id"); $stmt->execute(array( ':bcc_dest' => $bcc_dest, @@ -195,45 +179,37 @@ function bcc($_action, $_data = null, $attr = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('bcc_edited', $bcc_dest) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => 'bcc_edited' - ); break; case 'details': $bccdata = array(); $id = intval($_data); - try { - $stmt = $pdo->prepare("SELECT `id`, - `local_dest`, - `bcc_dest`, - `active` AS `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, - `type`, - `created`, - `domain`, - `modified` FROM `bcc_maps` - WHERE `id` = :id"); - $stmt->execute(array(':id' => $id)); - $bccdata = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + + $stmt = $pdo->prepare("SELECT `id`, + `local_dest`, + `bcc_dest`, + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, + `type`, + `created`, + `domain`, + `modified` FROM `bcc_maps` + WHERE `id` = :id"); + $stmt->execute(array(':id' => $id)); + $bccdata = $stmt->fetch(PDO::FETCH_ASSOC); + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $bccdata['domain'])) { $bccdata = null; return false; @@ -244,18 +220,10 @@ function bcc($_action, $_data = null, $attr = null) { $bccdata = array(); $all_items = array(); $id = intval($_data); - try { - $stmt = $pdo->query("SELECT `id`, `domain` FROM `bcc_maps`"); - $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + + $stmt = $pdo->query("SELECT `id`, `domain` FROM `bcc_maps`"); + $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($all_items as $i) { if (hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $i['domain'])) { $bccdata[] = $i['id']; @@ -275,31 +243,30 @@ function bcc($_action, $_data = null, $attr = null) { $stmt->execute(array(':id' => $id)); $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain']; if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `id`= :id"); $stmt->execute(array(':id' => $id)); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('bcc_deleted', $id) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('bcc_deleted', implode(', ', $ids)) - ); - return true; break; } } @@ -325,7 +292,7 @@ function recipient_map($_action, $_data = null, $attr = null) { $old_dest_sane = $old_dest; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('invalid_recipient_map_old', htmlspecialchars($old_dest)) @@ -333,7 +300,7 @@ function recipient_map($_action, $_data = null, $attr = null) { return false; } if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('invalid_recipient_map_new', htmlspecialchars($new_dest)) @@ -345,7 +312,7 @@ function recipient_map($_action, $_data = null, $attr = null) { $old_dests_existing[] = recipient_map('details', $rmap)['recipient_map_old']; } if (in_array($old_dest_sane, $old_dests_existing)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest)) @@ -362,14 +329,14 @@ function recipient_map($_action, $_data = null, $attr = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('mysql_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('recipient_map_entry_saved', htmlspecialchars($old_dest_sane)) @@ -388,12 +355,12 @@ function recipient_map($_action, $_data = null, $attr = null) { } } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (is_valid_domain_name($old_dest)) { $old_dest_sane = '@' . idn_to_ascii($old_dest); @@ -402,21 +369,21 @@ function recipient_map($_action, $_data = null, $attr = null) { $old_dest_sane = $old_dest; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('invalid_recipient_map_old', htmlspecialchars($old_dest)) ); - return false; + continue; } $active = intval($_data['active']); if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('invalid_recipient_map_new', htmlspecialchars($new_dest)) ); - return false; + continue; } $rmaps = recipient_map('get'); foreach ($rmaps as $rmap) { @@ -424,12 +391,12 @@ function recipient_map($_action, $_data = null, $attr = null) { } if (in_array($old_dest_sane, $old_dests_existing) && recipient_map('details', $id)['recipient_map_old'] != $old_dest_sane) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane)) ); - return false; + continue; } try { $stmt = $pdo->prepare("UPDATE `recipient_maps` SET @@ -445,61 +412,45 @@ function recipient_map($_action, $_data = null, $attr = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('mysql_error', $e) ); return false; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('recipient_map_entry_saved', htmlspecialchars($old_dest_sane)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('recipient_map_entry_saved', htmlspecialchars($old_dest)) - ); break; case 'details': $mapdata = array(); $id = intval($_data); - try { - $stmt = $pdo->prepare("SELECT `id`, - `old_dest` AS `recipient_map_old`, - `new_dest` AS `recipient_map_new`, - `active` AS `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, - `created`, - `modified` FROM `recipient_maps` - WHERE `id` = :id"); - $stmt->execute(array(':id' => $id)); - $mapdata = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + + $stmt = $pdo->prepare("SELECT `id`, + `old_dest` AS `recipient_map_old`, + `new_dest` AS `recipient_map_new`, + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, + `created`, + `modified` FROM `recipient_maps` + WHERE `id` = :id"); + $stmt->execute(array(':id' => $id)); + $mapdata = $stmt->fetch(PDO::FETCH_ASSOC); + return $mapdata; break; case 'get': $mapdata = array(); $all_items = array(); $id = intval($_data); - try { - $stmt = $pdo->query("SELECT `id` FROM `recipient_maps`"); - $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + + $stmt = $pdo->query("SELECT `id` FROM `recipient_maps`"); + $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($all_items as $i) { $mapdata[] = $i['id']; } @@ -517,7 +468,7 @@ function recipient_map($_action, $_data = null, $attr = null) { $stmt->execute(array(':id' => $id)); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('mysql_error', $e) @@ -525,7 +476,7 @@ function recipient_map($_action, $_data = null, $attr = null) { return false; } } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'msg' => array('recipient_map_entry_deleted', htmlspecialchars($old_dest)) ); diff --git a/data/web/inc/functions.autoconfiguration.inc.php b/data/web/inc/functions.autoconfiguration.inc.php deleted file mode 100644 index bd3dd10bbb..0000000000 --- a/data/web/inc/functions.autoconfiguration.inc.php +++ /dev/null @@ -1,119 +0,0 @@ - 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data), - 'msg' => 'access_denied' - ); - return false; - } - switch ($_type) { - case 'autodiscover': - $objects = (array)$_data['object']; - foreach ($objects as $object) { - if (is_valid_domain_name($object) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $exclude_regex = (isset($_data['exclude_regex'])) ? $_data['exclude_regex'] : null; - $exclude_regex = (isset($_data['exclude_regex'])) ? $_data['exclude_regex'] : null; - try { - $stmt = $pdo->prepare("SELECT COUNT(`domain`) AS `domain_c` FROM `autodiscover` - WHERE `domain` = :domain"); - $stmt->execute(array(':domain' => $object)); - $num_results = $stmt->fetchColumn(); - if ($num_results > 0) { - $stmt = $pdo->prepare("SELECT COUNT(`domain`) AS `domain_c` FROM `autodiscover` - WHERE `domain` = :domain"); - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data), - 'msg' => array('mysql_error', $e) - ); - return false; - } - } - elseif (filter_var($object, FILTER_VALIDATE_EMAIL) === true && hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - - } - } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data), - 'msg' => array('domain_modified', htmlspecialchars(implode(', ', $objects))) - ); - break; - } - break; - case 'get': - switch ($_type) { - case 'autodiscover': - $autodiscover = array(); - if (is_valid_domain_name($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - try { - $stmt = $pdo->prepare("SELECT * FROM `autodiscover` - WHERE `domain` = :domain"); - $stmt->execute(array(':domain' => $_data)); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $autodiscover['mailbox'] = $row['mailbox']; - $autodiscover['domain'] = $row['domain']; - $autodiscover['service'] = $row['service']; - $autodiscover['exclude_regex'] = $row['exclude_regex']; - $autodiscover['created'] = $row['created']; - $autodiscover['modified'] = $row['modified']; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data), - 'msg' => array('mysql_error', $e) - ); - return false; - } - } - elseif (filter_var($_data, FILTER_VALIDATE_EMAIL) === true && hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - try { - $stmt = $pdo->prepare("SELECT * FROM `autodiscover` - WHERE `mailbox` = :mailbox"); - $stmt->execute(array(':mailbox' => $_data)); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $autodiscover['mailbox'] = $row['mailbox']; - $autodiscover['domain'] = $row['domain']; - $autodiscover['service'] = $row['service']; - $autodiscover['exclude_regex'] = $row['exclude_regex']; - $autodiscover['created'] = $row['created']; - $autodiscover['modified'] = $row['modified']; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data), - 'msg' => array('mysql_error', $e) - ); - return false; - } - } - return $autodiscover; - break; - } - break; - case 'reset': - switch ($_type) { - case 'autodiscover': - if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") { - return false; - } - break; - } - break; - } -} diff --git a/data/web/inc/functions.customize.inc.php b/data/web/inc/functions.customize.inc.php index 8fb928fa91..a737bdbc97 100644 --- a/data/web/inc/functions.customize.inc.php +++ b/data/web/inc/functions.customize.inc.php @@ -5,7 +5,7 @@ function customize($_action, $_item, $_data = null) { switch ($_action) { case 'add': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'access_denied' @@ -17,7 +17,7 @@ function customize($_action, $_item, $_data = null) { if (in_array($_data['main_logo']['type'], array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/x-png', 'image/png', 'image/svg+xml'))) { try { if (file_exists($_data['main_logo']['tmp_name']) !== true) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'img_tmp_missing' @@ -26,7 +26,7 @@ function customize($_action, $_item, $_data = null) { } $image = new Imagick($_data['main_logo']['tmp_name']); if ($image->valid() !== true) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'img_invalid' @@ -36,7 +36,7 @@ function customize($_action, $_item, $_data = null) { $image->destroy(); } catch (ImagickException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'img_invalid' @@ -45,7 +45,7 @@ function customize($_action, $_item, $_data = null) { } } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'invalid_mime_type' @@ -56,14 +56,14 @@ function customize($_action, $_item, $_data = null) { $redis->Set('MAIN_LOGO', 'data:' . $_data['main_logo']['type'] . ';base64,' . base64_encode(file_get_contents($_data['main_logo']['tmp_name']))); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => array('redis_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'upload_success' @@ -73,7 +73,7 @@ function customize($_action, $_item, $_data = null) { break; case 'edit': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'access_denied' @@ -93,7 +93,7 @@ function customize($_action, $_item, $_data = null) { $redis->set('APP_LINKS', json_encode($out)); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => array('redis_error', $e) @@ -101,7 +101,7 @@ function customize($_action, $_item, $_data = null) { return false; } } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'app_links' @@ -119,14 +119,14 @@ function customize($_action, $_item, $_data = null) { $redis->set('HELP_TEXT', $help_text); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => array('redis_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'ui_texts' @@ -136,7 +136,7 @@ function customize($_action, $_item, $_data = null) { break; case 'delete': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'access_denied' @@ -147,7 +147,7 @@ function customize($_action, $_item, $_data = null) { case 'main_logo': try { if ($redis->del('MAIN_LOGO')) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'reset_main_logo' @@ -156,7 +156,7 @@ function customize($_action, $_item, $_data = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => array('redis_error', $e) @@ -173,7 +173,7 @@ function customize($_action, $_item, $_data = null) { $app_links = json_decode($redis->get('APP_LINKS'), true); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => array('redis_error', $e) @@ -187,7 +187,7 @@ function customize($_action, $_item, $_data = null) { return $redis->get('MAIN_LOGO'); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => array('redis_error', $e) @@ -204,7 +204,7 @@ function customize($_action, $_item, $_data = null) { return $data; } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => array('redis_error', $e) @@ -222,7 +222,7 @@ function customize($_action, $_item, $_data = null) { return $image->identifyImage(); } catch (ImagickException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), 'msg' => 'imagick_exception' diff --git a/data/web/inc/functions.dkim.inc.php b/data/web/inc/functions.dkim.inc.php index 8099d2f846..17bac738f1 100644 --- a/data/web/inc/functions.dkim.inc.php +++ b/data/web/inc/functions.dkim.inc.php @@ -6,7 +6,7 @@ function dkim($_action, $_data = null) { switch ($_action) { case 'add': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'access_denied' @@ -17,7 +17,7 @@ function dkim($_action, $_data = null) { $dkim_selector = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : 'dkim'; $domain = $_data['domain']; if (!is_valid_domain_name($domain) || !is_numeric($key_length)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_domain_or_sel_invalid' @@ -25,7 +25,7 @@ function dkim($_action, $_data = null) { return false; } if ($redis->hGet('DKIM_PUB_KEYS', $domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_domain_or_sel_invalid' @@ -33,7 +33,7 @@ function dkim($_action, $_data = null) { return false; } if (!ctype_alnum($dkim_selector)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_domain_or_sel_invalid' @@ -58,7 +58,7 @@ function dkim($_action, $_data = null) { $redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => array('redis_error', $e) @@ -72,7 +72,7 @@ function dkim($_action, $_data = null) { $redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, trim($privKey)); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => array('redis_error', $e) @@ -80,7 +80,7 @@ function dkim($_action, $_data = null) { return false; } } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_added' @@ -88,7 +88,7 @@ function dkim($_action, $_data = null) { return true; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_domain_or_sel_invalid' @@ -98,7 +98,7 @@ function dkim($_action, $_data = null) { break; case 'import': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'access_denied' @@ -109,7 +109,7 @@ function dkim($_action, $_data = null) { $private_key_normalized = preg_replace('~\r\n?~', "\n", $private_key_input); $private_key = openssl_pkey_get_private($private_key_normalized); if ($ssl_error = openssl_error_string()) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => array('private_key_error', $ssl_error) @@ -126,7 +126,7 @@ function dkim($_action, $_data = null) { $dkim_selector = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : 'dkim'; $domain = $_data['domain']; if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_domain_or_sel_invalid' @@ -134,7 +134,7 @@ function dkim($_action, $_data = null) { return false; } if ($redis->hGet('DKIM_PUB_KEYS', $domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_domain_or_sel_invalid' @@ -142,7 +142,7 @@ function dkim($_action, $_data = null) { return false; } if (!ctype_alnum($dkim_selector)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_domain_or_sel_invalid' @@ -155,7 +155,7 @@ function dkim($_action, $_data = null) { $redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, $private_key_normalized); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => array('redis_error', $e) @@ -168,14 +168,14 @@ function dkim($_action, $_data = null) { try { } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => array('redis_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'dkim_added' @@ -215,7 +215,7 @@ function dkim($_action, $_data = null) { break; case 'blind': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'access_denied' @@ -231,7 +231,7 @@ function dkim($_action, $_data = null) { case 'delete': $domains = (array)$_data['domains']; if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => 'access_denied' @@ -240,12 +240,12 @@ function dkim($_action, $_data = null) { } foreach ($domains as $domain) { if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_domain_or_sel_invalid' + 'msg' => array('dkim_domain_or_sel_invalid', $domain) ); - return false; + continue; } try { $selector = $redis->hGet('DKIM_SELECTORS', $domain); @@ -254,19 +254,19 @@ function dkim($_action, $_data = null) { $redis->hDel('DKIM_SELECTORS', $domain); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => array('redis_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data), + 'msg' => array('dkim_removed', htmlspecialchars($domain)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => array('dkim_removed', htmlspecialchars(implode(', ', $domains))) - ); break; } } \ No newline at end of file diff --git a/data/web/inc/functions.docker.inc.php b/data/web/inc/functions.docker.inc.php index cac2db78aa..dbd26375c9 100644 --- a/data/web/inc/functions.docker.inc.php +++ b/data/web/inc/functions.docker.inc.php @@ -158,19 +158,19 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex if ($response === false) { $err = curl_error($curl); curl_close($curl); - logger(array('return' => array( + logger(array('return' => array(array( 'type' => 'danger', 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers), 'msg' => $err, - ))); + )))); return $err; } else { curl_close($curl); - logger(array('return' => array( + logger(array('return' => array(array( 'type' => 'success', 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers), - ))); + )))); if (empty($response)) { return true; } diff --git a/data/web/inc/functions.domain_admin.inc.php b/data/web/inc/functions.domain_admin.inc.php index 3c631d08f5..86cec6210f 100644 --- a/data/web/inc/functions.domain_admin.inc.php +++ b/data/web/inc/functions.domain_admin.inc.php @@ -14,7 +14,7 @@ function domain_admin($_action, $_data = null) { $domains = (array)$_data['domains']; $active = intval($_data['active']); if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -22,7 +22,7 @@ function domain_admin($_action, $_data = null) { return false; } if (empty($domains)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'domain_invalid' @@ -30,40 +30,32 @@ function domain_admin($_action, $_data = null) { return false; } if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username)) || empty ($username)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'username_invalid' ); return false; } - try { - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` - WHERE `username` = :username"); - $stmt->execute(array(':username' => $username)); - $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - - $stmt = $pdo->prepare("SELECT `username` FROM `admin` - WHERE `username` = :username"); - $stmt->execute(array(':username' => $username)); - $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - - $stmt = $pdo->prepare("SELECT `username` FROM `domain_admins` - WHERE `username` = :username"); - $stmt->execute(array(':username' => $username)); - $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); - return false; - } + + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` + WHERE `username` = :username"); + $stmt->execute(array(':username' => $username)); + $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = $pdo->prepare("SELECT `username` FROM `admin` + WHERE `username` = :username"); + $stmt->execute(array(':username' => $username)); + $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = $pdo->prepare("SELECT `username` FROM `domain_admins` + WHERE `username` = :username"); + $stmt->execute(array(':username' => $username)); + $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + foreach ($num_results as $num_results_each) { if ($num_results_each != 0) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('object_exists', htmlspecialchars($username)) @@ -73,7 +65,7 @@ function domain_admin($_action, $_data = null) { } if (!empty($password) && !empty($password2)) { if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'password_complexity' @@ -81,7 +73,7 @@ function domain_admin($_action, $_data = null) { return false; } if ($password != $password2) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'password_mismatch' @@ -91,7 +83,7 @@ function domain_admin($_action, $_data = null) { $password_hashed = hash_password($password); foreach ($domains as $domain) { if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'domain_invalid' @@ -110,7 +102,7 @@ function domain_admin($_action, $_data = null) { } catch (PDOException $e) { domain_admin('delete', $username); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) @@ -128,7 +120,7 @@ function domain_admin($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) @@ -137,14 +129,14 @@ function domain_admin($_action, $_data = null) { } } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'password_empty' ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('domain_admin_added', htmlspecialchars($username)) @@ -152,7 +144,7 @@ function domain_admin($_action, $_data = null) { break; case 'edit': if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -177,44 +169,44 @@ function domain_admin($_action, $_data = null) { $username_new = (!empty($_data['username_new'])) ? $_data['username_new'] : $is_now['username']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' ); - return false; + continue; } $password = $_data['password']; $password2 = $_data['password2']; - if (!empty($domains)) { - foreach ($domains as $domain) { + foreach ($domains as $i => &$domain) { if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'domain_invalid' + 'msg' => array('domain_invalid', htmlspecialchars($domain)) ); - return false; + unset($domains[$i]); + continue; } } } if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username_new))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'username_invalid' + 'msg' => array('username_invalid', $username_new) ); - return false; + continue; } if ($username_new != $username) { if (!empty(domain_admin('details', $username_new)['username'])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'username_invalid' + 'msg' => array('username_invalid', $username_new) ); - return false; + continue; } } try { @@ -224,12 +216,12 @@ function domain_admin($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } if (!empty($domains)) { @@ -245,32 +237,32 @@ function domain_admin($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } } } if (!empty($password) && !empty($password2)) { if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'password_complexity' ); - return false; + continue; } if ($password != $password2) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'password_mismatch' ); - return false; + continue; } $password_hashed = hash_password($password); try { @@ -291,12 +283,12 @@ function domain_admin($_action, $_data = null) { } } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } } else { @@ -317,20 +309,21 @@ function domain_admin($_action, $_data = null) { } } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('domain_admin_modified', htmlspecialchars($username)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('domain_admin_modified', htmlspecialchars(implode(', ', $usernames))) - ); + return true; } // Domain administrator // Can only edit itself @@ -344,8 +337,9 @@ function domain_admin($_action, $_data = null) { WHERE `username` = :user"); $stmt->execute(array(':user' => $username)); $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (!verify_hash($row['password'], $password_old)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -355,7 +349,7 @@ function domain_admin($_action, $_data = null) { if (!empty($password_new2) && !empty($password_new)) { if ($password_new2 != $password_new) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'password_mismatch' @@ -363,7 +357,7 @@ function domain_admin($_action, $_data = null) { return false; } if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password_new)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'password_complexity' @@ -379,7 +373,7 @@ function domain_admin($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) @@ -387,8 +381,7 @@ function domain_admin($_action, $_data = null) { return false; } } - - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('domain_admin_modified', htmlspecialchars($username)) @@ -397,7 +390,7 @@ function domain_admin($_action, $_data = null) { break; case 'delete': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -407,12 +400,12 @@ function domain_admin($_action, $_data = null) { $usernames = (array)$_data['username']; foreach ($usernames as $username) { if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'username_invalid' + 'msg' => array('username_invalid', $username) ); - return false; + continue; } try { $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username"); @@ -425,50 +418,43 @@ function domain_admin($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('domain_admin_removed', htmlspecialchars($username)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('domain_admin_removed', htmlspecialchars(implode(', ', $usernames))) - ); break; case 'get': $domainadmins = array(); if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' ); return false; } - try { - $stmt = $pdo->query("SELECT DISTINCT - `username` - FROM `domain_admins` - WHERE `username` IN ( - SELECT `username` FROM `admin` - WHERE `superadmin`!='1' - )"); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($rows)) { - $domainadmins[] = $row['username']; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); + + $stmt = $pdo->query("SELECT DISTINCT + `username` + FROM `domain_admins` + WHERE `username` IN ( + SELECT `username` FROM `admin` + WHERE `superadmin`!='1' + )"); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($rows)) { + $domainadmins[] = $row['username']; } + return $domainadmins; break; case 'details': @@ -484,61 +470,54 @@ function domain_admin($_action, $_data = null) { if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $_data))) { return false; } - try { - $stmt = $pdo->prepare("SELECT - `tfa`.`active` AS `tfa_active_int`, - CASE `tfa`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `tfa_active`, - `domain_admins`.`username`, - `domain_admins`.`created`, - `domain_admins`.`active` AS `active_int`, - CASE `domain_admins`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` - FROM `domain_admins` - LEFT OUTER JOIN `tfa` ON `tfa`.`username`=`domain_admins`.`username` - WHERE `domain_admins`.`username`= :domain_admin"); - $stmt->execute(array( - ':domain_admin' => $_data - )); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if (empty($row)) { - return false; - } - $domainadmindata['username'] = $row['username']; - $domainadmindata['tfa_active'] = $row['tfa_active']; - $domainadmindata['active'] = $row['active']; - $domainadmindata['tfa_active_int'] = $row['tfa_active_int']; - $domainadmindata['active_int'] = $row['active_int']; - $domainadmindata['modified'] = $row['created']; - // GET SELECTED - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` - WHERE `domain` IN ( - SELECT `domain` FROM `domain_admins` - WHERE `username`= :domain_admin)"); - $stmt->execute(array(':domain_admin' => $_data)); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $domainadmindata['selected_domains'][] = $row['domain']; - } - // GET UNSELECTED - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` - WHERE `domain` NOT IN ( - SELECT `domain` FROM `domain_admins` - WHERE `username`= :domain_admin)"); - $stmt->execute(array(':domain_admin' => $_data)); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $domainadmindata['unselected_domains'][] = $row['domain']; - } - if (!isset($domainadmindata['unselected_domains'])) { - $domainadmindata['unselected_domains'] = ""; - } + + $stmt = $pdo->prepare("SELECT + `tfa`.`active` AS `tfa_active_int`, + CASE `tfa`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `tfa_active`, + `domain_admins`.`username`, + `domain_admins`.`created`, + `domain_admins`.`active` AS `active_int`, + CASE `domain_admins`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` + FROM `domain_admins` + LEFT OUTER JOIN `tfa` ON `tfa`.`username`=`domain_admins`.`username` + WHERE `domain_admins`.`username`= :domain_admin"); + $stmt->execute(array( + ':domain_admin' => $_data + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (empty($row)) { + return false; } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); + $domainadmindata['username'] = $row['username']; + $domainadmindata['tfa_active'] = $row['tfa_active']; + $domainadmindata['active'] = $row['active']; + $domainadmindata['tfa_active_int'] = $row['tfa_active_int']; + $domainadmindata['active_int'] = $row['active_int']; + $domainadmindata['modified'] = $row['created']; + // GET SELECTED + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` + WHERE `domain` IN ( + SELECT `domain` FROM `domain_admins` + WHERE `username`= :domain_admin)"); + $stmt->execute(array(':domain_admin' => $_data)); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $domainadmindata['selected_domains'][] = $row['domain']; } + // GET UNSELECTED + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` + WHERE `domain` NOT IN ( + SELECT `domain` FROM `domain_admins` + WHERE `username`= :domain_admin)"); + $stmt->execute(array(':domain_admin' => $_data)); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $domainadmindata['unselected_domains'][] = $row['domain']; + } + if (!isset($domainadmindata['unselected_domains'])) { + $domainadmindata['unselected_domains'] = ""; + } + return $domainadmindata; break; } diff --git a/data/web/inc/functions.fail2ban.inc.php b/data/web/inc/functions.fail2ban.inc.php index 668e41cb2e..166606ef2b 100644 --- a/data/web/inc/functions.fail2ban.inc.php +++ b/data/web/inc/functions.fail2ban.inc.php @@ -80,7 +80,7 @@ function fail2ban($_action, $_data = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) @@ -91,7 +91,7 @@ function fail2ban($_action, $_data = null) { break; case 'edit': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -101,29 +101,39 @@ function fail2ban($_action, $_data = null) { if (isset($_data['action']) && !empty($_data['network'])) { $networks = (array) $_data['network']; foreach ($networks as $network) { - if ($_data['action'] == "unban") { - if (valid_network($network)) { - $redis->hSet('F2B_QUEUE_UNBAN', $network, 1); + try { + if ($_data['action'] == "unban") { + if (valid_network($network)) { + $redis->hSet('F2B_QUEUE_UNBAN', $network, 1); + } } - } - elseif ($_data['action'] == "whitelist") { - if (valid_network($network)) { - $redis->hSet('F2B_WHITELIST', $network, 1); - $redis->hDel('F2B_BLACKLIST', $network, 1); - $redis->hSet('F2B_QUEUE_UNBAN', $network, 1); + elseif ($_data['action'] == "whitelist") { + if (valid_network($network)) { + $redis->hSet('F2B_WHITELIST', $network, 1); + $redis->hDel('F2B_BLACKLIST', $network, 1); + $redis->hSet('F2B_QUEUE_UNBAN', $network, 1); + } } - } - elseif ($_data['action'] == "blacklist") { - if (valid_network($network)) { - $redis->hSet('F2B_BLACKLIST', $network, 1); + elseif ($_data['action'] == "blacklist") { + if (valid_network($network)) { + $redis->hSet('F2B_BLACKLIST', $network, 1); + } } } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('redis_error', $e) + ); + continue; + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('object_modified', htmlspecialchars($network)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('object_modified', htmlspecialchars(implode(', ', $networks))) - ); return true; } $is_now = fail2ban('get'); @@ -137,7 +147,7 @@ function fail2ban($_action, $_data = null) { $bl = (isset($_data['blacklist'])) ? $_data['blacklist'] : $is_now['blacklist']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -178,14 +188,14 @@ function fail2ban($_action, $_data = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'f2b_modified' diff --git a/data/web/inc/functions.fwdhost.inc.php b/data/web/inc/functions.fwdhost.inc.php index f16834ea6f..5c511f4f26 100644 --- a/data/web/inc/functions.fwdhost.inc.php +++ b/data/web/inc/functions.fwdhost.inc.php @@ -8,7 +8,7 @@ function fwdhost($_action, $_data = null) { case 'add': global $lang; if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -28,7 +28,7 @@ function fwdhost($_action, $_data = null) { $hosts = get_outgoing_hosts_best_guess($host); } if (empty($hosts)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('invalid_host', htmlspecialchars($host)) @@ -46,7 +46,7 @@ function fwdhost($_action, $_data = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) @@ -54,7 +54,7 @@ function fwdhost($_action, $_data = null) { return false; } } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('forwarding_host_added', htmlspecialchars(implode(', ', $hosts))) @@ -63,7 +63,7 @@ function fwdhost($_action, $_data = null) { case 'edit': global $lang; if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -77,12 +77,12 @@ function fwdhost($_action, $_data = null) { $keep_spam = (isset($_data['keep_spam'])) ? $_data['keep_spam'] : $is_now['keep_spam']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' ); - return false; + continue; } try { if ($keep_spam == 1) { @@ -93,19 +93,19 @@ function fwdhost($_action, $_data = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('object_modified', htmlspecialchars($fwdhost)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('object_modified', htmlspecialchars(implode(', ', $fwdhosts))) - ); break; case 'delete': $hosts = (array)$_data['forwardinghost']; @@ -115,19 +115,19 @@ function fwdhost($_action, $_data = null) { $redis->hDel('KEEP_SPAM', $host); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('forwarding_host_removed', htmlspecialchars($host)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('forwarding_host_removed', htmlspecialchars(implode(', ', $hosts))) - ); break; case 'get': if ($_SESSION['mailcow_cc_role'] != "admin") { @@ -148,7 +148,7 @@ function fwdhost($_action, $_data = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) @@ -170,7 +170,7 @@ function fwdhost($_action, $_data = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index d99661cb09..a44cf7eb3c 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -5,64 +5,81 @@ function hash_password($password) { } function last_login($user) { global $pdo; - try { - $stmt = $pdo->prepare('SELECT `remote`, `time` FROM `logs` - WHERE JSON_EXTRACT(`call`, "$[0]") = "check_login" - AND JSON_EXTRACT(`call`, "$[1]") = :user - AND `type` = "success" ORDER BY `time` DESC LIMIT 1'); - $stmt->execute(array(':user' => $user)); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if (!empty($row)) { - return $row; - } - else { - return false; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $username, $role, $domain), - 'msg' => array('mysql_error', $e) - ); + $stmt = $pdo->prepare('SELECT `remote`, `time` FROM `logs` + WHERE JSON_EXTRACT(`call`, "$[0]") = "check_login" + AND JSON_EXTRACT(`call`, "$[1]") = :user + AND `type` = "success" ORDER BY `time` DESC LIMIT 1'); + $stmt->execute(array(':user' => $user)); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (!empty($row)) { + return $row; + } + else { return false; } } function logger($_data = false) { + /* + logger() will be called as last function + To manually log a message, logger needs to be called like below. + + logger(array( + 'return' => array( + array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => $err + ) + ) + )); + + These messages will not be printed as alert box. + To do so, push them to $_SESSION['return'] and do not call logger as they will be included automatically: + + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $user, '*'), + 'msg' => $err + ); + */ global $pdo; if (!$_data) { $_data = $_SESSION; } if (!empty($_data['return'])) { - $type = $_data['return']['type']; - $msg = json_encode($_data['return']['msg'], JSON_UNESCAPED_UNICODE); - $call = json_encode($_data['return']['log'], JSON_UNESCAPED_UNICODE); - if (!empty($_SESSION["dual-login"]["username"])) { - $user = $_SESSION["dual-login"]["username"] . ' => ' . $_SESSION['mailcow_cc_username']; - $role = $_SESSION["dual-login"]["role"] . ' => ' . $_SESSION['mailcow_cc_role']; - } - elseif (!empty($_SESSION['mailcow_cc_username'])) { - $user = $_SESSION['mailcow_cc_username']; - $role = $_SESSION['mailcow_cc_role']; - } - else { - $user = 'unauthenticated'; - $role = 'unauthenticated'; + $task = substr(strtoupper(md5(uniqid(rand(), true))), 0, 6); + foreach ($_data['return'] as $return) { + $type = $return['type']; + $msg = json_encode($return['msg'], JSON_UNESCAPED_UNICODE); + $call = json_encode($return['log'], JSON_UNESCAPED_UNICODE); + if (!empty($_SESSION["dual-login"]["username"])) { + $user = $_SESSION["dual-login"]["username"] . ' => ' . $_SESSION['mailcow_cc_username']; + $role = $_SESSION["dual-login"]["role"] . ' => ' . $_SESSION['mailcow_cc_role']; + } + elseif (!empty($_SESSION['mailcow_cc_username'])) { + $user = $_SESSION['mailcow_cc_username']; + $role = $_SESSION['mailcow_cc_role']; + } + else { + $user = 'unauthenticated'; + $role = 'unauthenticated'; + } + $stmt = $pdo->prepare("INSERT INTO `logs` (`type`, `task`, `msg`, `call`, `user`, `role`, `remote`, `time`) VALUES + (:type, :task, :msg, :call, :user, :role, :remote, UNIX_TIMESTAMP())"); + $stmt->execute(array( + ':type' => $type, + ':task' => $task, + ':call' => $call, + ':msg' => $msg, + ':user' => $user, + ':role' => $role, + ':remote' => get_remote_ip() + )); } } else { return true; } - $stmt = $pdo->prepare("INSERT INTO `logs` (`type`, `msg`, `call`, `user`, `role`, `remote`, `time`) VALUES - (:type, :msg, :call, :user, :role, :remote, UNIX_TIMESTAMP())"); - $stmt->execute(array( - ':type' => $type, - ':call' => $call, - ':msg' => $msg, - ':user' => $user, - ':role' => $role, - ':remote' => get_remote_ip() - )); } function hasDomainAccess($username, $role, $domain) { global $pdo; @@ -75,25 +92,15 @@ function hasDomainAccess($username, $role, $domain) { if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') { return false; } - try { - $stmt = $pdo->prepare("SELECT `domain` FROM `domain_admins` - WHERE ( - `active`='1' - AND `username` = :username - AND (`domain` = :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2)) - ) - OR 'admin' = :role"); - $stmt->execute(array(':username' => $username, ':domain1' => $domain, ':domain2' => $domain, ':role' => $role)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $username, $role, $domain), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `domain` FROM `domain_admins` + WHERE ( + `active`='1' + AND `username` = :username + AND (`domain` = :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2)) + ) + OR 'admin' = :role"); + $stmt->execute(array(':username' => $username, ':domain1' => $domain, ':domain2' => $domain, ':role' => $role)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); if (!empty($num_results)) { return true; } @@ -110,18 +117,12 @@ function hasMailboxObjectAccess($username, $role, $object) { if ($username == $object) { return true; } - try { - $stmt = $pdo->prepare("SELECT `domain` FROM `mailbox` WHERE `username` = :object"); - $stmt->execute(array(':object' => $object)); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if (isset($row['domain']) && hasDomainAccess($username, $role, $row['domain'])) { - return true; - } - } - catch(PDOException $e) { - error_log($e); - return false; - } + $stmt = $pdo->prepare("SELECT `domain` FROM `mailbox` WHERE `username` = :object"); + $stmt->execute(array(':object' => $object)); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (isset($row['domain']) && hasDomainAccess($username, $role, $row['domain'])) { + return true; + } return false; } function pem_to_der($pem_key) { @@ -193,25 +194,30 @@ function generate_tlsa_digest($hostname, $port, $starttls = null) { function alertbox_log_parser($_data){ global $lang; if (isset($_data['return'])) { - // Get type - $type = $_data['return']['type']; - // If a lang[type][msg] string exists, use it as message - if (is_string($lang[$_data['return']['type']][$_data['return']['msg']])) { - $msg = $lang[$_data['return']['type']][$_data['return']['msg']]; - } - // If msg is an array, use first element as language string and run printf on it with remaining array elements - elseif (is_array($_data['return']['msg'])) { - $msg = array_shift($_data['return']['msg']); - $msg = vsprintf( - $lang[$_data['return']['type']][$msg], - $_data['return']['msg'] - ); + foreach ($_data['return'] as $return) { + // Get type + $type = $return['type']; + // If a lang[type][msg] string exists, use it as message + if (is_string($lang[$return['type']][$return['msg']])) { + $msg = $lang[$return['type']][$return['msg']]; + } + // If msg is an array, use first element as language string and run printf on it with remaining array elements + elseif (is_array($return['msg'])) { + $msg = array_shift($return['msg']); + $msg = vsprintf( + $lang[$return['type']][$msg], + $return['msg'] + ); + } + // If none applies, use msg as returned message + else { + $msg = $return['msg']; + } + $log_array[] = array('msg' => json_encode($msg), 'type' => json_encode($type)); } - // If none applies, use msg as returned message - else { - $msg = $_data['return']['msg']; + if (!empty($log_array)) { + return $log_array; } - return array('msg' => json_encode($msg), 'type' => json_encode($type)); } return false; } @@ -260,7 +266,7 @@ function check_login($user, $pass) { global $pdo; global $redis; if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $user, '*'), 'msg' => 'malformed_username' @@ -280,7 +286,7 @@ function check_login($user, $pass) { $_SESSION['pending_mailcow_cc_role'] = "admin"; $_SESSION['pending_tfa_method'] = get_tfa($user)['name']; unset($_SESSION['ldelay']); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'info', 'log' => array(__FUNCTION__, $user, '*'), 'msg' => 'awaiting_tfa_confirmation' @@ -289,7 +295,7 @@ function check_login($user, $pass) { } else { unset($_SESSION['ldelay']); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $user, '*'), 'msg' => array('logged_in_as', $user) @@ -311,7 +317,7 @@ function check_login($user, $pass) { $_SESSION['pending_mailcow_cc_role'] = "domainadmin"; $_SESSION['pending_tfa_method'] = get_tfa($user)['name']; unset($_SESSION['ldelay']); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'info', 'log' => array(__FUNCTION__, $user, '*'), 'msg' => 'awaiting_tfa_confirmation' @@ -323,7 +329,7 @@ function check_login($user, $pass) { // Reactivate TFA if it was set to "deactivate TFA for next login" $stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user"); $stmt->execute(array(':user' => $user)); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $user, '*'), 'msg' => array('logged_in_as', $user) @@ -341,7 +347,7 @@ function check_login($user, $pass) { foreach ($rows as $row) { if (verify_hash($row['password'], $pass) !== false) { unset($_SESSION['ldelay']); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $user, '*'), 'msg' => array('logged_in_as', $user) @@ -359,7 +365,7 @@ function check_login($user, $pass) { $redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']); error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']); } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $user, '*'), 'msg' => 'login_failed' @@ -390,7 +396,7 @@ function set_acl() { $_SESSION = array_merge($_SESSION, $acl); } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'info', 'log' => array(__FUNCTION__), 'msg' => 'set_acl_failed' @@ -433,7 +439,7 @@ function edit_admin_account($_data) { !isset($_data_log['admin_pass']) ?: $_data_log['admin_pass'] = '*'; !isset($_data_log['admin_pass2']) ?: $_data_log['admin_pass2'] = '*'; if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'access_denied' @@ -445,7 +451,7 @@ function edit_admin_account($_data) { $password = $_data['admin_pass']; $password2 = $_data['admin_pass2']; if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username)) || empty ($username)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'username_invalid' @@ -454,7 +460,7 @@ function edit_admin_account($_data) { } if (!empty($password) && !empty($password2)) { if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'password_complexity' @@ -462,7 +468,7 @@ function edit_admin_account($_data) { return false; } if ($password != $password2) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'password_mismatch' @@ -482,7 +488,7 @@ function edit_admin_account($_data) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mysql_error', $e) @@ -501,7 +507,7 @@ function edit_admin_account($_data) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mysql_error', $e) @@ -516,7 +522,7 @@ function edit_admin_account($_data) { $stmt->execute(array(':username1' => $username, ':username2' => $username_now)); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mysql_error', $e) @@ -524,7 +530,7 @@ function edit_admin_account($_data) { return false; } $_SESSION['mailcow_cc_username'] = $username; - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'admin_modified' @@ -552,7 +558,7 @@ function edit_user_account($_data) { $role = $_SESSION['mailcow_cc_role']; $password_old = $_data['user_old_pass']; if (filter_var($username, FILTER_VALIDATE_EMAIL === false) || $role != 'user') { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'access_denied' @@ -569,7 +575,7 @@ function edit_user_account($_data) { $stmt->execute(array(':user' => $username)); $row = $stmt->fetch(PDO::FETCH_ASSOC); if (!verify_hash($row['password'], $password_old)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'access_denied' @@ -579,7 +585,7 @@ function edit_user_account($_data) { if (isset($password_new) && isset($password_new2)) { if (!empty($password_new2) && !empty($password_new)) { if ($password_new2 != $password_new) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'password_mismatch' @@ -587,7 +593,7 @@ function edit_user_account($_data) { return false; } if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password_new)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'password_complexity' @@ -603,7 +609,7 @@ function edit_user_account($_data) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mysql_error', $e) @@ -613,7 +619,7 @@ function edit_user_account($_data) { } } update_sogo_static_view(); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mailbox_modified', htmlspecialchars($username)) @@ -628,73 +634,63 @@ function user_get_alias_details($username) { if (!filter_var($username, FILTER_VALIDATE_EMAIL)) { return false; } - try { - $data['address'] = $username; - $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') AS `shared_aliases` FROM `alias` - WHERE `goto` REGEXP :username_goto - AND `address` NOT LIKE '@%' - AND `goto` != :username_goto2 - AND `address` != :username_address"); - $stmt->execute(array( - ':username_goto' => '(^|,)'.$username.'($|,)', - ':username_goto2' => $username, - ':username_address' => $username - )); - $run = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($run)) { - $data['shared_aliases'] = $row['shared_aliases']; - } - $stmt = $pdo->prepare("SELECT GROUP_CONCAT(`address` SEPARATOR ', ') AS `direct_aliases` FROM `alias` - WHERE `goto` = :username_goto - AND `address` NOT LIKE '@%' - AND `address` != :username_address"); - $stmt->execute( - array( - ':username_goto' => $username, - ':username_address' => $username - )); - $run = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($run)) { - $data['direct_aliases'][] = $row['direct_aliases']; - } - $stmt = $pdo->prepare("SELECT GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ', ') AS `ad_alias` FROM `mailbox` - LEFT OUTER JOIN `alias_domain` on `target_domain` = `domain` - WHERE `username` = :username ;"); - $stmt->execute(array(':username' => $username)); - $run = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($run)) { - $data['direct_aliases'][] = $row['ad_alias']; - } - $data['direct_aliases'] = implode(', ', array_filter($data['direct_aliases'])); - $data['direct_aliases'] = empty($data['direct_aliases']) ? '✘' : $data['direct_aliases']; - $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '✘') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` NOT LIKE '@%';"); - $stmt->execute(array(':username' => $username)); - $run = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($run)) { - $data['aliases_also_send_as'] = $row['send_as']; - } - $stmt = $pdo->prepare("SELECT IFNULL(CONCAT(GROUP_CONCAT(DISTINCT `send_as` SEPARATOR ', '), ', ', GROUP_CONCAT(DISTINCT CONCAT('@',`alias_domain`) SEPARATOR ', ')), '✘') AS `send_as` FROM `sender_acl` LEFT JOIN `alias_domain` ON `alias_domain`.`target_domain` = TRIM(LEADING '@' FROM `send_as`) WHERE `logged_in_as` = :username AND `send_as` LIKE '@%';"); - $stmt->execute(array(':username' => $username)); - $run = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($run)) { - $data['aliases_send_as_all'] = $row['send_as']; - } - $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') as `address` FROM `alias` WHERE `goto` REGEXP :username AND `address` LIKE '@%';"); - $stmt->execute(array(':username' => '(^|,)'.$username.'($|,)')); - $run = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($run)) { - $data['is_catch_all'] = $row['address']; - } - return $data; + $data['address'] = $username; + $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') AS `shared_aliases` FROM `alias` + WHERE `goto` REGEXP :username_goto + AND `address` NOT LIKE '@%' + AND `goto` != :username_goto2 + AND `address` != :username_address"); + $stmt->execute(array( + ':username_goto' => '(^|,)'.$username.'($|,)', + ':username_goto2' => $username, + ':username_address' => $username + )); + $run = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($run)) { + $data['shared_aliases'] = $row['shared_aliases']; } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $username), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT GROUP_CONCAT(`address` SEPARATOR ', ') AS `direct_aliases` FROM `alias` + WHERE `goto` = :username_goto + AND `address` NOT LIKE '@%' + AND `address` != :username_address"); + $stmt->execute( + array( + ':username_goto' => $username, + ':username_address' => $username + )); + $run = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($run)) { + $data['direct_aliases'][] = $row['direct_aliases']; + } + $stmt = $pdo->prepare("SELECT GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ', ') AS `ad_alias` FROM `mailbox` + LEFT OUTER JOIN `alias_domain` on `target_domain` = `domain` + WHERE `username` = :username ;"); + $stmt->execute(array(':username' => $username)); + $run = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($run)) { + $data['direct_aliases'][] = $row['ad_alias']; + } + $data['direct_aliases'] = implode(', ', array_filter($data['direct_aliases'])); + $data['direct_aliases'] = empty($data['direct_aliases']) ? '✘' : $data['direct_aliases']; + $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '✘') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` NOT LIKE '@%';"); + $stmt->execute(array(':username' => $username)); + $run = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($run)) { + $data['aliases_also_send_as'] = $row['send_as']; } + $stmt = $pdo->prepare("SELECT IFNULL(CONCAT(GROUP_CONCAT(DISTINCT `send_as` SEPARATOR ', '), ', ', GROUP_CONCAT(DISTINCT CONCAT('@',`alias_domain`) SEPARATOR ', ')), '✘') AS `send_as` FROM `sender_acl` LEFT JOIN `alias_domain` ON `alias_domain`.`target_domain` = TRIM(LEADING '@' FROM `send_as`) WHERE `logged_in_as` = :username AND `send_as` LIKE '@%';"); + $stmt->execute(array(':username' => $username)); + $run = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($run)) { + $data['aliases_send_as_all'] = $row['send_as']; + } + $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') as `address` FROM `alias` WHERE `goto` REGEXP :username AND `address` LIKE '@%';"); + $stmt->execute(array(':username' => '(^|,)'.$username.'($|,)')); + $run = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($run)) { + $data['is_catch_all'] = $row['address']; + } + return $data; } function is_valid_domain_name($domain_name) { if (empty($domain_name)) { @@ -716,7 +712,7 @@ function set_tfa($_data) { $username = $_SESSION['mailcow_cc_username']; if ($_SESSION['mailcow_cc_role'] != "domainadmin" && $_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'access_denied' @@ -728,7 +724,7 @@ function set_tfa($_data) { $stmt->execute(array(':user' => $username)); $row = $stmt->fetch(PDO::FETCH_ASSOC); if (!verify_hash($row['password'], $_data["confirm_password"])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'access_denied' @@ -743,7 +739,7 @@ function set_tfa($_data) { $yubico_key = $_data['yubico_key']; $yubi = new Auth_Yubico($yubico_id, $yubico_key); if (!$yubi) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'access_denied' @@ -751,7 +747,7 @@ function set_tfa($_data) { return false; } if (!ctype_alnum($_data["otp_token"]) || strlen($_data["otp_token"]) != 44) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'tfa_token_invalid' @@ -760,7 +756,7 @@ function set_tfa($_data) { } $yauth = $yubi->verify($_data["otp_token"]); if (PEAR::isError($yauth)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('yotp_verification_failed', $yauth->getMessage()) @@ -780,14 +776,14 @@ function set_tfa($_data) { $stmt->execute(array(':key_id' => $key_id, ':username' => $username, ':secret' => $yubico_id . ':' . $yubico_key . ':' . $yubico_modhex_id)); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mysql_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('object_modified', htmlspecialchars($username)) @@ -801,7 +797,7 @@ function set_tfa($_data) { $stmt->execute(array(':username' => $username)); $stmt = $pdo->prepare("INSERT INTO `tfa` (`username`, `key_id`, `authmech`, `keyHandle`, `publicKey`, `certificate`, `counter`, `active`) VALUES (?, ?, 'u2f', ?, ?, ?, ?, '1')"); $stmt->execute(array($username, $key_id, $reg->keyHandle, $reg->publicKey, $reg->certificate, $reg->counter)); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('object_modified', $username) @@ -809,7 +805,7 @@ function set_tfa($_data) { $_SESSION['regReq'] = null; } catch (Exception $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('u2f_verification_failed', $e->getMessage()) @@ -828,21 +824,21 @@ function set_tfa($_data) { $stmt->execute(array($username, $key_id, $_POST['totp_secret'])); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mysql_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('object_modified', $username) ); } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'totp_verification_failed' @@ -855,14 +851,14 @@ function set_tfa($_data) { $stmt->execute(array(':username' => $username)); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mysql_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('object_modified', htmlspecialchars($username)) @@ -880,7 +876,7 @@ function unset_tfa_key($_data) { $username = $_SESSION['mailcow_cc_username']; if ($_SESSION['mailcow_cc_role'] != "domainadmin" && $_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'access_denied' @@ -889,7 +885,7 @@ function unset_tfa_key($_data) { } try { if (!is_numeric($id)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'access_denied' @@ -901,7 +897,7 @@ function unset_tfa_key($_data) { $stmt->execute(array(':username' => $username)); $row = $stmt->fetch(PDO::FETCH_ASSOC); if ($row['keys'] == "1") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => 'last_key' @@ -910,14 +906,14 @@ function unset_tfa_key($_data) { } $stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username AND `id` = :id"); $stmt->execute(array(':username' => $username, ':id' => $id)); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('object_modified', $username) ); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_data_log), 'msg' => array('mysql_error', $e) @@ -1004,7 +1000,7 @@ function verify_tfa_login($username, $token) { switch ($row["authmech"]) { case "yubi_otp": if (!ctype_alnum($token) || strlen($token) != 44) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => array('yotp_verification_failed', 'token length error') @@ -1023,7 +1019,7 @@ function verify_tfa_login($username, $token) { $yubi = new Auth_Yubico($yubico_auth[0], $yubico_auth[1]); $yauth = $yubi->verify($token); if (PEAR::isError($yauth)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => array('yotp_verification_failed', $yauth->getMessage()) @@ -1032,14 +1028,14 @@ function verify_tfa_login($username, $token) { } else { $_SESSION['tfa_id'] = $row['id']; - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => 'verified_yotp_login' ); return true; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => array('yotp_verification_failed', 'unknown') @@ -1053,7 +1049,7 @@ function verify_tfa_login($username, $token) { $stmt->execute(array($reg->counter, $reg->id)); $_SESSION['tfa_id'] = $reg->id; $_SESSION['authReq'] = null; - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => 'verified_u2f_login' @@ -1061,7 +1057,7 @@ function verify_tfa_login($username, $token) { return true; } catch (Exception $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => array('u2f_verification_failed', $e->getMessage()) @@ -1069,7 +1065,7 @@ function verify_tfa_login($username, $token) { $_SESSION['regReq'] = null; return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => array('u2f_verification_failed', 'unknown') @@ -1089,14 +1085,14 @@ function verify_tfa_login($username, $token) { $row = $stmt->fetch(PDO::FETCH_ASSOC); if ($tfa->verifyCode($row['secret'], $_POST['token']) === true) { $_SESSION['tfa_id'] = $row['id']; - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => 'verified_totp_login' ); return true; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => 'totp_verification_failed' @@ -1104,7 +1100,7 @@ function verify_tfa_login($username, $token) { return false; } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => array('mysql_error', $e) @@ -1113,7 +1109,7 @@ function verify_tfa_login($username, $token) { } break; default: - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $username, '*'), 'msg' => 'unknown_tfa_method' @@ -1127,7 +1123,7 @@ function admin_api($action, $data = null) { global $pdo; global $lang; if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__), 'msg' => 'access_denied' @@ -1147,7 +1143,7 @@ function admin_api($action, $data = null) { } $allow_from = implode(',', array_unique(array_filter($allow_from))); if (empty($allow_from)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $data), 'msg' => 'ip_list_empty' @@ -1187,7 +1183,7 @@ function admin_api($action, $data = null) { )); break; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $data), 'msg' => 'admin_modified' @@ -1196,7 +1192,7 @@ function admin_api($action, $data = null) { function rspamd_ui($action, $data = null) { global $lang; if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__), 'msg' => 'access_denied' @@ -1208,7 +1204,7 @@ function rspamd_ui($action, $data = null) { $rspamd_ui_pass = $data['rspamd_ui_pass']; $rspamd_ui_pass2 = $data['rspamd_ui_pass2']; if (empty($rspamd_ui_pass) || empty($rspamd_ui_pass2)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, '*', '*'), 'msg' => 'password_empty' @@ -1216,7 +1212,7 @@ function rspamd_ui($action, $data = null) { return false; } if ($rspamd_ui_pass != $rspamd_ui_pass2) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, '*', '*'), 'msg' => 'password_mismatch' @@ -1224,7 +1220,7 @@ function rspamd_ui($action, $data = null) { return false; } if (strlen($rspamd_ui_pass) < 6) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, '*', '*'), 'msg' => 'rspamd_ui_pw_length' @@ -1234,7 +1230,7 @@ function rspamd_ui($action, $data = null) { $docker_return = docker('post', 'rspamd-mailcow', 'exec', array('cmd' => 'worker_password', 'raw' => $rspamd_ui_pass), array('Content-Type: application/json')); if ($docker_return_array = json_decode($docker_return, true)) { if ($docker_return_array['type'] == 'success') { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, '*', '*'), 'msg' => 'rspamd_ui_pw_set' @@ -1242,7 +1238,7 @@ function rspamd_ui($action, $data = null) { return true; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => $docker_return_array['type'], 'log' => array(__FUNCTION__, '*', '*'), 'msg' => $docker_return_array['msg'] @@ -1251,7 +1247,7 @@ function rspamd_ui($action, $data = null) { } } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, '*', '*'), 'msg' => 'unknown' @@ -1269,20 +1265,11 @@ function get_admin_details() { if ($_SESSION['mailcow_cc_role'] != 'admin') { return false; } - try { - $stmt = $pdo->query("SELECT `admin`.`username`, `api`.`active` AS `api_active`, `api`.`api_key`, `api`.`allow_from` FROM `admin` - INNER JOIN `api` ON `admin`.`username` = `api`.`username` - WHERE `admin`.`superadmin`='1' - AND `admin`.`active`='1'"); - $data = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__), - 'msg' => array('mysql_error', $e) - ); - } + $stmt = $pdo->query("SELECT `admin`.`username`, `api`.`active` AS `api_active`, `api`.`api_key`, `api`.`allow_from` FROM `admin` + INNER JOIN `api` ON `admin`.`username` = `api`.`username` + WHERE `admin`.`superadmin`='1' + AND `admin`.`active`='1'"); + $data = $stmt->fetch(PDO::FETCH_ASSOC); return $data; } function get_u2f_registrations($username) { @@ -1313,37 +1300,19 @@ function get_logs($container, $lines = false) { // SQL if ($container == "mailcow-ui") { if (isset($from) && isset($to)) { - try { - $stmt = $pdo->prepare("SELECT * FROM `logs` ORDER BY `id` DESC LIMIT :from, :to"); - $stmt->execute(array( - ':from' => $from - 1, - ':to' => $to - )); - $data = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__), - 'msg' => array('mysql_error', $e) - ); - } + $stmt = $pdo->prepare("SELECT * FROM `logs` ORDER BY `id` DESC LIMIT :from, :to"); + $stmt->execute(array( + ':from' => $from - 1, + ':to' => $to + )); + $data = $stmt->fetchAll(PDO::FETCH_ASSOC); } else { - try { - $stmt = $pdo->prepare("SELECT * FROM `logs` ORDER BY `id` DESC LIMIT :lines"); - $stmt->execute(array( - ':lines' => $lines + 1, - )); - $data = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__), - 'msg' => array('mysql_error', $e) - ); - } + $stmt = $pdo->prepare("SELECT * FROM `logs` ORDER BY `id` DESC LIMIT :lines"); + $stmt->execute(array( + ':lines' => $lines + 1, + )); + $data = $stmt->fetchAll(PDO::FETCH_ASSOC); } if (is_array($data)) { return $data; diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index d0d1cd1a69..82481cc3d4 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -11,7 +11,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { switch ($_type) { case 'time_limited_alias': if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -20,7 +20,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } if (isset($_data['username']) && filter_var($_data['username'], FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data['username'])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -35,47 +35,27 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $username = $_SESSION['mailcow_cc_username']; } if (!is_numeric($_data["validity"]) || $_data["validity"] > 672) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'validity_missing' ); return false; } - try { - $stmt = $pdo->prepare("SELECT `domain` FROM `mailbox` WHERE `username` = :username"); - $stmt->execute(array(':username' => $_SESSION['mailcow_cc_username'])); - $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain']; - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `domain` FROM `mailbox` WHERE `username` = :username"); + $stmt->execute(array(':username' => $_SESSION['mailcow_cc_username'])); + $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain']; $validity = strtotime("+".$_data["validity"]." hour"); $letters = 'abcefghijklmnopqrstuvwxyz1234567890'; $random_name = substr(str_shuffle($letters), 0, 24); - try { - $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES - (:address, :goto, :validity)"); - $stmt->execute(array( - ':address' => $random_name . '@' . $domain, - ':goto' => $username, - ':validity' => $validity - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } - $_SESSION['return'] = array( + $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES + (:address, :goto, :validity)"); + $stmt->execute(array( + ':address' => $random_name . '@' . $domain, + ':goto' => $username, + ':validity' => $validity + )); + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_modified', htmlspecialchars($_SESSION['mailcow_cc_username'])) @@ -84,7 +64,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { case 'filter': $sieve = new Sieve\SieveParser(); if (!isset($_SESSION['acl']['filters']) || $_SESSION['acl']['filters'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -93,7 +73,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } if (isset($_data['username']) && filter_var($_data['username'], FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data['username'])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -108,7 +88,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $username = $_SESSION['mailcow_cc_username']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'no_user_defined' @@ -120,7 +100,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $script_desc = $_data['script_desc']; $filter_type = $_data['filter_type']; if (empty($script_data)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'script_empty' @@ -131,7 +111,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $sieve->parse($script_data); } catch (Exception $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('sieve_error', $e->getMessage()) @@ -139,7 +119,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (empty($script_data) || empty($script_desc)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'value_missing' @@ -147,7 +127,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if ($filter_type != 'postfilter' && $filter_type != 'prefilter') { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'filter_type' @@ -156,46 +136,26 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } if (!empty($active)) { $script_name = 'active'; - try { - $stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_name` = 'inactive' WHERE `username` = :username AND `filter_type` = :filter_type"); - $stmt->execute(array( - ':username' => $username, - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - ':filter_type' => $filter_type - )); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } - } - else { - $script_name = 'inactive'; - } - try { - $stmt = $pdo->prepare("INSERT INTO `sieve_filters` (`username`, `script_data`, `script_desc`, `script_name`, `filter_type`) - VALUES (:username, :script_data, :script_desc, :script_name, :filter_type)"); + $stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_name` = 'inactive' WHERE `username` = :username AND `filter_type` = :filter_type"); $stmt->execute(array( ':username' => $username, - ':script_data' => $script_data, - ':script_desc' => $script_desc, - ':script_name' => $script_name, + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), ':filter_type' => $filter_type )); } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + else { + $script_name = 'inactive'; } - $_SESSION['return'] = array( + $stmt = $pdo->prepare("INSERT INTO `sieve_filters` (`username`, `script_data`, `script_desc`, `script_name`, `filter_type`) + VALUES (:username, :script_data, :script_desc, :script_name, :filter_type)"); + $stmt->execute(array( + ':username' => $username, + ':script_data' => $script_data, + ':script_desc' => $script_desc, + ':script_name' => $script_name, + ':filter_type' => $filter_type + )); + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_modified', $username) @@ -203,7 +163,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { break; case 'syncjob': if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -212,7 +172,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } if (isset($_data['username']) && filter_var($_data['username'], FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data['username'])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -227,7 +187,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $username = $_SESSION['mailcow_cc_username']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'no_user_defined' @@ -270,7 +230,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $maxbytespersecond = "0"; } if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -278,7 +238,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (!filter_var($mins_interval, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 3600)))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -286,7 +246,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (!is_valid_domain_name($host1)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -294,7 +254,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if ($enc1 != "TLS" && $enc1 != "SSL" && $enc1 != "PLAIN") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -302,72 +262,52 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (@preg_match("/" . $exclude . "/", null) === false) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); return false; } - try { - $stmt = $pdo->prepare("SELECT '1' FROM `imapsync` - WHERE `user2` = :user2 AND `user1` = :user1 AND `host1` = :host1"); - $stmt->execute(array(':user1' => $user1, ':user2' => $username, ':host1' => $host1)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT '1' FROM `imapsync` + WHERE `user2` = :user2 AND `user1` = :user1 AND `host1` = :host1"); + $stmt->execute(array(':user1' => $user1, ':user2' => $username, ':host1' => $host1)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); if ($num_results != 0) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('object_exists', htmlspecialchars($host1 . ' / ' . $user1)) ); return false; } - try { - $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `timeout1`, `timeout2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `subscribeall`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `custom_params`, `active`) - VALUES (:user2, :exclude, :delete1, :delete2, :timeout1, :timeout2, :automap, :skipcrossduplicates, :maxbytespersecond, :subscribeall, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :custom_params, :active)"); - $stmt->execute(array( - ':user2' => $username, - ':custom_params' => $custom_params, - ':exclude' => $exclude, - ':maxage' => $maxage, - ':delete1' => $delete1, - ':delete2' => $delete2, - ':timeout1' => $timeout1, - ':timeout2' => $timeout2, - ':automap' => $automap, - ':skipcrossduplicates' => $skipcrossduplicates, - ':maxbytespersecond' => $maxbytespersecond, - ':subscribeall' => $subscribeall, - ':subfolder2' => $subfolder2, - ':host1' => $host1, - ':authmech1' => 'PLAIN', - ':user1' => $user1, - ':password1' => $password1, - ':mins_interval' => $mins_interval, - ':port1' => $port1, - ':enc1' => $enc1, - ':delete2duplicates' => $delete2duplicates, - ':active' => $active, - )); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } - $_SESSION['return'] = array( + $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `timeout1`, `timeout2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `subscribeall`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `custom_params`, `active`) + VALUES (:user2, :exclude, :delete1, :delete2, :timeout1, :timeout2, :automap, :skipcrossduplicates, :maxbytespersecond, :subscribeall, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :custom_params, :active)"); + $stmt->execute(array( + ':user2' => $username, + ':custom_params' => $custom_params, + ':exclude' => $exclude, + ':maxage' => $maxage, + ':delete1' => $delete1, + ':delete2' => $delete2, + ':timeout1' => $timeout1, + ':timeout2' => $timeout2, + ':automap' => $automap, + ':skipcrossduplicates' => $skipcrossduplicates, + ':maxbytespersecond' => $maxbytespersecond, + ':subscribeall' => $subscribeall, + ':subfolder2' => $subfolder2, + ':host1' => $host1, + ':authmech1' => 'PLAIN', + ':user1' => $user1, + ':password1' => $password1, + ':mins_interval' => $mins_interval, + ':port1' => $port1, + ':enc1' => $enc1, + ':delete2duplicates' => $delete2duplicates, + ':active' => $active, + )); + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_modified', $username) @@ -375,7 +315,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { break; case 'domain': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -390,7 +330,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $restart_sogo = $_data['restart_sogo']; $quota = $_data['quota']; if ($maxquota > $quota) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'mailbox_quota_exceeds_domain_quota' @@ -398,7 +338,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if ($maxquota == "0" || empty($maxquota)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'maxquota_empty' @@ -410,7 +350,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $backupmx = intval($_data['backupmx']); ($relay_all_recipients == 1) ? $backupmx = '1' : null; if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_invalid' @@ -419,7 +359,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach (array($quota, $maxquota, $mailboxes, $aliases) as $data) { if (!is_numeric($data)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('object_is_not_numeric', htmlspecialchars($data)) @@ -427,26 +367,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } } - try { - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` - WHERE `domain` = :domain"); - $stmt->execute(array(':domain' => $domain)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` - WHERE `alias_domain` = :domain"); - $stmt->execute(array(':domain' => $domain)); - $num_results = $num_results + count($stmt->fetchAll(PDO::FETCH_ASSOC)); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` + WHERE `domain` = :domain"); + $stmt->execute(array(':domain' => $domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` + WHERE `alias_domain` = :domain"); + $stmt->execute(array(':domain' => $domain)); + $num_results = $num_results + count($stmt->fetchAll(PDO::FETCH_ASSOC)); if ($num_results != 0) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('domain_exists', htmlspecialchars($domain)) @@ -454,65 +384,62 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if ($domain == getenv('MAILCOW_HOSTNAME')) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_cannot_match_hostname' ); return false; } + $stmt = $pdo->prepare("INSERT INTO `domain` (`domain`, `description`, `aliases`, `mailboxes`, `maxquota`, `quota`, `backupmx`, `active`, `relay_all_recipients`) + VALUES (:domain, :description, :aliases, :mailboxes, :maxquota, :quota, :backupmx, :active, :relay_all_recipients)"); + $stmt->execute(array( + ':domain' => $domain, + ':description' => $description, + ':aliases' => $aliases, + ':mailboxes' => $mailboxes, + ':maxquota' => $maxquota, + ':quota' => $quota, + ':backupmx' => $backupmx, + ':active' => $active, + ':relay_all_recipients' => $relay_all_recipients + )); try { - $stmt = $pdo->prepare("INSERT INTO `domain` (`domain`, `description`, `aliases`, `mailboxes`, `maxquota`, `quota`, `backupmx`, `active`, `relay_all_recipients`) - VALUES (:domain, :description, :aliases, :mailboxes, :maxquota, :quota, :backupmx, :active, :relay_all_recipients)"); - $stmt->execute(array( - ':domain' => $domain, - ':description' => $description, - ':aliases' => $aliases, - ':mailboxes' => $mailboxes, - ':maxquota' => $maxquota, - ':quota' => $quota, - ':backupmx' => $backupmx, - ':active' => $active, - ':relay_all_recipients' => $relay_all_recipients - )); - try { - $redis->hSet('DOMAIN_MAP', $domain, 1); - } - catch (RedisException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('redis_error', $e) - ); - return false; - } - if (!empty($restart_sogo)) { - $restart_reponse = json_decode(docker('post', 'sogo-mailcow', 'restart'), true); - if ($restart_reponse['type'] == "success") { - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_added', htmlspecialchars($domain)) - ); - } - else { - $_SESSION['return'] = array( - 'type' => 'warning', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'domain_added_sogo_failed' - ); - } - } + $redis->hSet('DOMAIN_MAP', $domain, 1); } - catch (PDOException $e) { - mailbox('delete', 'domain', array('domain' => $domain)); - $_SESSION['return'] = array( + catch (RedisException $e) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('redis_error', $e) ); return false; } + if (!empty($restart_sogo)) { + $restart_reponse = json_decode(docker('post', 'sogo-mailcow', 'restart'), true); + if ($restart_reponse['type'] == "success") { + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('domain_added', htmlspecialchars($domain)) + ); + return true; + } + else { + $_SESSION['return'][] = array( + 'type' => 'warning', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'domain_added_sogo_failed' + ); + return false; + } + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('domain_added', htmlspecialchars($domain)) + ); + return true; break; case 'alias': $addresses = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['address'])); @@ -522,7 +449,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $goto_spam = intval($_data['goto_spam']); $goto_ham = intval($_data['goto_ham']); if (empty($addresses[0])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'alias_empty' @@ -530,7 +457,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (empty($gotos[0]) && ($goto_null + $goto_spam + $goto_ham == 0)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'goto_empty' @@ -547,7 +474,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $goto = "ham@localhost"; } else { - foreach ($gotos as &$goto) { + foreach ($gotos as $i => &$goto) { if (empty($goto)) { continue; } @@ -560,23 +487,26 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $stmt->execute(array(':goto' => $goto)); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); if ($num_results != 0) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'goto_invalid' + 'msg' => array('goto_invalid', htmlspecialchars($goto)) ); - return false; + unset($gotos[$i]); + continue; } if (!filter_var($goto, FILTER_VALIDATE_EMAIL) === true) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'goto_invalid' + 'msg' => array('goto_invalid', htmlspecialchars($goto)) ); - return false; + unset($gotos[$i]); + continue; } } $gotos = array_filter($gotos); + if (empty($gotos)) { return false; } $goto = implode(",", $gotos); } foreach ($addresses as $address) { @@ -589,6 +519,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $domain = idn_to_ascii(substr(strstr($address, '@'), 1)); $local_part = strstr($address, '@', true); $address = $local_part.'@'.$domain; + $domaindata = mailbox('get', 'domain_details', $domain); + if (is_array($domaindata) && $domaindata['aliases_left'] == "0") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'max_alias_exceeded' + ); + return false; + } $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `address`= :address OR `address` IN ( SELECT `username` FROM `mailbox`, `alias_domain` @@ -602,70 +541,39 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { )); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); if ($num_results != 0) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('is_alias_or_mailbox', htmlspecialchars($address)) ); return false; } - $domaindata = mailbox('get', 'domain_details', $domain); - if (is_array($domaindata) && $domaindata['aliases_left'] == "0") { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` + WHERE `domain`= :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2)"); + $stmt->execute(array(':domain1' => $domain, ':domain2' => $domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results == 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'max_alias_exceeded' + 'msg' => array('domain_not_found', htmlspecialchars($domain)) ); return false; } - try { - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` - WHERE `domain`= :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2)"); - $stmt->execute(array(':domain1' => $domain, ':domain2' => $domain)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_not_found', htmlspecialchars($domain)) - ); - return false; - } - $stmt = $pdo->prepare("SELECT `address` FROM `alias` - WHERE `address`= :address"); - $stmt->execute(array(':address' => $address)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('is_alias_or_mailbox', htmlspecialchars($address)) - ); - return false; - } - $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` - WHERE `address`= :address"); - $stmt->execute(array(':address' => $address)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('is_spam_alias', htmlspecialchars($address)) - ); - return false; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` + WHERE `address`= :address"); + $stmt->execute(array(':address' => $address)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('is_spam_alias', htmlspecialchars($address)) ); return false; } if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'alias_invalid' @@ -673,60 +581,45 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); return false; } - try { - $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `active`) - VALUES (:address, :goto, :domain, :active)"); - if (!filter_var($address, FILTER_VALIDATE_EMAIL) === true) { - $stmt->execute(array( - ':address' => '@'.$domain, - ':goto' => $goto, - ':domain' => $domain, - ':active' => $active - )); - } - else { - $stmt->execute(array( - ':address' => $address, - ':goto' => $goto, - ':domain' => $domain, - ':active' => $active - )); - } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'alias_added' - ); + $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `active`) + VALUES (:address, :goto, :domain, :active)"); + if (!filter_var($address, FILTER_VALIDATE_EMAIL) === true) { + $stmt->execute(array( + ':address' => '@'.$domain, + ':goto' => $goto, + ':domain' => $domain, + ':active' => $active + )); } - catch (PDOException $e) { - mailbox('delete', 'alias', array('address' => $address)); - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + else { + $stmt->execute(array( + ':address' => $address, + ':goto' => $goto, + ':domain' => $domain, + ':active' => $active + )); } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('alias_added', $address) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'alias_added' - ); break; case 'alias_domain': $active = intval($_data['active']); $alias_domains = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['alias_domain'])); + $alias_domains = array_filter($alias_domains); $target_domain = idn_to_ascii(strtolower(trim($_data['target_domain']))); if (!is_valid_domain_name($target_domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'target_domain_invalid' @@ -734,100 +627,79 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $target_domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); return false; } - foreach ($alias_domains as $alias_domain) { + foreach ($alias_domains as $i => &$alias_domain) { $alias_domain = idn_to_ascii(strtolower(trim($alias_domain))); if (!is_valid_domain_name($alias_domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'alias_domain_invalid' + 'msg' => array('alias_domain_invalid', htmlspecialchars(alias_domain)) ); - return false; + continue; } if ($alias_domain == $target_domain) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'aliasd_targetd_identical' - ); - return false; - } - try { - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` - WHERE `domain`= :target_domain"); - $stmt->execute(array(':target_domain' => $target_domain)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'targetd_not_found' - ); - return false; - } - $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `alias_domain`= :alias_domain - UNION - SELECT `domain` FROM `domain` WHERE `domain`= :alias_domain_in_domain"); - $stmt->execute(array(':alias_domain' => $alias_domain, ':alias_domain_in_domain' => $alias_domain)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'alias_domain_invalid' - ); - return false; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('aliasd_targetd_identical', htmlspecialchars($target_domain)) ); - return false; - } - try { - $stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `active`) - VALUES (:alias_domain, :target_domain, :active)"); - $stmt->execute(array( - ':alias_domain' => $alias_domain, - ':target_domain' => $target_domain, - ':active' => $active - )); + continue; } - catch (PDOException $e) { - mailbox('delete', 'alias_domain', array('alias_domain' => $alias_domain)); - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` + WHERE `domain`= :target_domain"); + $stmt->execute(array(':target_domain' => $target_domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results == 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('targetd_not_found', htmlspecialchars($target_domain)) ); - return false; - } - try { - $redis->hSet('DOMAIN_MAP', $alias_domain, 1); + continue; } - catch (RedisException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `alias_domain`= :alias_domain + UNION + SELECT `domain` FROM `domain` WHERE `domain`= :alias_domain_in_domain"); + $stmt->execute(array(':alias_domain' => $alias_domain, ':alias_domain_in_domain' => $alias_domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('redis_error', $e) + 'msg' => array('alias_domain_invalid', $alias_domain) ); - return false; + continue; } } - $_SESSION['return'] = array( + $stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `active`) + VALUES (:alias_domain, :target_domain, :active)"); + $stmt->execute(array( + ':alias_domain' => $alias_domain, + ':target_domain' => $target_domain, + ':active' => $active + )); + try { + $redis->hSet('DOMAIN_MAP', $alias_domain, 1); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('redis_error', $e) + ); + return false; + } + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('aliasd_added', htmlspecialchars(implode(', ', $alias_domains))) + 'msg' => array('aliasd_added', htmlspecialchars($alias_domain)) ); break; case 'mailbox': @@ -835,7 +707,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $domain = idn_to_ascii(strtolower(trim($_data['domain']))); $username = $local_part . '@' . $domain; if (!filter_var($username, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'mailbox_invalid' @@ -843,7 +715,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (empty($_data['local_part'])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'mailbox_invalid' @@ -861,7 +733,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $quota_b = ($quota_m * 1048576); $maildir = $domain . "/" . $local_part . "/"; if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_invalid' @@ -869,81 +741,71 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); return false; } - try { - $stmt = $pdo->prepare("SELECT `mailboxes`, `maxquota`, `quota` FROM `domain` - WHERE `domain` = :domain"); - $stmt->execute(array(':domain' => $domain)); - $DomainData = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt = $pdo->prepare("SELECT - COUNT(*) as count, - COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota` - FROM `mailbox` - WHERE `kind` NOT REGEXP 'location|thing|group' - AND `domain` = :domain"); - $stmt->execute(array(':domain' => $domain)); - $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt = $pdo->prepare("SELECT `local_part` FROM `mailbox` WHERE `local_part` = :local_part and `domain`= :domain"); - $stmt->execute(array(':local_part' => $local_part, ':domain' => $domain)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('object_exists', htmlspecialchars($username)) - ); - return false; - } - $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE address= :username"); - $stmt->execute(array(':username' => $username)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('is_alias', htmlspecialchars($username)) - ); - return false; - } - $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` WHERE `address`= :username"); - $stmt->execute(array(':username' => $username)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('is_spam_alias', htmlspecialchars($username)) - ); - return false; - } - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` WHERE `domain`= :domain"); - $stmt->execute(array(':domain' => $domain)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_not_found', htmlspecialchars($domain)) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `mailboxes`, `maxquota`, `quota` FROM `domain` + WHERE `domain` = :domain"); + $stmt->execute(array(':domain' => $domain)); + $DomainData = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt = $pdo->prepare("SELECT + COUNT(*) as count, + COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota` + FROM `mailbox` + WHERE `kind` NOT REGEXP 'location|thing|group' + AND `domain` = :domain"); + $stmt->execute(array(':domain' => $domain)); + $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt = $pdo->prepare("SELECT `local_part` FROM `mailbox` WHERE `local_part` = :local_part and `domain`= :domain"); + $stmt->execute(array(':local_part' => $local_part, ':domain' => $domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('object_exists', htmlspecialchars($username)) + ); + return false; + } + $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE address= :username"); + $stmt->execute(array(':username' => $username)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('is_alias', htmlspecialchars($username)) + ); + return false; + } + $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` WHERE `address`= :username"); + $stmt->execute(array(':username' => $username)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('is_spam_alias', htmlspecialchars($username)) + ); + return false; } - catch(PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` WHERE `domain`= :domain"); + $stmt->execute(array(':domain' => $domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results == 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('domain_not_found', htmlspecialchars($domain)) ); return false; } if (!is_numeric($quota_m) || $quota_m == "0") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'quota_not_0_not_numeric' @@ -952,7 +814,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } if (!empty($password) && !empty($password2)) { if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'password_complexity' @@ -960,7 +822,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if ($password != $password2) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'password_mismatch' @@ -970,7 +832,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $password_hashed = hash_password($password); } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'password_empty' @@ -978,7 +840,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if ($MailboxData['count'] >= $DomainData['mailboxes']) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('max_mailbox_exceeded', $MailboxData['count'], $DomainData['mailboxes']) @@ -986,7 +848,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if ($quota_m > $DomainData['maxquota']) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_quota_exceeded', $DomainData['maxquota']) @@ -995,56 +857,45 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } if (($MailboxData['quota'] + $quota_m) > $DomainData['quota']) { $quota_left_m = ($DomainData['quota'] - $MailboxData['quota']); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_quota_left_exceeded', $quota_left_m) ); return false; } - try { - $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `attributes`, `active`) - VALUES (:username, :password_hashed, :name, :maildir, :quota_b, :local_part, :domain, '{\"force_pw_update\": \"0\", \"tls_enforce_in\": \"0\", \"tls_enforce_out\": \"0\"}', :active)"); - $stmt->execute(array( - ':username' => $username, - ':password_hashed' => $password_hashed, - ':name' => $name, - ':maildir' => $maildir, - ':quota_b' => $quota_b, - ':local_part' => $local_part, - ':domain' => $domain, - ':active' => $active - )); - $stmt = $pdo->prepare("INSERT INTO `quota2` (`username`, `bytes`, `messages`) - VALUES (:username, '0', '0') ON DUPLICATE KEY UPDATE `bytes` = '0', `messages` = '0';"); - $stmt->execute(array(':username' => $username)); - $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `active`) - VALUES (:username1, :username2, :domain, :active)"); - $stmt->execute(array( - ':username1' => $username, - ':username2' => $username, - ':domain' => $domain, - ':active' => $active - )); - $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)"); - $stmt->execute(array( - ':username' => $username - )); - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_added', htmlspecialchars($username)) - ); - } - catch (PDOException $e) { - mailbox('delete', 'mailbox', array('username' => $username)); - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `attributes`, `active`) + VALUES (:username, :password_hashed, :name, :maildir, :quota_b, :local_part, :domain, '{\"force_pw_update\": \"0\", \"tls_enforce_in\": \"0\", \"tls_enforce_out\": \"0\"}', :active)"); + $stmt->execute(array( + ':username' => $username, + ':password_hashed' => $password_hashed, + ':name' => $name, + ':maildir' => $maildir, + ':quota_b' => $quota_b, + ':local_part' => $local_part, + ':domain' => $domain, + ':active' => $active + )); + $stmt = $pdo->prepare("INSERT INTO `quota2` (`username`, `bytes`, `messages`) + VALUES (:username, '0', '0') ON DUPLICATE KEY UPDATE `bytes` = '0', `messages` = '0';"); + $stmt->execute(array(':username' => $username)); + $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `active`) + VALUES (:username1, :username2, :domain, :active)"); + $stmt->execute(array( + ':username1' => $username, + ':username2' => $username, + ':domain' => $domain, + ':active' => $active + )); + $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)"); + $stmt->execute(array( + ':username' => $username + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_added', htmlspecialchars($username)) + ); break; case 'resource': $domain = idn_to_ascii(strtolower(trim($_data['domain']))); @@ -1055,7 +906,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $multiple_bookings = intval($_data['multiple_bookings']); $active = intval($_data['active']); if (!filter_var($name, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'resource_invalid' @@ -1063,7 +914,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (empty($description)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'description_invalid' @@ -1074,7 +925,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $multiple_bookings = -1; } if ($kind != 'location' && $kind != 'group' && $kind != 'thing') { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'resource_invalid' @@ -1082,7 +933,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_invalid' @@ -1090,94 +941,73 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); return false; } - try { - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :name"); - $stmt->execute(array(':name' => $name)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('object_exists', htmlspecialchars($name)) - ); - return false; - } - $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE address= :name"); - $stmt->execute(array(':name' => $name)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('is_alias', htmlspecialchars($name)) - ); - return false; - } - $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` WHERE `address`= :name"); - $stmt->execute(array(':name' => $name)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('is_spam_alias', htmlspecialchars($name)) - ); - return false; - } - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` WHERE `domain`= :domain"); - $stmt->execute(array(':domain' => $domain)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_not_found', htmlspecialchars($domain)) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :name"); + $stmt->execute(array(':name' => $name)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('object_exists', htmlspecialchars($name)) + ); + return false; } - catch(PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE address= :name"); + $stmt->execute(array(':name' => $name)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('is_alias', htmlspecialchars($name)) ); return false; } - try { - $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `active`, `multiple_bookings`, `kind`) - VALUES (:name, 'RESOURCE', :description, 'RESOURCE', 0, :local_part, :domain, :active, :multiple_bookings, :kind)"); - $stmt->execute(array( - ':name' => $name, - ':description' => $description, - ':local_part' => $local_part, - ':domain' => $domain, - ':active' => $active, - ':kind' => $kind, - ':multiple_bookings' => $multiple_bookings - )); - $_SESSION['return'] = array( - 'type' => 'success', + $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` WHERE `address`= :name"); + $stmt->execute(array(':name' => $name)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( + 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('resource_added', htmlspecialchars($name)) + 'msg' => array('is_spam_alias', htmlspecialchars($name)) ); + return false; } - catch (PDOException $e) { - mailbox('delete', 'resource', array('name' => $name)); - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` WHERE `domain`= :domain"); + $stmt->execute(array(':domain' => $domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results == 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('domain_not_found', htmlspecialchars($domain)) ); return false; } + $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `active`, `multiple_bookings`, `kind`) + VALUES (:name, 'RESOURCE', :description, 'RESOURCE', 0, :local_part, :domain, :active, :multiple_bookings, :kind)"); + $stmt->execute(array( + ':name' => $name, + ':description' => $description, + ':local_part' => $local_part, + ':domain' => $domain, + ':active' => $active, + ':kind' => $kind, + ':multiple_bookings' => $multiple_bookings + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('resource_added', htmlspecialchars($name)) + ); break; } break; @@ -1193,62 +1023,52 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $target_domain = (!empty($_data['target_domain'])) ? idn_to_ascii(strtolower(trim($_data['target_domain']))) : $is_now['target_domain']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'alias_domain_invalid' + 'msg' => array('alias_domain_invalid', htmlspecialchars($alias_domain)) ); - return false; + continue; } if (!is_valid_domain_name($target_domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'target_domain_invalid' + 'msg' => array('target_domain_invalid', htmlspecialchars($target_domain)) ); - return false; + continue; } if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $target_domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (empty(mailbox('get', 'domain_details', $target_domain)) || !empty(mailbox('get', 'alias_domain_details', $target_domain))) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'target_domain_invalid' - ); - return false; - } - try { - $stmt = $pdo->prepare("UPDATE `alias_domain` SET - `target_domain` = :target_domain, - `active` = :active - WHERE `alias_domain` = :alias_domain"); - $stmt->execute(array( - ':alias_domain' => $alias_domain, - ':target_domain' => $target_domain, - ':active' => $active - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('target_domain_invalid', htmlspecialchars($target_domain)) ); - return false; + continue; } + $stmt = $pdo->prepare("UPDATE `alias_domain` SET + `target_domain` = :target_domain, + `active` = :active + WHERE `alias_domain` = :alias_domain"); + $stmt->execute(array( + ':alias_domain' => $alias_domain, + ':target_domain' => $target_domain, + ':active' => $active + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('aliasd_modified', htmlspecialchars($alias_domain)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('aliasd_modified', htmlspecialchars(implode(', ', $alias_domains))) - ); break; case 'tls_policy': if (!is_array($_data['username'])) { @@ -1259,7 +1079,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $usernames = $_data['username']; } if (!isset($_SESSION['acl']['tls_policy']) || $_SESSION['acl']['tls_policy'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -1268,12 +1088,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($usernames as $username) { if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } $is_now = mailbox('get', 'tls_policy', $username); if (!empty($is_now)) { @@ -1281,35 +1101,28 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $tls_enforce_out = (isset($_data['tls_enforce_out'])) ? intval($_data['tls_enforce_out']) : $is_now['tls_enforce_out']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', :tls_out), `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', :tls_in) WHERE `username` = :username"); - $stmt->execute(array( - ':tls_out' => intval($tls_enforce_out), - ':tls_in' => intval($tls_enforce_in), - ':username' => $username - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("UPDATE `mailbox` + SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', :tls_out), + `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', :tls_in) + WHERE `username` = :username"); + $stmt->execute(array( + ':tls_out' => intval($tls_enforce_out), + ':tls_in' => intval($tls_enforce_in), + ':username' => $username + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', $username) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_modified', implode(', ', $usernames)) - ); break; case 'spam_score': if (!is_array($_data['username'])) { @@ -1320,7 +1133,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $usernames = $_data['username']; } if (!isset($_SESSION['acl']['spam_score']) || $_SESSION['acl']['spam_score'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -1331,55 +1144,40 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $lowspamlevel = explode(',', $_data['spam_score'])[0]; $highspamlevel = explode(',', $_data['spam_score'])[1]; if (!is_numeric($lowspamlevel) || !is_numeric($highspamlevel)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username - AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`) - VALUES (:username, 'highspamlevel', :highspamlevel)"); - $stmt->execute(array( - ':username' => $username, - ':highspamlevel' => $highspamlevel - )); - $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`) - VALUES (:username, 'lowspamlevel', :lowspamlevel)"); - $stmt->execute(array( - ':username' => $username, - ':lowspamlevel' => $lowspamlevel - )); - } - catch (PDOException $e) { - $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username - AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')"); - $stmt->execute(array( - ':username' => $username - )); - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username + AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`) + VALUES (:username, 'highspamlevel', :highspamlevel)"); + $stmt->execute(array( + ':username' => $username, + ':highspamlevel' => $highspamlevel + )); + $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`) + VALUES (:username, 'lowspamlevel', :lowspamlevel)"); + $stmt->execute(array( + ':username' => $username, + ':lowspamlevel' => $lowspamlevel + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', $username) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_modified', implode(', ', $usernames)) - ); break; case 'time_limited_alias': if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -1394,50 +1192,30 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $addresses = $_data['address']; } foreach ($addresses as $address) { - try { - $stmt = $pdo->prepare("SELECT `goto` FROM `spamalias` WHERE `address` = :address"); - $stmt->execute(array(':address' => $address)); - $goto = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `goto` FROM `spamalias` WHERE `address` = :address"); + $stmt->execute(array(':address' => $address)); + $goto = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $goto)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = (`validity` + 3600) WHERE - `address` = :address AND - `validity` >= :validity"); - $stmt->execute(array( - ':address' => $address, - ':validity' => time() - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = (`validity` + 3600) WHERE + `address` = :address AND + `validity` >= :validity"); + $stmt->execute(array( + ':address' => $address, + ':validity' => time() + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', htmlspecialchars(implode(', ', $usernames))) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_modified', htmlspecialchars(implode(', ', $usernames))) - ); break; case 'delimiter_action': if (!is_array($_data['username'])) { @@ -1448,7 +1226,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $usernames = $_data['username']; } if (!isset($_SESSION['acl']['delimiter_action']) || $_SESSION['acl']['delimiter_action'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -1457,12 +1235,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($usernames as $username) { if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (isset($_data['tagged_mail_handler']) && $_data['tagged_mail_handler'] == "subject") { try { @@ -1470,12 +1248,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $redis->hDel('RCPT_WANTS_SUBFOLDER_TAG', $username); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) ); - return false; + continue; } } else if (isset($_data['tagged_mail_handler']) && $_data['tagged_mail_handler'] == "subfolder") { @@ -1484,12 +1262,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $redis->hDel('RCPT_WANTS_SUBJECT_TAG', $username); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) ); - return false; + continue; } } else { @@ -1498,32 +1276,22 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $redis->hDel('RCPT_WANTS_SUBFOLDER_TAG', $username); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) ); - return false; + continue; } } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', $username) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_modified', implode(', ', $usernames)) - ); break; case 'ratelimit': - $rl_value = intval($_data['rl_value']); - $rl_frame = $_data['rl_frame']; - if (!in_array($rl_frame, array('s', 'm', 'h'))) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'rl_timeframe' - ); - return false; - } if (!is_array($_data['object'])) { $objects = array(); $objects[] = $_data['object']; @@ -1532,40 +1300,55 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $objects = $_data['object']; } foreach ($objects as $object) { + $rl_value = intval($_data['rl_value']); + $rl_frame = $_data['rl_frame']; + if (!in_array($rl_frame, array('s', 'm', 'h'))) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'rl_timeframe' + ); + continue; + } if (is_valid_domain_name($object)) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } } elseif (filter_var($object, FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } } else { - return false; + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + continue; } if (empty($rl_value)) { try { $redis->hDel('RL_VALUE', $object); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) ); - return false; + continue; } } else { @@ -1573,20 +1356,20 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $redis->hSet('RL_VALUE', $object, $rl_value . ' / 1' . $rl_frame); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) ); - return false; + continue; } } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('object_modified', $object) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_modified', implode(', ', $objects)) - ); break; case 'syncjob': if (!is_array($_data['id'])) { @@ -1597,7 +1380,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $ids = $_data['id']; } if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -1631,12 +1414,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $timeout2 = (isset($_data['timeout2']) && $_data['timeout2'] != "") ? intval($_data['timeout2']) : $is_now['timeout2']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (empty($subfolder2)) { $subfolder2 = ""; @@ -1654,107 +1437,97 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $maxbytespersecond = "0"; } if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (!filter_var($mins_interval, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 3600)))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (!is_valid_domain_name($host1)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if ($enc1 != "TLS" && $enc1 != "SSL" && $enc1 != "PLAIN") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (@preg_match("/" . $exclude . "/", null) === false) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("UPDATE `imapsync` SET `delete1` = :delete1, - `delete2` = :delete2, - `automap` = :automap, - `skipcrossduplicates` = :skipcrossduplicates, - `maxage` = :maxage, - `maxbytespersecond` = :maxbytespersecond, - `subfolder2` = :subfolder2, - `exclude` = :exclude, - `host1` = :host1, - `last_run` = :last_run, - `user1` = :user1, - `password1` = :password1, - `mins_interval` = :mins_interval, - `port1` = :port1, - `enc1` = :enc1, - `delete2duplicates` = :delete2duplicates, - `custom_params` = :custom_params, - `timeout1` = :timeout1, - `timeout2` = :timeout2, - `subscribeall` = :subscribeall, - `active` = :active - WHERE `id` = :id"); - $stmt->execute(array( - ':delete1' => $delete1, - ':delete2' => $delete2, - ':automap' => $automap, - ':skipcrossduplicates' => $skipcrossduplicates, - ':id' => $id, - ':exclude' => $exclude, - ':maxage' => $maxage, - ':maxbytespersecond' => $maxbytespersecond, - ':subfolder2' => $subfolder2, - ':host1' => $host1, - ':user1' => $user1, - ':password1' => $password1, - ':last_run' => $last_run, - ':mins_interval' => $mins_interval, - ':port1' => $port1, - ':enc1' => $enc1, - ':delete2duplicates' => $delete2duplicates, - ':custom_params' => $custom_params, - ':timeout1' => $timeout1, - ':timeout2' => $timeout2, - ':subscribeall' => $subscribeall, - ':active' => $active, - )); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("UPDATE `imapsync` SET `delete1` = :delete1, + `delete2` = :delete2, + `automap` = :automap, + `skipcrossduplicates` = :skipcrossduplicates, + `maxage` = :maxage, + `maxbytespersecond` = :maxbytespersecond, + `subfolder2` = :subfolder2, + `exclude` = :exclude, + `host1` = :host1, + `last_run` = :last_run, + `user1` = :user1, + `password1` = :password1, + `mins_interval` = :mins_interval, + `port1` = :port1, + `enc1` = :enc1, + `delete2duplicates` = :delete2duplicates, + `custom_params` = :custom_params, + `timeout1` = :timeout1, + `timeout2` = :timeout2, + `subscribeall` = :subscribeall, + `active` = :active + WHERE `id` = :id"); + $stmt->execute(array( + ':delete1' => $delete1, + ':delete2' => $delete2, + ':automap' => $automap, + ':skipcrossduplicates' => $skipcrossduplicates, + ':id' => $id, + ':exclude' => $exclude, + ':maxage' => $maxage, + ':maxbytespersecond' => $maxbytespersecond, + ':subfolder2' => $subfolder2, + ':host1' => $host1, + ':user1' => $user1, + ':password1' => $password1, + ':last_run' => $last_run, + ':mins_interval' => $mins_interval, + ':port1' => $port1, + ':enc1' => $enc1, + ':delete2duplicates' => $delete2duplicates, + ':custom_params' => $custom_params, + ':timeout1' => $timeout1, + ':timeout2' => $timeout2, + ':subscribeall' => $subscribeall, + ':active' => $active, + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', $username) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_modified', $username) - ); break; case 'filter': $sieve = new Sieve\SieveParser(); @@ -1766,7 +1539,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $ids = $_data['id']; } if (!isset($_SESSION['acl']['filters']) || $_SESSION['acl']['filters'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -1783,103 +1556,152 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $filter_type = (!empty($_data['filter_type'])) ? $_data['filter_type'] : $is_now['filter_type']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } try { $sieve->parse($script_data); } catch (Exception $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('sieve_error', $e->getMessage()) ); - return false; + continue; } if ($filter_type != 'postfilter' && $filter_type != 'prefilter') { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'filter_type' ); - return false; + continue; } if ($active == '1') { $script_name = 'active'; - try { - $stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_name` = 'inactive' WHERE `username` = :username AND `filter_type` = :filter_type"); - $stmt->execute(array( - ':username' => $username, - ':filter_type' => $filter_type - )); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } - } - else { - $script_name = 'inactive'; - } - try { - $stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_desc` = :script_desc, `script_data` = :script_data, `script_name` = :script_name, `filter_type` = :filter_type - WHERE `id` = :id"); + $stmt = $pdo->prepare("UPDATE `sieve_filters` + SET `script_name` = 'inactive' + WHERE `username` = :username + AND `filter_type` = :filter_type"); $stmt->execute(array( - ':script_desc' => $script_desc, - ':script_data' => $script_data, - ':script_name' => $script_name, - ':filter_type' => $filter_type, - ':id' => $id + ':username' => $username, + ':filter_type' => $filter_type )); } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + else { + $script_name = 'inactive'; } + $stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_desc` = :script_desc, `script_data` = :script_data, `script_name` = :script_name, `filter_type` = :filter_type + WHERE `id` = :id"); + $stmt->execute(array( + ':script_desc' => $script_desc, + ':script_data' => $script_data, + ':script_name' => $script_name, + ':filter_type' => $filter_type, + ':id' => $id + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', $username) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_modified', $username) - ); break; case 'alias': - if (!is_array($_data['address'])) { - $addresses = array(); - $addresses[] = $_data['address']; + if (!is_array($_data['id'])) { + $ids = array(); + $ids[] = $_data['id']; } else { - $addresses = $_data['address']; + $ids = $_data['id']; } - foreach ($addresses as $address) { - $is_now = mailbox('get', 'alias_details', $address); + foreach ($ids as $id) { + $is_now = mailbox('get', 'alias_details', $id); if (!empty($is_now)) { $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int']; - $goto_null = (isset($_data['goto_null'])) ? intval($_data['goto_null']) : $is_now['goto_null']; - $goto_spam = (isset($_data['goto_spam'])) ? intval($_data['goto_spam']) : $is_now['goto_spam']; - $goto_ham = (isset($_data['goto_ham'])) ? intval($_data['goto_ham']) : $is_now['goto_ham']; - $goto = (!empty($_data['goto'])) ? $_data['goto'] : $is_now['goto']; + $goto_null = (isset($_data['goto_null'])) ? intval($_data['goto_null']) : 0; + $goto_spam = (isset($_data['goto_spam'])) ? intval($_data['goto_spam']) : 0; + $goto_ham = (isset($_data['goto_ham'])) ? intval($_data['goto_ham']) : 0; + $goto = (!empty($_data['goto'])) ? $_data['goto'] : $is_now['goto']; + $address = (!empty($_data['address'])) ? $_data['address'] : $is_now['address']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'alias_invalid' ); - return false; + continue; + } + if ($is_now['address'] != $address) { + $domain = idn_to_ascii(substr(strstr($address, '@'), 1)); + $local_part = strstr($address, '@', true); + $address = $local_part.'@'.$domain; + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + continue; + } + if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'alias_invalid' + ); + continue; + } + $stmt = $pdo->prepare("SELECT `address` FROM `alias` + WHERE `address`= :address OR `address` IN ( + SELECT `username` FROM `mailbox`, `alias_domain` + WHERE ( + `alias_domain`.`alias_domain` = :address_d + AND `mailbox`.`username` = CONCAT(:address_l, '@', alias_domain.target_domain)))"); + $stmt->execute(array( + ':address' => $address, + ':address_l' => $local_part, + ':address_d' => $domain + )); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('is_alias_or_mailbox', htmlspecialchars($address)) + ); + continue; + } + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` + WHERE `domain`= :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2)"); + $stmt->execute(array(':domain1' => $domain, ':domain2' => $domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results == 0) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('domain_not_found', htmlspecialchars($domain)) + ); + continue; + } + $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` + WHERE `address`= :address"); + $stmt->execute(array(':address' => $address)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('is_spam_alias', htmlspecialchars($address)) + ); + continue; + } } if ($goto_null == "1") { $goto = "null@localhost"; @@ -1891,85 +1713,52 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $goto = "ham@localhost"; } else { - $gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto'])); - foreach ($gotos as &$goto) { + $gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $goto)); + foreach ($gotos as $i => &$goto) { if (empty($goto)) { continue; } if (!filter_var($goto, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' =>'goto_invalid' + 'msg' => array('goto_invalid', $goto) ); - return false; + unset($gotos[$i]); + continue; } if ($goto == $address) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'alias_goto_identical' ); - return false; + unset($gotos[$i]); + continue; } } $gotos = array_filter($gotos); $goto = implode(",", $gotos); } - $domain = idn_to_ascii(substr(strstr($address, '@'), 1)); - $local_part = strstr($address, '@', true); - if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - return false; - } - if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'alias_invalid' - ); - return false; - } - try { - if (!empty($goto)) { - $stmt = $pdo->prepare("UPDATE `alias` SET - `goto` = :goto, - `active`= :active - WHERE `address` = :address"); - $stmt->execute(array( - ':goto' => $goto, - ':active' => $active, - ':address' => $address - )); - } - else { - $stmt = $pdo->prepare("UPDATE `alias` SET - `active`= :active - WHERE `address` = :address"); - $stmt->execute(array( - ':active' => $active, - ':address' => $address - )); - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + if (!empty($goto)) { + $stmt = $pdo->prepare("UPDATE `alias` SET + `address` = :address, + `goto` = :goto, + `active`= :active + WHERE `id` = :id"); + $stmt->execute(array( + ':address' => $address, + ':goto' => $goto, + ':active' => $active, + ':id' => $id + )); } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('alias_modified', htmlspecialchars($address)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('alias_modified', htmlspecialchars(implode(', ', $addresses))) - ); break; case 'domain': if (!is_array($_data['domain'])) { @@ -1982,39 +1771,29 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { foreach ($domains as $domain) { $domain = idn_to_ascii($domain); if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_invalid' ); - return false; + continue; } if ($_SESSION['mailcow_cc_role'] == "domainadmin" && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { $description = $_data['description']; $active = intval($_data['active']); - try { - $stmt = $pdo->prepare("UPDATE `domain` SET - `description` = :description - WHERE `domain` = :domain"); - $stmt->execute(array( - ':description' => $description, - ':domain' => $domain - )); - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_modified', htmlspecialchars($domain)) - ); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("UPDATE `domain` SET + `description` = :description + WHERE `domain` = :domain"); + $stmt->execute(array( + ':description' => $description, + ':domain' => $domain + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('domain_modified', htmlspecialchars($domain)) + ); } elseif ($_SESSION['mailcow_cc_role'] == "admin") { $is_now = mailbox('get', 'domain_details', $domain); @@ -2031,129 +1810,109 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ($relay_all_recipients == '1') ? $backupmx = '1' : null; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_invalid' ); - return false; - } - try { - // todo: should be using api here - $stmt = $pdo->prepare("SELECT - COUNT(*) AS count, - MAX(COALESCE(ROUND(`quota`/1048576), 0)) AS `biggest_mailbox`, - COALESCE(ROUND(SUM(`quota`)/1048576), 0) AS `quota_all` - FROM `mailbox` - WHERE `kind` NOT REGEXP 'location|thing|group' - AND domain = :domain"); - $stmt->execute(array(':domain' => $domain)); - $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC); - // todo: should be using api here - $stmt = $pdo->prepare("SELECT COUNT(*) AS `count` FROM `alias` - WHERE domain = :domain - AND address NOT IN ( - SELECT `username` FROM `mailbox` - )"); - $stmt->execute(array(':domain' => $domain)); - $AliasData = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + // todo: should be using api here + $stmt = $pdo->prepare("SELECT + COUNT(*) AS count, + MAX(COALESCE(ROUND(`quota`/1048576), 0)) AS `biggest_mailbox`, + COALESCE(ROUND(SUM(`quota`)/1048576), 0) AS `quota_all` + FROM `mailbox` + WHERE `kind` NOT REGEXP 'location|thing|group' + AND domain = :domain"); + $stmt->execute(array(':domain' => $domain)); + $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC); + // todo: should be using api here + $stmt = $pdo->prepare("SELECT COUNT(*) AS `count` FROM `alias` + WHERE domain = :domain + AND address NOT IN ( + SELECT `username` FROM `mailbox` + )"); + $stmt->execute(array(':domain' => $domain)); + $AliasData = $stmt->fetch(PDO::FETCH_ASSOC); if ($maxquota > $quota) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'mailbox_quota_exceeds_domain_quota' ); - return false; + continue; } if ($maxquota == "0" || empty($maxquota)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'maxquota_empty' ); - return false; + continue; } if ($MailboxData['biggest_mailbox'] > $maxquota) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('max_quota_in_use', $MailboxData['biggest_mailbox']) ); - return false; + continue; } if ($MailboxData['quota_all'] > $quota) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('domain_quota_m_in_use', $MailboxData['quota_all']) ); - return false; + continue; } if ($MailboxData['count'] > $mailboxes) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailboxes_in_use', $MailboxData['count']) ); - return false; + continue; } if ($AliasData['count'] > $aliases) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('aliases_in_use', $AliasData['count']) ); - return false; - } - try { - $stmt = $pdo->prepare("UPDATE `domain` SET - `relay_all_recipients` = :relay_all_recipients, - `backupmx` = :backupmx, - `active` = :active, - `quota` = :quota, - `maxquota` = :maxquota, - `relayhost` = :relayhost, - `mailboxes` = :mailboxes, - `aliases` = :aliases, - `description` = :description - WHERE `domain` = :domain"); - $stmt->execute(array( - ':relay_all_recipients' => $relay_all_recipients, - ':backupmx' => $backupmx, - ':active' => $active, - ':quota' => $quota, - ':maxquota' => $maxquota, - ':relayhost' => $relayhost, - ':mailboxes' => $mailboxes, - ':aliases' => $aliases, - ':description' => $description, - ':domain' => $domain - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("UPDATE `domain` SET + `relay_all_recipients` = :relay_all_recipients, + `backupmx` = :backupmx, + `active` = :active, + `quota` = :quota, + `maxquota` = :maxquota, + `relayhost` = :relayhost, + `mailboxes` = :mailboxes, + `aliases` = :aliases, + `description` = :description + WHERE `domain` = :domain"); + $stmt->execute(array( + ':relay_all_recipients' => $relay_all_recipients, + ':backupmx' => $backupmx, + ':active' => $active, + ':quota' => $quota, + ':maxquota' => $maxquota, + ':relayhost' => $relayhost, + ':mailboxes' => $mailboxes, + ':aliases' => $aliases, + ':description' => $description, + ':domain' => $domain + )); } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('domain_modified', htmlspecialchars($domain)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_modified', htmlspecialchars(implode(', ', $domains))) - ); break; case 'mailbox': if (!is_array($_data['username'])) { @@ -2165,12 +1924,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($usernames as $username) { if (!filter_var($username, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'username_invalid' + 'msg' => array('username_invalid', $username) ); - return false; + continue; } $is_now = mailbox('get', 'mailbox_details', $username); if (!empty($is_now)) { @@ -2184,59 +1943,49 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $password2 = (!empty($_data['password2'])) ? $_data['password2'] : null; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("SELECT `quota`, `maxquota` - FROM `domain` - WHERE `domain` = :domain"); - $stmt->execute(array(':domain' => $domain)); - $DomainData = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("SELECT `quota`, `maxquota` + FROM `domain` + WHERE `domain` = :domain"); + $stmt->execute(array(':domain' => $domain)); + $DomainData = $stmt->fetch(PDO::FETCH_ASSOC); if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (!is_numeric($quota_m) || $quota_m == "0") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('quota_not_0_not_numeric', htmlspecialchars($quota_m)) ); - return false; + continue; } if ($quota_m > $DomainData['maxquota']) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_quota_exceeded', $DomainData['maxquota']) ); - return false; + continue; } if (((($is_now['quota_used'] / 1048576) - $quota_m) + $quota_m) > $DomainData['quota']) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_quota_left_exceeded', ($is_now['max_new_quota'] / 1048576)) ); - return false; + continue; } if (isset($_data['sender_acl'])) { // Get sender_acl items set by admin @@ -2256,7 +2005,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } else { if (array_search('default', $_data['sender_acl']) !== false){ - unset($_data['sender_acl'][array_search('defaaault', $_data['sender_acl'])]); + unset($_data['sender_acl'][array_search('default', $_data['sender_acl'])]); } $sender_acl_domain_admin = $_data['sender_acl']; } @@ -2265,47 +2014,60 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { foreach ($sender_acl_domain_admin as $key => $val) { // Check for invalid domain or email format or not * if (!filter_var($val, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name(ltrim($val, '@')) && $val != '*') { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key]) + ); unset($sender_acl_domain_admin[$key]); continue; } // Check if user has domain access (if object is domain) - $domain = ltrim($sender_acl, '@'); + $domain = ltrim($sender_acl_domain_admin[$key], '@'); if (is_valid_domain_name($domain)) { // Check for- and skip non-mailcow domains $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')); if (!empty($domains)) { if (!in_array($domain, $domains)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key]) + ); unset($sender_acl_domain_admin[$key]); continue; } } if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'sender_acl_invalid' + 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key]) ); - return false; + unset($sender_acl_domain_admin[$key]); + continue; } } // Wildcard can only be used if role == admin if ($val == '*' && $_SESSION['mailcow_cc_role'] != 'admin') { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'sender_acl_invalid' + 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key]) ); - return false; + unset($sender_acl_domain_admin[$key]); + continue; } // Check if user has mailbox access (if object is email) if (filter_var($val, FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $val)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'sender_acl_invalid' + 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key]) ); - return false; + unset($sender_acl_domain_admin[$key]); + continue; } } } @@ -2313,132 +2075,82 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $sender_acl_merged = array_merge($sender_acl_domain_admin, $sender_acl_admin); // If merged array still contains "*", set it as only value !in_array('*', $sender_acl_merged) ?: $sender_acl_merged = array('*'); - try { - $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username"); - $stmt->execute(array( - ':username' => $username - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username"); + $stmt->execute(array( + ':username' => $username + )); foreach ($sender_acl_merged as $sender_acl) { $domain = ltrim($sender_acl, '@'); if (is_valid_domain_name($domain)) { $sender_acl = '@' . $domain; } - try { - $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`) - VALUES (:sender_acl, :username)"); - $stmt->execute(array( - ':sender_acl' => $sender_acl, - ':username' => $username - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } - } - } - else { - try { - $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username"); + $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`) + VALUES (:sender_acl, :username)"); $stmt->execute(array( + ':sender_acl' => $sender_acl, ':username' => $username )); } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + } + else { + $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username"); + $stmt->execute(array( + ':username' => $username + )); } } if (!empty($password) && !empty($password2)) { if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'password_complexity' ); - return false; + continue; } if ($password != $password2) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'password_mismatch' ); - return false; + continue; } $password_hashed = hash_password($password); - try { - $stmt = $pdo->prepare("UPDATE `mailbox` SET - `password` = :password_hashed - WHERE `username` = :username"); - $stmt->execute(array( - ':password_hashed' => $password_hashed, - ':username' => $username - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } - } - try { - $stmt = $pdo->prepare("UPDATE `alias` SET - `active` = :active - WHERE `address` = :address"); - $stmt->execute(array( - ':address' => $username, - ':active' => $active - )); $stmt = $pdo->prepare("UPDATE `mailbox` SET - `active` = :active, - `name`= :name, - `quota` = :quota_b, - `attributes` = JSON_SET(`attributes`, '$.force_pw_update', :force_pw_update) + `password` = :password_hashed WHERE `username` = :username"); $stmt->execute(array( - ':active' => $active, - ':name' => $name, - ':quota_b' => $quota_b, - ':force_pw_update' => $force_pw_update, + ':password_hashed' => $password_hashed, ':username' => $username )); } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("UPDATE `alias` SET + `active` = :active + WHERE `address` = :address"); + $stmt->execute(array( + ':address' => $username, + ':active' => $active + )); + $stmt = $pdo->prepare("UPDATE `mailbox` SET + `active` = :active, + `name`= :name, + `quota` = :quota_b, + `attributes` = JSON_SET(`attributes`, '$.force_pw_update', :force_pw_update) + WHERE `username` = :username"); + $stmt->execute(array( + ':active' => $active, + ':name' => $name, + ':quota_b' => $quota_b, + ':force_pw_update' => $force_pw_update, + ':username' => $username + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', $username) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_modified', implode(', ', $usernames)) - ); break; case 'resource': if (!is_array($_data['name'])) { @@ -2457,77 +2169,67 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $kind = (!empty($_data['kind'])) ? $_data['kind'] : $is_now['kind']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'resource_invalid' + 'msg' => array('resource_invalid', htmlspecialchars($name)) ); - return false; + continue; } if (!filter_var($name, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'resource_invalid' + 'msg' => array('resource_invalid', htmlspecialchars($name)) ); - return false; + continue; } if (!isset($multiple_bookings) || $multiple_bookings < -1) { $multiple_bookings = -1; } if (empty($description)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'description_invalid' + 'msg' => array('description_invalid', htmlspecialchars($name)) ); - return false; + continue; } if ($kind != 'location' && $kind != 'group' && $kind != 'thing') { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'resource_invalid' + 'msg' => array('resource_invalid', htmlspecialchars($name)) ); - return false; + continue; } if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $name)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("UPDATE `mailbox` SET - `active` = :active, - `name`= :description, - `kind`= :kind, - `multiple_bookings`= :multiple_bookings - WHERE `username` = :name"); - $stmt->execute(array( - ':active' => $active, - ':description' => $description, - ':multiple_bookings' => $multiple_bookings, - ':kind' => $kind, - ':name' => $name - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("UPDATE `mailbox` SET + `active` = :active, + `name`= :description, + `kind`= :kind, + `multiple_bookings`= :multiple_bookings + WHERE `username` = :name"); + $stmt->execute(array( + ':active' => $active, + ':description' => $description, + ':multiple_bookings' => $multiple_bookings, + ':kind' => $kind, + ':name' => $name + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('resource_modified', htmlspecialchars($name)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('resource_modified', implode(', ', $names)) - ); break; } break; @@ -2544,108 +2246,98 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $data['sender_acl_addresses']['rw'] = array(); $data['sender_acl_addresses']['selectable'] = array(); $data['fixed_sender_aliases'] = array(); - try { - // Fixed addresses - $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` REGEXP :goto AND `address` NOT LIKE '@%'"); - $stmt->execute(array(':goto' => '(^|,)'.$_data.'($|,)')); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($rows)) { - $data['fixed_sender_aliases'][] = $row['address']; + // Fixed addresses + $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` REGEXP :goto AND `address` NOT LIKE '@%'"); + $stmt->execute(array(':goto' => '(^|,)'.$_data.'($|,)')); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($rows)) { + $data['fixed_sender_aliases'][] = $row['address']; + } + $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias_domain_alias` FROM `mailbox`, `alias_domain` + WHERE `alias_domain`.`target_domain` = `mailbox`.`domain` + AND `mailbox`.`username` = :username"); + $stmt->execute(array(':username' => $_data)); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($rows)) { + if (!empty($row['alias_domain_alias'])) { + $data['fixed_sender_aliases'][] = $row['alias_domain_alias']; + } + } + // Return array $data['sender_acl_domains/addresses']['ro'] with read-only objects + // Return array $data['sender_acl_domains/addresses']['rw'] with read-write objects (can be deleted) + $stmt = $pdo->prepare("SELECT REPLACE(`send_as`, '@', '') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND (`send_as` LIKE '@%' OR `send_as` = '*')"); + $stmt->execute(array(':logged_in_as' => $_data)); + $domain_rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($domain_row = array_shift($domain_rows)) { + if (is_valid_domain_name($domain_row['send_as']) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain_row['send_as'])) { + $data['sender_acl_domains']['ro'][] = $domain_row['send_as']; + continue; } - $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias_domain_alias` FROM `mailbox`, `alias_domain` - WHERE `alias_domain`.`target_domain` = `mailbox`.`domain` - AND `mailbox`.`username` = :username"); - $stmt->execute(array(':username' => $_data)); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($rows)) { - if (!empty($row['alias_domain_alias'])) { - $data['fixed_sender_aliases'][] = $row['alias_domain_alias']; - } + if (is_valid_domain_name($domain_row['send_as']) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain_row['send_as'])) { + $data['sender_acl_domains']['rw'][] = $domain_row['send_as']; + continue; } - // Return array $data['sender_acl_domains/addresses']['ro'] with read-only objects - // Return array $data['sender_acl_domains/addresses']['rw'] with read-write objects (can be deleted) - $stmt = $pdo->prepare("SELECT REPLACE(`send_as`, '@', '') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND (`send_as` LIKE '@%' OR `send_as` = '*')"); - $stmt->execute(array(':logged_in_as' => $_data)); - $domain_rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($domain_row = array_shift($domain_rows)) { - if (is_valid_domain_name($domain_row['send_as']) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain_row['send_as'])) { - $data['sender_acl_domains']['ro'][] = $domain_row['send_as']; - continue; - } - if (is_valid_domain_name($domain_row['send_as']) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain_row['send_as'])) { - $data['sender_acl_domains']['rw'][] = $domain_row['send_as']; - continue; - } - if ($domain_row['send_as'] == '*' && $_SESSION['mailcow_cc_role'] != 'admin') { - $data['sender_acl_domains']['ro'][] = $domain_row['send_as']; - } - if ($domain_row['send_as'] == '*' && $_SESSION['mailcow_cc_role'] == 'admin') { - $data['sender_acl_domains']['rw'][] = $domain_row['send_as']; - } + if ($domain_row['send_as'] == '*' && $_SESSION['mailcow_cc_role'] != 'admin') { + $data['sender_acl_domains']['ro'][] = $domain_row['send_as']; } - $stmt = $pdo->prepare("SELECT `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND (`send_as` NOT LIKE '@%' AND `send_as` != '*')"); - $stmt->execute(array(':logged_in_as' => $_data)); - $address_rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($address_row = array_shift($address_rows)) { - if (filter_var($address_row['send_as'], FILTER_VALIDATE_EMAIL) && !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $address_row['send_as'])) { - $data['sender_acl_addresses']['ro'][] = $address_row['send_as']; - continue; - } - if (filter_var($address_row['send_as'], FILTER_VALIDATE_EMAIL) && hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $address_row['send_as'])) { - $data['sender_acl_addresses']['rw'][] = $address_row['send_as']; - continue; - } + if ($domain_row['send_as'] == '*' && $_SESSION['mailcow_cc_role'] == 'admin') { + $data['sender_acl_domains']['rw'][] = $domain_row['send_as']; } - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` - WHERE `domain` NOT IN ( - SELECT REPLACE(`send_as`, '@', '') FROM `sender_acl` - WHERE `logged_in_as` = :logged_in_as1 - AND `send_as` LIKE '@%') - UNION - SELECT '*' FROM `domain` - WHERE '*' NOT IN ( - SELECT `send_as` FROM `sender_acl` - WHERE `logged_in_as` = :logged_in_as2 - )"); - $stmt->execute(array( - ':logged_in_as1' => $_data, - ':logged_in_as2' => $_data - )); - $rows_domain = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row_domain = array_shift($rows_domain)) { - if (is_valid_domain_name($row_domain['domain']) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row_domain['domain'])) { - $data['sender_acl_domains']['selectable'][] = $row_domain['domain']; - continue; - } - if ($row_domain['domain'] == '*' && $_SESSION['mailcow_cc_role'] == 'admin') { - $data['sender_acl_domains']['selectable'][] = $row_domain['domain']; - continue; - } + } + $stmt = $pdo->prepare("SELECT `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND (`send_as` NOT LIKE '@%' AND `send_as` != '*')"); + $stmt->execute(array(':logged_in_as' => $_data)); + $address_rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($address_row = array_shift($address_rows)) { + if (filter_var($address_row['send_as'], FILTER_VALIDATE_EMAIL) && !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $address_row['send_as'])) { + $data['sender_acl_addresses']['ro'][] = $address_row['send_as']; + continue; } - $stmt = $pdo->prepare("SELECT `address` FROM `alias` - WHERE `goto` != :goto - AND `address` NOT IN ( - SELECT `send_as` FROM `sender_acl` - WHERE `logged_in_as` = :logged_in_as - AND `send_as` NOT LIKE '@%')"); - $stmt->execute(array( - ':logged_in_as' => $_data, - ':goto' => $_data - )); - $rows_mbox = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($rows_mbox)) { - if (filter_var($row['address'], FILTER_VALIDATE_EMAIL) && hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['address'])) { - $data['sender_acl_addresses']['selectable'][] = $row['address']; - } + if (filter_var($address_row['send_as'], FILTER_VALIDATE_EMAIL) && hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $address_row['send_as'])) { + $data['sender_acl_addresses']['rw'][] = $address_row['send_as']; + continue; } } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` + WHERE `domain` NOT IN ( + SELECT REPLACE(`send_as`, '@', '') FROM `sender_acl` + WHERE `logged_in_as` = :logged_in_as1 + AND `send_as` LIKE '@%') + UNION + SELECT '*' FROM `domain` + WHERE '*' NOT IN ( + SELECT `send_as` FROM `sender_acl` + WHERE `logged_in_as` = :logged_in_as2 + )"); + $stmt->execute(array( + ':logged_in_as1' => $_data, + ':logged_in_as2' => $_data + )); + $rows_domain = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row_domain = array_shift($rows_domain)) { + if (is_valid_domain_name($row_domain['domain']) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row_domain['domain'])) { + $data['sender_acl_domains']['selectable'][] = $row_domain['domain']; + continue; + } + if ($row_domain['domain'] == '*' && $_SESSION['mailcow_cc_role'] == 'admin') { + $data['sender_acl_domains']['selectable'][] = $row_domain['domain']; + continue; + } + } + $stmt = $pdo->prepare("SELECT `address` FROM `alias` + WHERE `goto` != :goto + AND `address` NOT IN ( + SELECT `send_as` FROM `sender_acl` + WHERE `logged_in_as` = :logged_in_as + AND `send_as` NOT LIKE '@%')"); + $stmt->execute(array( + ':logged_in_as' => $_data, + ':goto' => $_data + )); + $rows_mbox = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($rows_mbox)) { + if (filter_var($row['address'], FILTER_VALIDATE_EMAIL) && hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['address'])) { + $data['sender_acl_addresses']['selectable'][] = $row['address']; + } } return $data; break; @@ -2655,44 +2347,24 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - try { - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` != 'ALL' AND `domain` = :domain"); - $stmt->execute(array( - ':domain' => $_data, - )); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $mailboxes[] = $row['username']; - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` != 'ALL' AND `domain` = :domain"); + $stmt->execute(array( + ':domain' => $_data, + )); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $mailboxes[] = $row['username']; } } else { - try { - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND (`domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role)"); - $stmt->execute(array( - ':username' => $_SESSION['mailcow_cc_username'], - ':role' => $_SESSION['mailcow_cc_role'], - )); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $mailboxes[] = $row['username']; - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND (`domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role)"); + $stmt->execute(array( + ':username' => $_SESSION['mailcow_cc_username'], + ':role' => $_SESSION['mailcow_cc_role'], + )); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $mailboxes[] = $row['username']; } } return $mailboxes; @@ -2707,19 +2379,9 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { else { $_data = $_SESSION['mailcow_cc_username']; } - try { - $stmt = $pdo->prepare("SELECT `attributes` FROM `mailbox` WHERE `username` = :username"); - $stmt->execute(array(':username' => $_data)); - $attrs = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `attributes` FROM `mailbox` WHERE `username` = :username"); + $stmt->execute(array(':username' => $_data)); + $attrs = $stmt->fetch(PDO::FETCH_ASSOC); $attrs = json_decode($attrs['attributes'], true); return array( 'tls_enforce_in' => $attrs['tls_enforce_in'], @@ -2736,20 +2398,11 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { else { $_data = $_SESSION['mailcow_cc_username']; } - try { - $stmt = $pdo->prepare("SELECT `id` FROM `sieve_filters` WHERE `username` = :username"); - $stmt->execute(array(':username' => $_data)); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $filters[] = $row['id']; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); + $stmt = $pdo->prepare("SELECT `id` FROM `sieve_filters` WHERE `username` = :username"); + $stmt->execute(array(':username' => $_data)); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $filters[] = $row['id']; } return $filters; break; @@ -2758,27 +2411,17 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if (!is_numeric($_data)) { return false; } - try { - $stmt = $pdo->prepare("SELECT CASE `script_name` WHEN 'active' THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, - CASE `script_name` WHEN 'active' THEN 1 ELSE 0 END AS `active_int`, - id, - username, - filter_type, - script_data, - script_desc - FROM `sieve_filters` - WHERE `id` = :id"); - $stmt->execute(array(':id' => $_data)); - $filter_details = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT CASE `script_name` WHEN 'active' THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, + CASE `script_name` WHEN 'active' THEN 1 ELSE 0 END AS `active_int`, + id, + username, + filter_type, + script_data, + script_desc + FROM `sieve_filters` + WHERE `id` = :id"); + $stmt->execute(array(':id' => $_data)); + $filter_details = $stmt->fetch(PDO::FETCH_ASSOC); if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $filter_details['username'])) { return false; } @@ -2818,52 +2461,43 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if (!is_numeric($_data)) { return false; } - try { - if (isset($_extra) && in_array('no_log', $_extra)) { - $field_query = $pdo->query('SHOW FIELDS FROM `imapsync` WHERE FIELD NOT IN ("returned_text", "password1")'); - $fields = $field_query->fetchAll(PDO::FETCH_ASSOC); - while($field = array_shift($fields)) { - $shown_fields[] = $field['Field']; - } - $stmt = $pdo->prepare("SELECT " . implode(',', $shown_fields) . ", - `active` AS `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` - FROM `imapsync` WHERE id = :id"); - } - elseif (isset($_extra) && in_array('with_password', $_extra)) { - $stmt = $pdo->prepare("SELECT *, - `active` AS `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` - FROM `imapsync` WHERE id = :id"); + if (isset($_extra) && in_array('no_log', $_extra)) { + $field_query = $pdo->query('SHOW FIELDS FROM `imapsync` WHERE FIELD NOT IN ("returned_text", "password1")'); + $fields = $field_query->fetchAll(PDO::FETCH_ASSOC); + while($field = array_shift($fields)) { + $shown_fields[] = $field['Field']; } - else { - $field_query = $pdo->query('SHOW FIELDS FROM `imapsync` WHERE FIELD NOT IN ("password1")'); - $fields = $field_query->fetchAll(PDO::FETCH_ASSOC); - while($field = array_shift($fields)) { - $shown_fields[] = $field['Field']; - } - $stmt = $pdo->prepare("SELECT " . implode(',', $shown_fields) . ", - `active` AS `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` - FROM `imapsync` WHERE id = :id"); - } - $stmt->execute(array(':id' => $_data)); - $syncjobdetails = $stmt->fetch(PDO::FETCH_ASSOC); - if (!empty($syncjobdetails['returned_text'])) { - $syncjobdetails['log'] = $syncjobdetails['returned_text']; - } - else { - $syncjobdetails['log'] = ''; + $stmt = $pdo->prepare("SELECT " . implode(',', $shown_fields) . ", + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` + FROM `imapsync` WHERE id = :id"); + } + elseif (isset($_extra) && in_array('with_password', $_extra)) { + $stmt = $pdo->prepare("SELECT *, + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` + FROM `imapsync` WHERE id = :id"); + } + else { + $field_query = $pdo->query('SHOW FIELDS FROM `imapsync` WHERE FIELD NOT IN ("password1")'); + $fields = $field_query->fetchAll(PDO::FETCH_ASSOC); + while($field = array_shift($fields)) { + $shown_fields[] = $field['Field']; } - unset($syncjobdetails['returned_text']); + $stmt = $pdo->prepare("SELECT " . implode(',', $shown_fields) . ", + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` + FROM `imapsync` WHERE id = :id"); } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); + $stmt->execute(array(':id' => $_data)); + $syncjobdetails = $stmt->fetch(PDO::FETCH_ASSOC); + if (!empty($syncjobdetails['returned_text'])) { + $syncjobdetails['log'] = $syncjobdetails['returned_text']; + } + else { + $syncjobdetails['log'] = ''; } + unset($syncjobdetails['returned_text']); if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $syncjobdetails['user2'])) { return false; } @@ -2879,20 +2513,11 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { else { $_data = $_SESSION['mailcow_cc_username']; } - try { - $stmt = $pdo->prepare("SELECT `id` FROM `imapsync` WHERE `user2` = :username"); - $stmt->execute(array(':username' => $_data)); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $syncjobdata[] = $row['id']; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); + $stmt = $pdo->prepare("SELECT `id` FROM `imapsync` WHERE `user2` = :username"); + $stmt->execute(array(':username' => $_data)); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $syncjobdata[] = $row['id']; } return $syncjobdata; break; @@ -2907,43 +2532,21 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { else { $_data = $_SESSION['mailcow_cc_username']; } - try { - $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `object` = :username AND - (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')"); - $stmt->execute(array(':username' => $_data)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `object` = :username AND + (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')"); + $stmt->execute(array(':username' => $_data)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); if (empty($num_results)) { return $default; } else { - try { - $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'highspamlevel' AND `object` = :username"); - $stmt->execute(array(':username' => $_data)); - $highspamlevel = $stmt->fetch(PDO::FETCH_ASSOC); - - $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'lowspamlevel' AND `object` = :username"); - $stmt->execute(array(':username' => $_data)); - $lowspamlevel = $stmt->fetch(PDO::FETCH_ASSOC); - - return $lowspamlevel['value'].', '.$highspamlevel['value']; - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'highspamlevel' AND `object` = :username"); + $stmt->execute(array(':username' => $_data)); + $highspamlevel = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'lowspamlevel' AND `object` = :username"); + $stmt->execute(array(':username' => $_data)); + $lowspamlevel = $stmt->fetch(PDO::FETCH_ASSOC); + return $lowspamlevel['value'].', '.$highspamlevel['value']; } break; case 'time_limited_aliases': @@ -2956,23 +2559,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { else { $_data = $_SESSION['mailcow_cc_username']; } - try { - $stmt = $pdo->prepare("SELECT `address`, - `goto`, - `validity` - FROM `spamalias` - WHERE `goto` = :username - AND `validity` >= :unixnow"); - $stmt->execute(array(':username' => $_data, ':unixnow' => time())); - $tladata = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - } + $stmt = $pdo->prepare("SELECT `address`, + `goto`, + `validity` + FROM `spamalias` + WHERE `goto` = :username + AND `validity` >= :unixnow"); + $stmt->execute(array(':username' => $_data, ':unixnow' => time())); + $tladata = $stmt->fetchAll(PDO::FETCH_ASSOC); return $tladata; break; case 'delimiter_action': @@ -2997,7 +2591,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) @@ -3011,44 +2605,24 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - try { - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `domain` != 'ALL' AND `domain` = :domain"); - $stmt->execute(array( - ':domain' => $_data, - )); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $resources[] = $row['username']; - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `domain` != 'ALL' AND `domain` = :domain"); + $stmt->execute(array( + ':domain' => $_data, + )); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $resources[] = $row['username']; } } else { - try { - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role"); - $stmt->execute(array( - ':username' => $_SESSION['mailcow_cc_username'], - ':role' => $_SESSION['mailcow_cc_role'], - )); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $resources[] = $row['username']; - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role"); + $stmt->execute(array( + ':username' => $_SESSION['mailcow_cc_username'], + ':role' => $_SESSION['mailcow_cc_role'], + )); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $resources[] = $row['username']; } } return $resources; @@ -3059,44 +2633,24 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - try { - $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain"); - $stmt->execute(array( - ':domain' => $_data, - )); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $aliasdomains[] = $row['alias_domain']; - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain"); + $stmt->execute(array( + ':domain' => $_data, + )); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $aliasdomains[] = $row['alias_domain']; } } else { - try { - $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role"); - $stmt->execute(array( - ':username' => $_SESSION['mailcow_cc_username'], - ':role' => $_SESSION['mailcow_cc_role'], - )); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $aliasdomains[] = $row['alias_domain']; - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role"); + $stmt->execute(array( + ':username' => $_SESSION['mailcow_cc_username'], + ':role' => $_SESSION['mailcow_cc_role'], + )); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $aliasdomains[] = $row['alias_domain']; } } return $aliasdomains; @@ -3106,30 +2660,20 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { return false; } - try { - $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `address` != `goto` AND `domain` = :domain"); - $stmt->execute(array( - ':domain' => $_data, - )); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $aliases[] = $row['address']; - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `id` FROM `alias` WHERE `address` != `goto` AND `domain` = :domain"); + $stmt->execute(array( + ':domain' => $_data, + )); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $aliases[] = $row['id']; } return $aliases; break; case 'ratelimit': if (is_valid_domain_name($_data)) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -3139,7 +2683,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } elseif (filter_var($_data, FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -3162,7 +2706,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) @@ -3173,85 +2717,67 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { break; case 'alias_details': $aliasdata = array(); - try { - $stmt = $pdo->prepare("SELECT - `domain`, - `goto`, - `address`, - `active` as `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, - `created`, - `modified` - FROM `alias` - WHERE `address` = :address AND `address` != `goto`"); - $stmt->execute(array( - ':address' => $_data, - )); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain"); - $stmt->execute(array( - ':domain' => $row['domain'], - )); - $row_alias_domain = $stmt->fetch(PDO::FETCH_ASSOC); - if (isset($row_alias_domain['target_domain']) && !empty($row_alias_domain['target_domain'])) { - $aliasdata['in_primary_domain'] = $row_alias_domain['target_domain']; - } - else { - $aliasdata['in_primary_domain'] = ""; - } - $aliasdata['domain'] = $row['domain']; - $aliasdata['goto'] = $row['goto']; - $aliasdata['address'] = $row['address']; - (!filter_var($aliasdata['address'], FILTER_VALIDATE_EMAIL)) ? $aliasdata['is_catch_all'] = 1 : $aliasdata['is_catch_all'] = 0; - $aliasdata['active'] = $row['active']; - $aliasdata['active_int'] = $row['active_int']; - $aliasdata['created'] = $row['created']; - $aliasdata['modified'] = $row['modified']; - if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $aliasdata['domain'])) { - return false; - } + $stmt = $pdo->prepare("SELECT + `id`, + `domain`, + `goto`, + `address`, + `active` as `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, + `created`, + `modified` + FROM `alias` + WHERE `id` = :id AND `address` != `goto`"); + $stmt->execute(array( + ':id' => intval($_data), + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain"); + $stmt->execute(array( + ':domain' => $row['domain'], + )); + $row_alias_domain = $stmt->fetch(PDO::FETCH_ASSOC); + if (isset($row_alias_domain['target_domain']) && !empty($row_alias_domain['target_domain'])) { + $aliasdata['in_primary_domain'] = $row_alias_domain['target_domain']; } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); + else { + $aliasdata['in_primary_domain'] = ""; + } + $aliasdata['id'] = $row['id']; + $aliasdata['domain'] = $row['domain']; + $aliasdata['goto'] = $row['goto']; + $aliasdata['address'] = $row['address']; + (!filter_var($aliasdata['address'], FILTER_VALIDATE_EMAIL)) ? $aliasdata['is_catch_all'] = 1 : $aliasdata['is_catch_all'] = 0; + $aliasdata['active'] = $row['active']; + $aliasdata['active_int'] = $row['active_int']; + $aliasdata['created'] = $row['created']; + $aliasdata['modified'] = $row['modified']; + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $aliasdata['domain'])) { return false; } return $aliasdata; break; case 'alias_domain_details': $aliasdomaindata = array(); - try { - $stmt = $pdo->prepare("SELECT - `alias_domain`, - `target_domain`, - `active` AS `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, - `created`, - `modified` - FROM `alias_domain` - WHERE `alias_domain` = :aliasdomain"); - $stmt->execute(array( - ':aliasdomain' => $_data, - )); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $aliasdomaindata['alias_domain'] = $row['alias_domain']; - $aliasdomaindata['target_domain'] = $row['target_domain']; - $aliasdomaindata['active'] = $row['active']; - $aliasdomaindata['active_int'] = $row['active_int']; - $aliasdomaindata['created'] = $row['created']; - $aliasdomaindata['modified'] = $row['modified']; - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT + `alias_domain`, + `target_domain`, + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, + `created`, + `modified` + FROM `alias_domain` + WHERE `alias_domain` = :aliasdomain"); + $stmt->execute(array( + ':aliasdomain' => $_data, + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $aliasdomaindata['alias_domain'] = $row['alias_domain']; + $aliasdomaindata['target_domain'] = $row['target_domain']; + $aliasdomaindata['active'] = $row['active']; + $aliasdomaindata['active_int'] = $row['active_int']; + $aliasdomaindata['created'] = $row['created']; + $aliasdomaindata['modified'] = $row['modified']; if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $aliasdomaindata['target_domain'])) { return false; } @@ -3262,30 +2788,20 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") { return false; } - try { - $stmt = $pdo->prepare("SELECT `domain` FROM `domain` - WHERE (`domain` IN ( - SELECT `domain` from `domain_admins` - WHERE (`active`='1' AND `username` = :username)) - ) - OR ('admin'= :role) - AND `domain` != 'ALL'"); - $stmt->execute(array( - ':username' => $_SESSION['mailcow_cc_username'], - ':role' => $_SESSION['mailcow_cc_role'], - )); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $domains[] = $row['domain']; - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `domain` FROM `domain` + WHERE (`domain` IN ( + SELECT `domain` from `domain_admins` + WHERE (`active`='1' AND `username` = :username)) + ) + OR ('admin'= :role) + AND `domain` != 'ALL'"); + $stmt->execute(array( + ':username' => $_SESSION['mailcow_cc_username'], + ':role' => $_SESSION['mailcow_cc_role'], + )); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $domains[] = $row['domain']; } return $domains; break; @@ -3295,85 +2811,75 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { return false; } - try { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain"); - $stmt->execute(array( - ':domain' => $_data - )); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if (!empty($row)) { - $_data = $row['target_domain']; - } - $stmt = $pdo->prepare("SELECT - `domain`, - `description`, - `aliases`, - `mailboxes`, - `maxquota`, - `quota`, - `relayhost`, - `relay_all_recipients` as `relay_all_recipients_int`, - `backupmx` as `backupmx_int`, - `active` as `active_int`, - CASE `relay_all_recipients` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `relay_all_recipients`, - CASE `backupmx` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `backupmx`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` - FROM `domain` WHERE `domain`= :domain"); - $stmt->execute(array( - ':domain' => $_data - )); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if (empty($row)) { - return false; - } - $stmt = $pdo->prepare("SELECT COUNT(*) AS `count`, - COALESCE(SUM(`quota`), 0) AS `in_use` - FROM `mailbox` - WHERE `kind` NOT REGEXP 'location|thing|group' - AND `domain` = :domain"); - $stmt->execute(array(':domain' => $row['domain'])); - $MailboxDataDomain = $stmt->fetch(PDO::FETCH_ASSOC); - $domaindata['max_new_mailbox_quota'] = ($row['quota'] * 1048576) - $MailboxDataDomain['in_use']; - if ($domaindata['max_new_mailbox_quota'] > ($row['maxquota'] * 1048576)) { - $domaindata['max_new_mailbox_quota'] = ($row['maxquota'] * 1048576); - } - $domaindata['quota_used_in_domain'] = $MailboxDataDomain['in_use']; - $domaindata['mboxes_in_domain'] = $MailboxDataDomain['count']; - $domaindata['mboxes_left'] = $row['mailboxes'] - $MailboxDataDomain['count']; - $domaindata['domain_name'] = $row['domain']; - $domaindata['description'] = $row['description']; - $domaindata['max_num_aliases_for_domain'] = $row['aliases']; - $domaindata['max_num_mboxes_for_domain'] = $row['mailboxes']; - $domaindata['max_quota_for_mbox'] = $row['maxquota'] * 1048576; - $domaindata['max_quota_for_domain'] = $row['quota'] * 1048576; - $domaindata['relayhost'] = $row['relayhost']; - $domaindata['backupmx'] = $row['backupmx']; - $domaindata['backupmx_int'] = $row['backupmx_int']; - $domaindata['active'] = $row['active']; - $domaindata['active_int'] = $row['active_int']; - $domaindata['relay_all_recipients'] = $row['relay_all_recipients']; - $domaindata['relay_all_recipients_int'] = $row['relay_all_recipients_int']; - $stmt = $pdo->prepare("SELECT COUNT(*) AS `alias_count` FROM `alias` - WHERE (`domain`= :domain OR `domain` IN (SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain2)) - AND `address` NOT IN ( - SELECT `username` FROM `mailbox` - )"); - $stmt->execute(array( - ':domain' => $_data, - ':domain2' => $_data - )); - $AliasDataDomain = $stmt->fetch(PDO::FETCH_ASSOC); - (isset($AliasDataDomain['alias_count'])) ? $domaindata['aliases_in_domain'] = $AliasDataDomain['alias_count'] : $domaindata['aliases_in_domain'] = "0"; - $domaindata['aliases_left'] = $row['aliases'] - $AliasDataDomain['alias_count']; - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain"); + $stmt->execute(array( + ':domain' => $_data + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (!empty($row)) { + $_data = $row['target_domain']; } + $stmt = $pdo->prepare("SELECT + `domain`, + `description`, + `aliases`, + `mailboxes`, + `maxquota`, + `quota`, + `relayhost`, + `relay_all_recipients` as `relay_all_recipients_int`, + `backupmx` as `backupmx_int`, + `active` as `active_int`, + CASE `relay_all_recipients` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `relay_all_recipients`, + CASE `backupmx` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `backupmx`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` + FROM `domain` WHERE `domain`= :domain"); + $stmt->execute(array( + ':domain' => $_data + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (empty($row)) { + return false; + } + $stmt = $pdo->prepare("SELECT COUNT(*) AS `count`, + COALESCE(SUM(`quota`), 0) AS `in_use` + FROM `mailbox` + WHERE `kind` NOT REGEXP 'location|thing|group' + AND `domain` = :domain"); + $stmt->execute(array(':domain' => $row['domain'])); + $MailboxDataDomain = $stmt->fetch(PDO::FETCH_ASSOC); + $domaindata['max_new_mailbox_quota'] = ($row['quota'] * 1048576) - $MailboxDataDomain['in_use']; + if ($domaindata['max_new_mailbox_quota'] > ($row['maxquota'] * 1048576)) { + $domaindata['max_new_mailbox_quota'] = ($row['maxquota'] * 1048576); + } + $domaindata['quota_used_in_domain'] = $MailboxDataDomain['in_use']; + $domaindata['mboxes_in_domain'] = $MailboxDataDomain['count']; + $domaindata['mboxes_left'] = $row['mailboxes'] - $MailboxDataDomain['count']; + $domaindata['domain_name'] = $row['domain']; + $domaindata['description'] = $row['description']; + $domaindata['max_num_aliases_for_domain'] = $row['aliases']; + $domaindata['max_num_mboxes_for_domain'] = $row['mailboxes']; + $domaindata['max_quota_for_mbox'] = $row['maxquota'] * 1048576; + $domaindata['max_quota_for_domain'] = $row['quota'] * 1048576; + $domaindata['relayhost'] = $row['relayhost']; + $domaindata['backupmx'] = $row['backupmx']; + $domaindata['backupmx_int'] = $row['backupmx_int']; + $domaindata['active'] = $row['active']; + $domaindata['active_int'] = $row['active_int']; + $domaindata['relay_all_recipients'] = $row['relay_all_recipients']; + $domaindata['relay_all_recipients_int'] = $row['relay_all_recipients_int']; + $stmt = $pdo->prepare("SELECT COUNT(*) AS `alias_count` FROM `alias` + WHERE (`domain`= :domain OR `domain` IN (SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain2)) + AND `address` NOT IN ( + SELECT `username` FROM `mailbox` + )"); + $stmt->execute(array( + ':domain' => $_data, + ':domain2' => $_data + )); + $AliasDataDomain = $stmt->fetch(PDO::FETCH_ASSOC); + (isset($AliasDataDomain['alias_count'])) ? $domaindata['aliases_in_domain'] = $AliasDataDomain['alias_count'] : $domaindata['aliases_in_domain'] = "0"; + $domaindata['aliases_left'] = $row['aliases'] - $AliasDataDomain['alias_count']; return $domaindata; break; case 'mailbox_details': @@ -3381,66 +2887,56 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } $mailboxdata = array(); - try { - $stmt = $pdo->prepare("SELECT - `domain`.`backupmx`, - `mailbox`.`username`, - `mailbox`.`name`, - `mailbox`.`active` AS `active_int`, - CASE `mailbox`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, - `mailbox`.`domain`, - `mailbox`.`quota`, - `quota2`.`bytes`, - `attributes`, - `quota2`.`messages` - FROM `mailbox`, `quota2`, `domain` - WHERE `mailbox`.`kind` NOT REGEXP 'location|thing|group' AND `mailbox`.`username` = `quota2`.`username` AND `domain`.`domain` = `mailbox`.`domain` AND `mailbox`.`username` = :mailbox"); - $stmt->execute(array( - ':mailbox' => $_data, - )); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt = $pdo->prepare("SELECT `maxquota`, `quota` FROM `domain` WHERE `domain` = :domain"); - $stmt->execute(array(':domain' => $row['domain'])); - $DomainQuota = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt = $pdo->prepare("SELECT COALESCE(SUM(`quota`), 0) as `in_use` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` = :domain AND `username` != :username"); - $stmt->execute(array(':domain' => $row['domain'], ':username' => $_data)); - $MailboxUsage = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt = $pdo->prepare("SELECT IFNULL(COUNT(`address`), 0) AS `sa_count` FROM `spamalias` WHERE `goto` = :address AND `validity` >= :unixnow"); - $stmt->execute(array(':address' => $_data, ':unixnow' => time())); - $SpamaliasUsage = $stmt->fetch(PDO::FETCH_ASSOC); - $mailboxdata['max_new_quota'] = ($DomainQuota['quota'] * 1048576) - $MailboxUsage['in_use']; - if ($mailboxdata['max_new_quota'] > ($DomainQuota['maxquota'] * 1048576)) { - $mailboxdata['max_new_quota'] = ($DomainQuota['maxquota'] * 1048576); - } - $mailboxdata['username'] = $row['username']; - $mailboxdata['is_relayed'] = $row['backupmx']; - $mailboxdata['name'] = $row['name']; - $mailboxdata['active'] = $row['active']; - $mailboxdata['active_int'] = $row['active_int']; - $mailboxdata['domain'] = $row['domain']; - $mailboxdata['quota'] = $row['quota']; - $mailboxdata['attributes'] = json_decode($row['attributes'], true); - $mailboxdata['quota_used'] = intval($row['bytes']); - $mailboxdata['percent_in_use'] = round((intval($row['bytes']) / intval($row['quota'])) * 100); - $mailboxdata['messages'] = $row['messages']; - $mailboxdata['spam_aliases'] = $SpamaliasUsage['sa_count']; - if ($mailboxdata['percent_in_use'] >= 90) { - $mailboxdata['percent_class'] = "danger"; - } - elseif ($mailboxdata['percent_in_use'] >= 75) { - $mailboxdata['percent_class'] = "warning"; - } - else { - $mailboxdata['percent_class'] = "success"; - } + $stmt = $pdo->prepare("SELECT + `domain`.`backupmx`, + `mailbox`.`username`, + `mailbox`.`name`, + `mailbox`.`active` AS `active_int`, + CASE `mailbox`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, + `mailbox`.`domain`, + `mailbox`.`quota`, + `quota2`.`bytes`, + `attributes`, + `quota2`.`messages` + FROM `mailbox`, `quota2`, `domain` + WHERE `mailbox`.`kind` NOT REGEXP 'location|thing|group' AND `mailbox`.`username` = `quota2`.`username` AND `domain`.`domain` = `mailbox`.`domain` AND `mailbox`.`username` = :mailbox"); + $stmt->execute(array( + ':mailbox' => $_data, + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt = $pdo->prepare("SELECT `maxquota`, `quota` FROM `domain` WHERE `domain` = :domain"); + $stmt->execute(array(':domain' => $row['domain'])); + $DomainQuota = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt = $pdo->prepare("SELECT COALESCE(SUM(`quota`), 0) as `in_use` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` = :domain AND `username` != :username"); + $stmt->execute(array(':domain' => $row['domain'], ':username' => $_data)); + $MailboxUsage = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt = $pdo->prepare("SELECT IFNULL(COUNT(`address`), 0) AS `sa_count` FROM `spamalias` WHERE `goto` = :address AND `validity` >= :unixnow"); + $stmt->execute(array(':address' => $_data, ':unixnow' => time())); + $SpamaliasUsage = $stmt->fetch(PDO::FETCH_ASSOC); + $mailboxdata['max_new_quota'] = ($DomainQuota['quota'] * 1048576) - $MailboxUsage['in_use']; + if ($mailboxdata['max_new_quota'] > ($DomainQuota['maxquota'] * 1048576)) { + $mailboxdata['max_new_quota'] = ($DomainQuota['maxquota'] * 1048576); + } + $mailboxdata['username'] = $row['username']; + $mailboxdata['is_relayed'] = $row['backupmx']; + $mailboxdata['name'] = $row['name']; + $mailboxdata['active'] = $row['active']; + $mailboxdata['active_int'] = $row['active_int']; + $mailboxdata['domain'] = $row['domain']; + $mailboxdata['quota'] = $row['quota']; + $mailboxdata['attributes'] = json_decode($row['attributes'], true); + $mailboxdata['quota_used'] = intval($row['bytes']); + $mailboxdata['percent_in_use'] = round((intval($row['bytes']) / intval($row['quota'])) * 100); + $mailboxdata['messages'] = $row['messages']; + $mailboxdata['spam_aliases'] = $SpamaliasUsage['sa_count']; + if ($mailboxdata['percent_in_use'] >= 90) { + $mailboxdata['percent_class'] = "danger"; + } + elseif ($mailboxdata['percent_in_use'] >= 75) { + $mailboxdata['percent_class'] = "warning"; } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + else { + $mailboxdata['percent_class'] = "success"; } return $mailboxdata; break; @@ -3449,38 +2945,28 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { return false; } - try { - $stmt = $pdo->prepare("SELECT - `username`, - `name`, - `kind`, - `multiple_bookings`, - `local_part`, - `active` AS `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, - `domain` - FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `username` = :resource"); - $stmt->execute(array( - ':resource' => $_data, - )); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $resourcedata['name'] = $row['username']; - $resourcedata['kind'] = $row['kind']; - $resourcedata['multiple_bookings'] = $row['multiple_bookings']; - $resourcedata['description'] = $row['name']; - $resourcedata['active'] = $row['active']; - $resourcedata['active_int'] = $row['active_int']; - $resourcedata['domain'] = $row['domain']; - $resourcedata['local_part'] = $row['local_part']; - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT + `username`, + `name`, + `kind`, + `multiple_bookings`, + `local_part`, + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, + `domain` + FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `username` = :resource"); + $stmt->execute(array( + ':resource' => $_data, + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $resourcedata['name'] = $row['username']; + $resourcedata['kind'] = $row['kind']; + $resourcedata['multiple_bookings'] = $row['multiple_bookings']; + $resourcedata['description'] = $row['name']; + $resourcedata['active'] = $row['active']; + $resourcedata['active_int'] = $row['active_int']; + $resourcedata['domain'] = $row['domain']; + $resourcedata['local_part'] = $row['local_part']; if (!isset($resourcedata['domain']) || (isset($resourcedata['domain']) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $resourcedata['domain']))) { return false; @@ -3500,7 +2986,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $ids = $_data['id']; } if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -3511,35 +2997,25 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if (!is_numeric($id)) { return false; } - try { - $stmt = $pdo->prepare("SELECT `user2` FROM `imapsync` WHERE id = :id"); - $stmt->execute(array(':id' => $id)); - $user2 = $stmt->fetch(PDO::FETCH_ASSOC)['user2']; - if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $user2)) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - return false; - } - $stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `id`= :id"); - $stmt->execute(array(':id' => $id)); - } - catch (PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `user2` FROM `imapsync` WHERE id = :id"); + $stmt->execute(array(':id' => $id)); + $user2 = $stmt->fetch(PDO::FETCH_ASSOC)['user2']; + if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $user2)) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => 'access_denied' ); - return false; + continue; } + $stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `id`= :id"); + $stmt->execute(array(':id' => $id)); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('deleted_syncjob', $id) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('deleted_syncjobs', implode(', ', $ids)) - ); break; case 'filter': if (!is_array($_data['id'])) { @@ -3550,7 +3026,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $ids = $_data['id']; } if (!isset($_SESSION['acl']['filters']) || $_SESSION['acl']['filters'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -3559,37 +3035,27 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($ids as $id) { if (!is_numeric($id)) { - return false; - } - try { - $stmt = $pdo->prepare("SELECT `username` FROM `sieve_filters` WHERE id = :id"); - $stmt->execute(array(':id' => $id)); - $usr = $stmt->fetch(PDO::FETCH_ASSOC)['username']; - if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $usr)) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - return false; - } - $stmt = $pdo->prepare("DELETE FROM `sieve_filters` WHERE `id`= :id"); - $stmt->execute(array(':id' => $id)); + continue; } - catch (PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `username` FROM `sieve_filters` WHERE id = :id"); + $stmt->execute(array(':id' => $id)); + $usr = $stmt->fetch(PDO::FETCH_ASSOC)['username']; + if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $usr)) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => 'access_denied' ); - return false; + continue; } + $stmt = $pdo->prepare("DELETE FROM `sieve_filters` WHERE `id`= :id"); + $stmt->execute(array(':id' => $id)); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('delete_filter', $id) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('delete_filters', implode(', ', $ids)) - ); break; case 'time_limited_alias': if (!is_array($_data['address'])) { @@ -3600,7 +3066,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $addresses = $_data['address']; } if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -3608,48 +3074,28 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } foreach ($addresses as $address) { - try { - $stmt = $pdo->prepare("SELECT `goto` FROM `spamalias` WHERE `address` = :address"); - $stmt->execute(array(':address' => $address)); - $goto = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `goto` FROM `spamalias` WHERE `address` = :address"); + $stmt->execute(array(':address' => $address)); + $goto = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $goto)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username AND `address` = :item"); - $stmt->execute(array( - ':username' => $goto, - ':item' => $address - )); + continue; } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username AND `address` = :item"); + $stmt->execute(array( + ':username' => $goto, + ':item' => $address + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', htmlspecialchars($goto)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_modified', htmlspecialchars($usernames)) - ); break; case 'eas_cache': if (!is_array($_data['username'])) { @@ -3660,7 +3106,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $usernames = $_data['username']; } if (!isset($_SESSION['acl']['eas_reset']) || $_SESSION['acl']['eas_reset'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -3669,33 +3115,23 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($usernames as $username) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username"); - $stmt->execute(array( - ':username' => $username - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('eas_reset', htmlspecialchars($username)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('eas_reset', htmlspecialchars(implode(', ', $usernames))) - ); break; case 'domain': if (!is_array($_data['domain'])) { @@ -3706,7 +3142,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $domains = $_data['domain']; } if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' @@ -3715,157 +3151,112 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($domains as $domain) { if (!is_valid_domain_name($domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_invalid' ); - return false; + continue; } $domain = idn_to_ascii(strtolower(trim($domain))); - try { - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` - WHERE `domain` = :domain"); - $stmt->execute(array(':domain' => $domain)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` + WHERE `domain` = :domain"); + $stmt->execute(array(':domain' => $domain)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); if ($num_results != 0 || !empty($num_results)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_not_empty' ); - return false; - } - try { - $stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain"); - $stmt->execute(array( - ':domain' => $domain, - )); - $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `domain` = :domain"); - $stmt->execute(array( - ':domain' => $domain, - )); - $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :domain"); - $stmt->execute(array( - ':domain' => $domain, - )); - $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `target_domain` = :domain"); - $stmt->execute(array( - ':domain' => $domain, - )); - $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `domain` = :domain"); - $stmt->execute(array( - ':domain' => $domain, - )); - $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` LIKE :domain"); - $stmt->execute(array( - ':domain' => '%@'.$domain, - )); - $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :domain"); - $stmt->execute(array( - ':domain' => '%@'.$domain, - )); - $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` = :domain"); - $stmt->execute(array( - ':domain' => '%@'.$domain, - )); - $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain"); - $stmt->execute(array( - ':domain' => '%@'.$domain, - )); - $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :domain"); - $stmt->execute(array( - ':domain' => $domain, - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain"); + $stmt->execute(array( + ':domain' => $domain, + )); + $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `domain` = :domain"); + $stmt->execute(array( + ':domain' => $domain, + )); + $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :domain"); + $stmt->execute(array( + ':domain' => $domain, + )); + $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `target_domain` = :domain"); + $stmt->execute(array( + ':domain' => $domain, + )); + $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `domain` = :domain"); + $stmt->execute(array( + ':domain' => $domain, + )); + $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` LIKE :domain"); + $stmt->execute(array( + ':domain' => '%@'.$domain, + )); + $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :domain"); + $stmt->execute(array( + ':domain' => '%@'.$domain, + )); + $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` = :domain"); + $stmt->execute(array( + ':domain' => '%@'.$domain, + )); + $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain"); + $stmt->execute(array( + ':domain' => '%@'.$domain, + )); + $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :domain"); + $stmt->execute(array( + ':domain' => $domain, + )); try { $redis->hDel('DOMAIN_MAP', $domain); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('domain_removed', htmlspecialchars($domain)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_removed', htmlspecialchars(implode(', ', $domains))) - ); break; case 'alias': - if (!is_array($_data['address'])) { - $addresses = array(); - $addresses[] = $_data['address']; + if (!is_array($_data['id'])) { + $ids = array(); + $ids[] = $_data['id']; } else { - $addresses = $_data['address']; + $ids = $_data['id']; } - foreach ($addresses as $address) { - $local_part = strstr($address, '@', true); - $domain = mailbox('get', 'alias_details', $address)['domain']; - try { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :address"); - $stmt->execute(array(':address' => $address)); - $gotos = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } - $goto_array = explode(',', $gotos['goto']); - if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'] = array( + foreach ($ids as $id) { + $alias_data = mailbox('get', 'alias_details', $id); + if (empty($alias_data)) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `address` = :address AND `address` NOT IN (SELECT `username` FROM `mailbox`)"); - $stmt->execute(array( - ':address' => $address - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `id` = :id"); + $stmt->execute(array( + ':id' => $id + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('alias_removed', htmlspecialchars($alias_data['address'])) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('alias_removed', htmlspecialchars(implode(', ', $addresses))) - ); break; case 'alias_domain': if (!is_array($_data['alias_domain'])) { @@ -3877,74 +3268,54 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($alias_domains as $alias_domain) { if (!is_valid_domain_name($alias_domain)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'domain_invalid' ); - return false; - } - try { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` - WHERE `alias_domain`= :alias_domain"); - $stmt->execute(array(':alias_domain' => $alias_domain)); - $DomainData = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` + WHERE `alias_domain`= :alias_domain"); + $stmt->execute(array(':alias_domain' => $alias_domain)); + $DomainData = $stmt->fetch(PDO::FETCH_ASSOC); if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $DomainData['target_domain'])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `alias_domain` = :alias_domain"); - $stmt->execute(array( - ':alias_domain' => $alias_domain, - )); - $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :alias_domain"); - $stmt->execute(array( - ':alias_domain' => $alias_domain, - )); - $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :alias_domain"); - $stmt->execute(array( - ':alias_domain' => $alias_domain, - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `alias_domain` = :alias_domain"); + $stmt->execute(array( + ':alias_domain' => $alias_domain, + )); + $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :alias_domain"); + $stmt->execute(array( + ':alias_domain' => $alias_domain, + )); + $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :alias_domain"); + $stmt->execute(array( + ':alias_domain' => $alias_domain, + )); try { $redis->hDel('DOMAIN_MAP', $alias_domain); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('redis_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('alias_domain_removed', htmlspecialchars($alias_domain)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('alias_domain_removed', htmlspecialchars(implode(', ', $alias_domains))) - ); break; case 'mailbox': if (!is_array($_data['username'])) { @@ -3956,115 +3327,105 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($usernames as $username) { if (!filter_var($username, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } - try { - $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `user2` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $username . "/%' OR `c_uid` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :username"); + $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `user2` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $username . "/%' OR `c_uid` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias` + WHERE `goto` REGEXP :username"); + $stmt->execute(array(':username' => '(^|,)'.$username.'($|,)')); + $GotoData = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($GotoData as $gotos) { + $goto_exploded = explode(',', $gotos['goto']); + if (($key = array_search($username, $goto_exploded)) !== false) { + unset($goto_exploded[$key]); + } + $gotos_rebuild = implode(',', $goto_exploded); + $stmt = $pdo->prepare("UPDATE `alias` SET + `goto` = :goto + WHERE `address` = :address"); $stmt->execute(array( - ':username' => $username + ':goto' => $gotos_rebuild, + ':address' => $gotos['address'] )); - $stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias` - WHERE `goto` REGEXP :username"); - $stmt->execute(array(':username' => '(^|,)'.$username.'($|,)')); - $GotoData = $stmt->fetchAll(PDO::FETCH_ASSOC); - foreach ($GotoData as $gotos) { - $goto_exploded = explode(',', $gotos['goto']); - if (($key = array_search($username, $goto_exploded)) !== false) { - unset($goto_exploded[$key]); - } - $gotos_rebuild = implode(',', $goto_exploded); - $stmt = $pdo->prepare("UPDATE `alias` SET - `goto` = :goto - WHERE `address` = :address"); - $stmt->execute(array( - ':goto' => $gotos_rebuild, - ':address' => $gotos['address'] - )); - } - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_removed', htmlspecialchars($username)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mailbox_removed', htmlspecialchars(implode(', ', $usernames))) - ); break; case 'resource': if (!is_array($_data['name'])) { @@ -4076,69 +3437,59 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($names as $name) { if (!filter_var($name, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; + continue; } if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $name)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username"); - $stmt->execute(array( - ':username' => $name - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username"); - $stmt->execute(array( - ':username' => $name - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username"); - $stmt->execute(array( - ':username' => $name - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $name . "/%' OR `c_uid` = :username"); - $stmt->execute(array( - ':username' => $name - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); - $stmt->execute(array( - ':username' => $name - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); - $stmt->execute(array( - ':username' => $name - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); - $stmt->execute(array( - ':username' => $name - )); - $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username"); - $stmt->execute(array( - ':username' => $name - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + continue; } + $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username"); + $stmt->execute(array( + ':username' => $name + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username"); + $stmt->execute(array( + ':username' => $name + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username"); + $stmt->execute(array( + ':username' => $name + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $name . "/%' OR `c_uid` = :username"); + $stmt->execute(array( + ':username' => $name + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); + $stmt->execute(array( + ':username' => $name + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); + $stmt->execute(array( + ':username' => $name + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)"); + $stmt->execute(array( + ':username' => $name + )); + $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username"); + $stmt->execute(array( + ':username' => $name + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('resource_removed', htmlspecialchars($name)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('resource_removed', htmlspecialchars(implode(', ', $names))) - ); break; } break; @@ -4146,4 +3497,4 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox'))) { update_sogo_static_view(); } -} +} \ No newline at end of file diff --git a/data/web/inc/functions.policy.inc.php b/data/web/inc/functions.policy.inc.php index 6bc2f7802f..c852616950 100644 --- a/data/web/inc/functions.policy.inc.php +++ b/data/web/inc/functions.policy.inc.php @@ -11,7 +11,7 @@ function policy($_action, $_scope, $_data = null) { $object = $_data['domain']; if (is_valid_domain_name($object)) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' @@ -21,7 +21,7 @@ function policy($_action, $_scope, $_data = null) { $object = idn_to_ascii(strtolower(trim($object))); } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' @@ -36,7 +36,7 @@ function policy($_action, $_scope, $_data = null) { } $object_from = preg_replace('/\.+/', '.', rtrim(preg_replace("/\.\*/", "*", trim(strtolower($_data['object_from']))), '.')); if (!ctype_alnum(str_replace(array('@', '_', '.', '-', '*'), '', $object_from))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'policy_list_from_invalid' @@ -44,55 +44,37 @@ function policy($_action, $_scope, $_data = null) { return false; } if ($object_list != "blacklist_from" && $object_list != "whitelist_from") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' ); return false; } - try { - $stmt = $pdo->prepare("SELECT `object` FROM `filterconf` - WHERE (`option` = 'whitelist_from' OR `option` = 'blacklist_from') - AND `object` = :object - AND `value` = :object_from"); - $stmt->execute(array(':object' => $object, ':object_from' => $object_from)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => 'policy_list_from_exists' - ); - return false; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('mysql_error', $e) - ); - return false; - } - try { - $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option` ,`value`) - VALUES (:object, :object_list, :object_from)"); - $stmt->execute(array( - ':object' => $object, - ':object_list' => $object_list, - ':object_from' => $object_from - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `object` FROM `filterconf` + WHERE (`option` = 'whitelist_from' OR `option` = 'blacklist_from') + AND `object` = :object + AND `value` = :object_from"); + $stmt->execute(array(':object' => $object, ':object_from' => $object_from)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('mysql_error', $e) + 'msg' => 'policy_list_from_exists' ); return false; } - $_SESSION['return'] = array( + + $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option` ,`value`) + VALUES (:object, :object_list, :object_from)"); + $stmt->execute(array( + ':object' => $object, + ':object_list' => $object_list, + ':object_from' => $object_from + )); + + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => array('domain_modified', $object) @@ -101,7 +83,7 @@ function policy($_action, $_scope, $_data = null) { case 'mailbox': $object = $_data['username']; if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' @@ -109,7 +91,7 @@ function policy($_action, $_scope, $_data = null) { return false; } if (!isset($_SESSION['acl']['spam_policy']) || $_SESSION['acl']['spam_policy'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' @@ -124,7 +106,7 @@ function policy($_action, $_scope, $_data = null) { } $object_from = preg_replace('/\.+/', '.', rtrim(preg_replace("/\.\*/", "*", trim(strtolower($_data['object_from']))), '.')); if (!ctype_alnum(str_replace(array('@', '_', '.', '-', '*'), '', $object_from))) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'policy_list_from_invalid' @@ -132,55 +114,35 @@ function policy($_action, $_scope, $_data = null) { return false; } if ($object_list != "blacklist_from" && $object_list != "whitelist_from") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' ); return false; } - try { - $stmt = $pdo->prepare("SELECT `object` FROM `filterconf` - WHERE (`option` = 'whitelist_from' OR `option` = 'blacklist_from') - AND `object` = :object - AND `value` = :object_from"); - $stmt->execute(array(':object' => $object, ':object_from' => $object_from)); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => 'policy_list_from_exists' - ); - return false; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('mysql_error', $e) - ); - return false; - } - try { - $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option` ,`value`) - VALUES (:object, :object_list, :object_from)"); - $stmt->execute(array( - ':object' => $object, - ':object_list' => $object_list, - ':object_from' => $object_from - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare("SELECT `object` FROM `filterconf` + WHERE (`option` = 'whitelist_from' OR `option` = 'blacklist_from') + AND `object` = :object + AND `value` = :object_from"); + $stmt->execute(array(':object' => $object, ':object_from' => $object_from)); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('mysql_error', $e) + 'msg' => 'policy_list_from_exists' ); return false; } - $_SESSION['return'] = array( + $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option` ,`value`) + VALUES (:object, :object_list, :object_from)"); + $stmt->execute(array( + ':object' => $object, + ':object_list' => $object_list, + ':object_from' => $object_from + )); + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => array('mailbox_modified', $object) @@ -194,43 +156,34 @@ function policy($_action, $_scope, $_data = null) { (array)$prefids = $_data['prefid']; foreach ($prefids as $prefid) { if (!is_numeric($prefid)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("SELECT `object` FROM `filterconf` WHERE `prefid` = :prefid"); - $stmt->execute(array(':prefid' => $prefid)); - $object = $stmt->fetch(PDO::FETCH_ASSOC)['object']; - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('mysql_error', $e) - ); + continue; } + $stmt = $pdo->prepare("SELECT `object` FROM `filterconf` WHERE `prefid` = :prefid"); + $stmt->execute(array(':prefid' => $prefid)); + $object = $stmt->fetch(PDO::FETCH_ASSOC)['object']; if (is_valid_domain_name($object)) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' ); - return false; + continue; } $object = idn_to_ascii(strtolower(trim($object))); } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' ); - return false; + continue; } try { $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :object AND `prefid` = :prefid"); @@ -240,19 +193,19 @@ function policy($_action, $_scope, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('item_deleted',$prefid) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('items_deleted', implode(', ', $prefids)) - ); break; case 'mailbox': if (!is_array($_data['prefid'])) { @@ -263,7 +216,7 @@ function policy($_action, $_scope, $_data = null) { $prefids = $_data['prefid']; } if (!isset($_SESSION['acl']['spam_policy']) || $_SESSION['acl']['spam_policy'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' @@ -272,32 +225,23 @@ function policy($_action, $_scope, $_data = null) { } foreach ($prefids as $prefid) { if (!is_numeric($prefid)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare("SELECT `object` FROM `filterconf` WHERE `prefid` = :prefid"); - $stmt->execute(array(':prefid' => $prefid)); - $object = $stmt->fetch(PDO::FETCH_ASSOC)['object']; - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('mysql_error', $e) - ); + continue; } + $stmt = $pdo->prepare("SELECT `object` FROM `filterconf` WHERE `prefid` = :prefid"); + $stmt->execute(array(':prefid' => $prefid)); + $object = $stmt->fetch(PDO::FETCH_ASSOC)['object']; if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => 'access_denied' ); - return false; + continue; } try { $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :object AND `prefid` = :prefid"); @@ -307,19 +251,19 @@ function policy($_action, $_scope, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('items_deleted', implode(', ', $prefids)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('items_deleted', implode(', ', $prefids)) - ); break; } break; @@ -335,23 +279,16 @@ function policy($_action, $_scope, $_data = null) { } $_data = idn_to_ascii(strtolower(trim($_data))); } - try { - // WHITELIST - $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='whitelist_from' AND (`object` LIKE :object_mail OR `object` = :object_domain)"); - $stmt->execute(array(':object_mail' => '%@' . $_data, ':object_domain' => $_data)); - $rows['whitelist'] = $stmt->fetchAll(PDO::FETCH_ASSOC); - // BLACKLIST - $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='blacklist_from' AND (`object` LIKE :object_mail OR `object` = :object_domain)"); - $stmt->execute(array(':object_mail' => '%@' . $_data, ':object_domain' => $_data)); - $rows['blacklist'] = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('mysql_error', $e) - ); - } + + // WHITELIST + $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='whitelist_from' AND (`object` LIKE :object_mail OR `object` = :object_domain)"); + $stmt->execute(array(':object_mail' => '%@' . $_data, ':object_domain' => $_data)); + $rows['whitelist'] = $stmt->fetchAll(PDO::FETCH_ASSOC); + // BLACKLIST + $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='blacklist_from' AND (`object` LIKE :object_mail OR `object` = :object_domain)"); + $stmt->execute(array(':object_mail' => '%@' . $_data, ':object_domain' => $_data)); + $rows['blacklist'] = $stmt->fetchAll(PDO::FETCH_ASSOC); + return $rows; break; case 'mailbox': @@ -367,23 +304,14 @@ function policy($_action, $_scope, $_data = null) { if (empty($domain)) { return false; } - try { - // WHITELIST - $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='whitelist_from' AND (`object` = :username OR `object` = :domain)"); - $stmt->execute(array(':username' => $_data, ':domain' => $domain)); - $rows['whitelist'] = $stmt->fetchAll(PDO::FETCH_ASSOC); - // BLACKLIST - $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='blacklist_from' AND (`object` = :username OR `object` = :domain)"); - $stmt->execute(array(':username' => $_data, ':domain' => $domain)); - $rows['blacklist'] = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('mysql_error', $e) - ); - } + // WHITELIST + $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='whitelist_from' AND (`object` = :username OR `object` = :domain)"); + $stmt->execute(array(':username' => $_data, ':domain' => $domain)); + $rows['whitelist'] = $stmt->fetchAll(PDO::FETCH_ASSOC); + // BLACKLIST + $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='blacklist_from' AND (`object` = :username OR `object` = :domain)"); + $stmt->execute(array(':username' => $_data, ':domain' => $domain)); + $rows['blacklist'] = $stmt->fetchAll(PDO::FETCH_ASSOC); return $rows; break; } diff --git a/data/web/inc/functions.quarantine.inc.php b/data/web/inc/functions.quarantine.inc.php index 865a0f0834..c92a2cdd87 100644 --- a/data/web/inc/functions.quarantine.inc.php +++ b/data/web/inc/functions.quarantine.inc.php @@ -14,7 +14,7 @@ function quarantine($_action, $_data = null) { $ids = $_data['id']; } if (!isset($_SESSION['acl']['quarantine']) || $_SESSION['acl']['quarantine'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -23,59 +23,40 @@ function quarantine($_action, $_data = null) { } foreach ($ids as $id) { if (!is_numeric($id)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' ); - return false; - } - try { - $stmt = $pdo->prepare('SELECT `rcpt` FROM `quarantine` WHERE `id` = :id'); - $stmt->execute(array(':id' => $id)); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if (hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt'])) { - try { - $stmt = $pdo->prepare("DELETE FROM `quarantine` WHERE `id` = :id"); - $stmt->execute(array( - ':id' => $id - )); - } - catch (PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); - return false; - } - } - else { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'access_denied' - ); - return false; - } + continue; } - catch(PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare('SELECT `rcpt` FROM `quarantine` WHERE `id` = :id'); + $stmt->execute(array(':id' => $id)); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt']) && $_SESSION['mailcow_cc_role'] != 'admin') { + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) + 'msg' => 'access_denied' ); + continue; } + else { + $stmt = $pdo->prepare("DELETE FROM `quarantine` WHERE `id` = :id"); + $stmt->execute(array( + ':id' => $id + )); + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('item_deleted', $id) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('items_deleted', implode(', ', $ids)) - ); break; case 'edit': if (!isset($_SESSION['acl']['quarantine']) || $_SESSION['acl']['quarantine'] != "1" ) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -85,7 +66,7 @@ function quarantine($_action, $_data = null) { // Edit settings if ($_data['action'] == 'settings') { if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -101,14 +82,14 @@ function quarantine($_action, $_data = null) { $redis->Set('Q_EXCLUDE_DOMAINS', json_encode($exclude_domains)); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'saved_settings' @@ -125,31 +106,22 @@ function quarantine($_action, $_data = null) { } foreach ($ids as $id) { if (!is_numeric($id)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' ); - return false; + continue; } - try { - $stmt = $pdo->prepare('SELECT `msg`, `qid`, `sender`, `rcpt` FROM `quarantine` WHERE `id` = :id'); - $stmt->execute(array(':id' => $id)); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt'])) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'msg' => 'access_denied' - ); - return false; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( + $stmt = $pdo->prepare('SELECT `msg`, `qid`, `sender`, `rcpt` FROM `quarantine` WHERE `id` = :id'); + $stmt->execute(array(':id' => $id)); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt'])) { + $_SESSION['return'][] = array( 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) + 'msg' => 'access_denied' ); + continue; } $sender = (isset($row['sender'])) ? $row['sender'] : 'sender-unknown@rspamd'; try { @@ -170,12 +142,12 @@ function quarantine($_action, $_data = null) { $postfix = 'postfix'; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'warning', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('release_send_failed', 'Cannot determine Postfix host') ); - return false; + continue; } $mail->Host = $postfix; $mail->Port = 590; @@ -193,12 +165,12 @@ function quarantine($_action, $_data = null) { } catch (phpmailerException $e) { unlink($msg_tmpf); - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'warning', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('release_send_failed', $e->errorMessage()) ); - return false; + continue; } try { $stmt = $pdo->prepare("DELETE FROM `quarantine` WHERE `id` = :id"); @@ -207,63 +179,179 @@ function quarantine($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('item_released', $id) + ); + } + } + elseif ($_data['action'] == 'learnspam') { + if (!is_array($_data['id'])) { + $ids = array(); + $ids[] = $_data['id']; + } + else { + $ids = $_data['id']; + } + foreach ($ids as $id) { + if (!is_numeric($id)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'access_denied' + ); + continue; + } + $stmt = $pdo->prepare('SELECT `msg`, `rcpt` FROM `quarantine` WHERE `id` = :id'); + $stmt->execute(array(':id' => $id)); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt']) && $_SESSION['mailcow_cc_role'] != 'admin') { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'msg' => 'access_denied' + ); + continue; + } + $curl = curl_init(); + curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/rspamd-sock/rspamd.sock'); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_TIMEOUT, 30); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/plain')); + curl_setopt($curl, CURLOPT_URL,"http://rspamd/learnspam"); + curl_setopt($curl, CURLOPT_POSTFIELDS, $row['msg']); + $response = curl_exec($curl); + if (!curl_errno($curl)) { + $response = json_decode($response, true); + if (isset($response['error'])) { + if (stripos($response['error'], 'already learned') === false) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('spam_learn_error', $response['error']) + ); + continue; + } + } + curl_close($curl); + $curl = curl_init(); + curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/rspamd-sock/rspamd.sock'); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_TIMEOUT, 30); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/plain', 'Flag: 11')); + curl_setopt($curl, CURLOPT_URL,"http://rspamd/fuzzyadd"); + curl_setopt($curl, CURLOPT_POSTFIELDS, $row['msg']); + $response = curl_exec($curl); + if (!curl_errno($curl)) { + $response = json_decode($response, true); + if (isset($response['error'])) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('fuzzy_learn_error', $response['error']) + ); + continue; + } + curl_close($curl); + try { + $stmt = $pdo->prepare("DELETE FROM `quarantine` WHERE `id` = :id"); + $stmt->execute(array( + ':id' => $id + )); + } + catch (PDOException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('mysql_error', $e) + ); + continue; + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__), + 'msg' => 'qlearn_spam' + ); + continue; + } + else { + curl_close($curl); + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('spam_learn_error', 'curl error ' . curl_errno($curl)) + ); + continue; + } + curl_close($curl); + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('learn_spam_error', 'unknown') + ); + continue; + } + else { + curl_close($curl); + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('spam_learn_error', 'curl error ' . curl_errno($curl)) + ); + continue; + } + curl_close($curl); + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('learn_spam_error', 'unknown') + ); + continue; } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'items_released' - ); } return true; break; case 'get': - try { - if ($_SESSION['mailcow_cc_role'] == "user") { - $stmt = $pdo->prepare('SELECT `id`, `qid`, `rcpt`, `sender`, UNIX_TIMESTAMP(`created`) AS `created` FROM `quarantine` WHERE `rcpt` = :mbox'); - $stmt->execute(array(':mbox' => $_SESSION['mailcow_cc_username'])); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $q_meta[] = $row; - } + if ($_SESSION['mailcow_cc_role'] == "user") { + $stmt = $pdo->prepare('SELECT `id`, `qid`, `rcpt`, `sender`, UNIX_TIMESTAMP(`created`) AS `created` FROM `quarantine` WHERE `rcpt` = :mbox'); + $stmt->execute(array(':mbox' => $_SESSION['mailcow_cc_username'])); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $q_meta[] = $row; + } + } + elseif ($_SESSION['mailcow_cc_role'] == "admin") { + $stmt = $pdo->query('SELECT `id`, `qid`, `rcpt`, `sender`, UNIX_TIMESTAMP(`created`) AS `created` FROM `quarantine`'); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + while($row = array_shift($rows)) { + $q_meta[] = $row; } - elseif ($_SESSION['mailcow_cc_role'] == "admin") { - $stmt = $pdo->query('SELECT `id`, `qid`, `rcpt`, `sender`, UNIX_TIMESTAMP(`created`) AS `created` FROM `quarantine`'); + } + else { + $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')); + foreach ($domains as $domain) { + $stmt = $pdo->prepare('SELECT `id`, `qid`, `rcpt`, `sender`, UNIX_TIMESTAMP(`created`) AS `created` FROM `quarantine` WHERE `rcpt` REGEXP :domain'); + $stmt->execute(array(':domain' => '@' . $domain . '$')); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); while($row = array_shift($rows)) { $q_meta[] = $row; } } - else { - $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')); - foreach ($domains as $domain) { - $stmt = $pdo->prepare('SELECT `id`, `qid`, `rcpt`, `sender`, UNIX_TIMESTAMP(`created`) AS `created` FROM `quarantine` WHERE `rcpt` REGEXP :domain'); - $stmt->execute(array(':domain' => '@' . $domain . '$')); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - while($row = array_shift($rows)) { - $q_meta[] = $row; - } - } - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); } return $q_meta; break; case 'settings': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -276,7 +364,7 @@ function quarantine($_action, $_data = null) { $settings['retention_size'] = $redis->Get('Q_RETENTION_SIZE'); } catch (RedisException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('redis_error', $e) @@ -289,21 +377,11 @@ function quarantine($_action, $_data = null) { if (!is_numeric($_data) || empty($_data)) { return false; } - try { - $stmt = $pdo->prepare('SELECT `rcpt`, `symbols`, `msg`, `domain` FROM `quarantine` WHERE `id`= :id'); - $stmt->execute(array(':id' => $_data)); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if (hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt'])) { - return $row; - } - return false; - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); + $stmt = $pdo->prepare('SELECT `rcpt`, `symbols`, `msg`, `domain` FROM `quarantine` WHERE `id`= :id'); + $stmt->execute(array(':id' => $_data)); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt'])) { + return $row; } return false; break; diff --git a/data/web/inc/functions.relayhost.inc.php b/data/web/inc/functions.relayhost.inc.php index 8faad80af9..a3e1ffdaf9 100644 --- a/data/web/inc/functions.relayhost.inc.php +++ b/data/web/inc/functions.relayhost.inc.php @@ -6,7 +6,7 @@ function relayhost($_action, $_data = null) { switch ($_action) { case 'add': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -17,7 +17,7 @@ function relayhost($_action, $_data = null) { $username = str_replace(':', '\:', trim($_data['username'])); $password = str_replace(':', '\:', trim($_data['password'])); if (empty($hostname)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('invalid_host', htmlspecialchars($host)) @@ -35,14 +35,14 @@ function relayhost($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('relayhost_added', htmlspecialchars(implode(', ', $hosts))) @@ -50,7 +50,7 @@ function relayhost($_action, $_data = null) { break; case 'edit': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -67,12 +67,12 @@ function relayhost($_action, $_data = null) { $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'relayhost_invalid' + 'msg' => array('relayhost_invalid', $id) ); - return false; + continue; } try { $stmt = $pdo->prepare("UPDATE `relayhosts` SET @@ -90,23 +90,23 @@ function relayhost($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('object_modified', htmlspecialchars(implode(', ', $hostnames))) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('object_modified', htmlspecialchars(implode(', ', $hostnames))) - ); break; case 'delete': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -122,36 +122,27 @@ function relayhost($_action, $_data = null) { $stmt->execute(array(':id' => $id)); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('relayhost_removed', htmlspecialchars($id)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('relayhost_removed', htmlspecialchars(implode(', ', $hostnames))) - ); break; case 'get': if ($_SESSION['mailcow_cc_role'] != "admin") { return false; } $relayhosts = array(); - try { - $stmt = $pdo->query("SELECT `id`, `hostname`, `username` FROM `relayhosts`"); - $relayhosts = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); - } + $stmt = $pdo->query("SELECT `id`, `hostname`, `username` FROM `relayhosts`"); + $relayhosts = $stmt->fetchAll(PDO::FETCH_ASSOC); return $relayhosts; break; case 'details': @@ -159,33 +150,23 @@ function relayhost($_action, $_data = null) { return false; } $relayhostdata = array(); - try { - $stmt = $pdo->prepare("SELECT `id`, - `hostname`, - `username`, - `password`, - `active` AS `active_int`, - CONCAT(LEFT(`password`, 3), '...') AS `password_short`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` - FROM `relayhosts` - WHERE `id` = :id"); + $stmt = $pdo->prepare("SELECT `id`, + `hostname`, + `username`, + `password`, + `active` AS `active_int`, + CONCAT(LEFT(`password`, 3), '...') AS `password_short`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` + FROM `relayhosts` + WHERE `id` = :id"); + $stmt->execute(array(':id' => $_data)); + $relayhostdata = $stmt->fetch(PDO::FETCH_ASSOC); + if (!empty($relayhostdata)) { + $stmt = $pdo->prepare("SELECT GROUP_CONCAT(`domain` SEPARATOR ', ') AS `used_by_domains` FROM `domain` WHERE `relayhost` = :id"); $stmt->execute(array(':id' => $_data)); - $relayhostdata = $stmt->fetch(PDO::FETCH_ASSOC); - - if (!empty($relayhostdata)) { - $stmt = $pdo->prepare("SELECT GROUP_CONCAT(`domain` SEPARATOR ', ') AS `used_by_domains` FROM `domain` WHERE `relayhost` = :id"); - $stmt->execute(array(':id' => $_data)); - $used_by_domains = $stmt->fetch(PDO::FETCH_ASSOC)['used_by_domains']; - $used_by_domains = (empty($used_by_domains)) ? '' : $used_by_domains; - $relayhostdata['used_by_domains'] = $used_by_domains; - } - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); + $used_by_domains = $stmt->fetch(PDO::FETCH_ASSOC)['used_by_domains']; + $used_by_domains = (empty($used_by_domains)) ? '' : $used_by_domains; + $relayhostdata['used_by_domains'] = $used_by_domains; } return $relayhostdata; break; diff --git a/data/web/inc/functions.rsettings.inc.php b/data/web/inc/functions.rsettings.inc.php index 9f13a4c312..fbf8922bab 100644 --- a/data/web/inc/functions.rsettings.inc.php +++ b/data/web/inc/functions.rsettings.inc.php @@ -6,7 +6,7 @@ function rsettings($_action, $_data = null) { switch ($_action) { case 'add': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -17,7 +17,7 @@ function rsettings($_action, $_data = null) { $desc = $_data['desc']; $active = intval($_data['active']); if (empty($content)) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'map_content_empty' @@ -34,14 +34,14 @@ function rsettings($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); return false; } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'settings_map_added' @@ -49,7 +49,7 @@ function rsettings($_action, $_data = null) { break; case 'edit': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -65,12 +65,12 @@ function rsettings($_action, $_data = null) { $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int']; } else { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'settings_map_invalid' + 'msg' => array('settings_map_invalid', $id) ); - return false; + continue; } $content = trim($content); try { @@ -87,23 +87,23 @@ function rsettings($_action, $_data = null) { )); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); - return false; + continue; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('object_modified', htmlspecialchars($ids)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('object_modified', htmlspecialchars(implode(', ', $ids))) - ); break; case 'delete': if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'access_denied' @@ -117,36 +117,27 @@ function rsettings($_action, $_data = null) { $stmt->execute(array(':id' => $id)); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => array('mysql_error', $e) ); return false; } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('settings_map_removed', htmlspecialchars($id)) + ); } - $_SESSION['return'] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('settings_map_removed', htmlspecialchars(implode(', ', $ids))) - ); break; case 'get': if ($_SESSION['mailcow_cc_role'] != "admin") { return false; } $settingsmaps = array(); - try { - $stmt = $pdo->query("SELECT `id`, `desc`, `active` FROM `settingsmap`"); - $settingsmaps = $stmt->fetchAll(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); - } + $stmt = $pdo->query("SELECT `id`, `desc`, `active` FROM `settingsmap`"); + $settingsmaps = $stmt->fetchAll(PDO::FETCH_ASSOC); return $settingsmaps; break; case 'details': @@ -154,24 +145,15 @@ function rsettings($_action, $_data = null) { return false; } $settingsmapdata = array(); - try { - $stmt = $pdo->prepare("SELECT `id`, - `desc`, - `content`, - `active` AS `active_int`, - CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` - FROM `settingsmap` - WHERE `id` = :id"); - $stmt->execute(array(':id' => $_data)); - $settingsmapdata = $stmt->fetch(PDO::FETCH_ASSOC); - } - catch(PDOException $e) { - $_SESSION['return'] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('mysql_error', $e) - ); - } + $stmt = $pdo->prepare("SELECT `id`, + `desc`, + `content`, + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active` + FROM `settingsmap` + WHERE `id` = :id"); + $stmt->execute(array(':id' => $_data)); + $settingsmapdata = $stmt->fetch(PDO::FETCH_ASSOC); return $settingsmapdata; break; } diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index b938a56b92..c99484d517 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "05072018_2319"; + $db_version = "10082018_2019"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -112,6 +112,7 @@ function init_db_schema() { ), "alias" => array( "cols" => array( + "id" => "INT NOT NULL AUTO_INCREMENT", "address" => "VARCHAR(255) NOT NULL", "goto" => "TEXT NOT NULL", "domain" => "VARCHAR(255) NOT NULL", @@ -121,7 +122,10 @@ function init_db_schema() { ), "keys" => array( "primary" => array( - "" => array("address") + "" => array("id") + ), + "unique" => array( + "address" => array("address") ), "key" => array( "domain" => array("domain") @@ -366,6 +370,7 @@ function init_db_schema() { "logs" => array( "cols" => array( "id" => "INT NOT NULL AUTO_INCREMENT", + "task" => "CHAR(32) NOT NULL DEFAULT '000000'", "type" => "VARCHAR(32) DEFAULT ''", "msg" => "TEXT", "call" => "TEXT", @@ -754,6 +759,8 @@ function init_db_schema() { if ($num_results == 0) { if (strpos($type, 'AUTO_INCREMENT') !== false) { $type = $type . ' PRIMARY KEY '; + // Adding an AUTO_INCREMENT key, need to drop primary keys first + $pdo->query("ALTER TABLE `" . $table . "` DROP PRIMARY KEY"); } $pdo->query("ALTER TABLE `" . $table . "` ADD `" . $column . "` " . $type); } @@ -933,7 +940,7 @@ function init_db_schema() { WHERE `username` = :username"); $stmt->execute(array(':tls_enforce_in' => $tls_options['tls_enforce_in'], ':tls_enforce_out' => $tls_options['tls_enforce_out'], ':username' => $tls_user)); } - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__), 'msg' => 'db_init_complete' @@ -943,7 +950,7 @@ function init_db_schema() { $stmt = $pdo->query("INSERT INTO `user_acl` (`username`) SELECT `username` FROM `mailbox` WHERE `kind` = '' AND NOT EXISTS (SELECT `username` FROM `user_acl`);"); } catch (PDOException $e) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__), 'msg' => array('mysql_error', $e) diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index 1370155e7f..0ec41fab93 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -51,6 +51,25 @@ 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('mysql_error', $e) + ); + return false; + } + else { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('mysql_error', 'unknown error') + ); + return false; + } +} +set_exception_handler('pdo_exception_handler'); // TODO: Move function function get_remote_ip($anonymize = null) { diff --git a/data/web/inc/sessions.inc.php b/data/web/inc/sessions.inc.php index fe1cdfa2b8..a3b8140703 100644 --- a/data/web/inc/sessions.inc.php +++ b/data/web/inc/sessions.inc.php @@ -52,7 +52,7 @@ function session_check() { return true; } if (!isset($_SESSION['SESS_REMOTE_UA']) || ($_SESSION['SESS_REMOTE_UA'] != $_SERVER['HTTP_USER_AGENT'])) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'warning', 'msg' => 'session_ua' ); @@ -60,7 +60,7 @@ function session_check() { } if (!empty($_POST)) { if ($_SESSION['CSRF']['TOKEN'] != $_POST['csrf_token']) { - $_SESSION['return'] = array( + $_SESSION['return'][] = array( 'type' => 'warning', 'msg' => 'session_token' ); diff --git a/data/web/js/api.js b/data/web/js/api.js index 3f9bc4b7b3..2e770f7bb1 100644 --- a/data/web/js/api.js +++ b/data/web/js/api.js @@ -3,6 +3,10 @@ $(document).ready(function() { if ($(elem).data('submitted') == '1') { return true; } else { + var parent_btn_grp = $(elem).parentsUntil(".btn-group").parent(); + if (parent_btn_grp.hasClass('btn-group')) { + parent_btn_grp.replaceWith('
- +
- +
diff --git a/data/web/quarantine.php b/data/web/quarantine.php index ec3ebb44f7..87f565a168 100644 --- a/data/web/quarantine.php +++ b/data/web/quarantine.php @@ -24,6 +24,8 @@
From 1791383eab16e5c6f7640395e711aabcd7b6912a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Wed, 15 Aug 2018 00:05:18 +0200 Subject: [PATCH 011/109] [Web] Fix duplicate success message after editing a domain as domain administrator [Web] Add "login as" button for domain admin table --- data/web/inc/functions.mailbox.inc.php | 10 +++++----- data/web/inc/triggers.inc.php | 9 +++++++++ data/web/js/admin.js | 3 ++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 82481cc3d4..92d55e8b0b 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1906,12 +1906,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ':description' => $description, ':domain' => $domain )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('domain_modified', htmlspecialchars($domain)) + ); } - $_SESSION['return'][] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_modified', htmlspecialchars($domain)) - ); } break; case 'mailbox': diff --git a/data/web/inc/triggers.inc.php b/data/web/inc/triggers.inc.php index 892d79fb40..4df1becaa3 100644 --- a/data/web/inc/triggers.inc.php +++ b/data/web/inc/triggers.inc.php @@ -52,6 +52,15 @@ header("Location: /user.php"); } } + else { + if (!empty(domain_admin('details', $duallogin))) { + $_SESSION["dual-login"]["username"] = $_SESSION['mailcow_cc_username']; + $_SESSION["dual-login"]["role"] = $_SESSION['mailcow_cc_role']; + $_SESSION['mailcow_cc_username'] = $duallogin; + $_SESSION['mailcow_cc_role'] = "domainadmin"; + header("Location: /user.php"); + } + } } } diff --git a/data/web/js/admin.js b/data/web/js/admin.js index f9f2867fb2..a4fe801e3f 100644 --- a/data/web/js/admin.js +++ b/data/web/js/admin.js @@ -27,7 +27,7 @@ jQuery(function($){ {"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"}, {"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active}, - {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} + {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} ], "rows": $.ajax({ dataType: 'json', @@ -130,6 +130,7 @@ jQuery(function($){ item.action = ''; }); } From 2c58323e36deb04575085c3021508a0cba26df88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Wed, 15 Aug 2018 14:16:55 +0200 Subject: [PATCH 012/109] [Web] Fix database init --- data/web/inc/init_db.inc.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index c99484d517..9c154e7fe0 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -759,8 +759,12 @@ function init_db_schema() { if ($num_results == 0) { if (strpos($type, 'AUTO_INCREMENT') !== false) { $type = $type . ' PRIMARY KEY '; - // Adding an AUTO_INCREMENT key, need to drop primary keys first - $pdo->query("ALTER TABLE `" . $table . "` DROP PRIMARY KEY"); + // Adding an AUTO_INCREMENT key, need to drop primary keys first, if exists + $stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = 'PRIMARY'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $pdo->query("ALTER TABLE `" . $table . "` DROP PRIMARY KEY"); + } } $pdo->query("ALTER TABLE `" . $table . "` ADD `" . $column . "` " . $type); } From f81dad17bff9e86fddc5cee56f76908873dffd4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Wed, 15 Aug 2018 22:48:13 +0200 Subject: [PATCH 013/109] [Compose] Update Postfix image --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index e01bf2d3b3..3c9f292039 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -196,7 +196,7 @@ services: - dovecot postfix-mailcow: - image: mailcow/postfix:1.20 + image: mailcow/postfix:1.21 build: ./data/Dockerfiles/postfix volumes: - ./data/conf/postfix:/opt/postfix/conf From 6498fb0b39470434b359659203fc37bfbac30f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Thu, 16 Aug 2018 12:42:12 +0200 Subject: [PATCH 014/109] [Web] Change alias to TEXT field --- data/web/inc/init_db.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 9c154e7fe0..95c54472ef 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "10082018_2019"; + $db_version = "16082018_2019"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -76,7 +76,7 @@ function init_db_schema() { "c_cn" => "VARCHAR(255)", "mail" => "VARCHAR(255) NOT NULL", // TODO -> use TEXT and check if SOGo login breaks on empty aliases - "aliases" => "VARCHAR(6144) NOT NULL DEFAULT ''", + "aliases" => "TEXT NOT NULL", "ad_aliases" => "VARCHAR(6144) NOT NULL DEFAULT ''", "home" => "VARCHAR(255)", "kind" => "VARCHAR(100) NOT NULL DEFAULT ''", From 66ee11c03d53aa3c70ca2718da6aed15f14439c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Fri, 17 Aug 2018 21:42:31 +0200 Subject: [PATCH 015/109] [SOGo] Disable display of ACL "any/authenticated" by default [Dovecot] Disable "any" ACL by default [SOGo] Might fix theme switching (yes, again) --- data/Dockerfiles/sogo/Dockerfile | 3 ++- data/Dockerfiles/sogo/acl.diff | 11 +++++++++++ data/Dockerfiles/sogo/bootstrap-sogo.sh | 23 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 data/Dockerfiles/sogo/acl.diff diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index 7765f08cae..30a06d2425 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -20,6 +20,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ netcat \ psmisc \ wget \ + patch \ && rm -rf /var/lib/apt/lists/* \ && dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \ @@ -45,7 +46,7 @@ COPY supervisord.conf /etc/supervisor/supervisord.conf COPY theme-blue.js /usr/lib/GNUstep/SOGo/WebServerResources/js/theme-blue.js COPY theme-blue.css /usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css COPY sogo-full.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg - +COPY acl.diff /acl.diff CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf RUN rm -rf /tmp/* /var/tmp/* diff --git a/data/Dockerfiles/sogo/acl.diff b/data/Dockerfiles/sogo/acl.diff new file mode 100644 index 0000000000..5137003886 --- /dev/null +++ b/data/Dockerfiles/sogo/acl.diff @@ -0,0 +1,11 @@ +--- /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox 2018-08-17 18:29:57.987504204 +0200 ++++ /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox 2018-08-17 18:29:35.918291298 +0200 +@@ -46,7 +46,7 @@ + + +
+- + diff --git a/data/Dockerfiles/sogo/bootstrap-sogo.sh b/data/Dockerfiles/sogo/bootstrap-sogo.sh index de995c2285..46d8ec6cef 100755 --- a/data/Dockerfiles/sogo/bootstrap-sogo.sh +++ b/data/Dockerfiles/sogo/bootstrap-sogo.sh @@ -172,4 +172,27 @@ sed -i \ /usr/lib/GNUstep/SOGo/WebServerResources/js/Common/Common.app.js \ /usr/lib/GNUstep/SOGo/WebServerResources/js/Common.js +sed -i \ + -e 's/default: "900"/default: "700"/g' \ + -e 's/default: "500"/default: "700"/g' \ + -e 's/"hue-1": "400"/"hue-1": "500"/g' \ + -e 's/"hue-1": "A100"/"hue-1": "500"/g' \ + -e 's/"hue-2": "800"/"hue-2": "700"/g' \ + -e 's/"hue-2": "300"/"hue-2": "700"/g' \ + -e 's/"hue-3": "A700"/"hue-3": "A200"/' \ + -e 's/default:"900"/default:"700"/g' \ + -e 's/default:"500"/default:"700"/g' \ + -e 's/"hue-1":"400"/"hue-1":"500"/g' \ + -e 's/"hue-1":"A100"/"hue-1":"500"/g' \ + -e 's/"hue-2":"800"/"hue-2":"700"/g' \ + -e 's/"hue-2":"300"/"hue-2":"700"/g' \ + -e 's/"hue-3":"A700"/"hue-3":"A200"/' \ + /usr/lib/GNUstep/SOGo/WebServerResources/js/Common/Common.app.js \ + /usr/lib/GNUstep/SOGo/WebServerResources/js/Common.js + +# Patch ACLs (comment this out to enable any or authenticated targets for ACL) +if patch -sfN --dry-run /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff > /dev/null; then + patch /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff; +fi + exec gosu sogo /usr/sbin/sogod From 407d92102cabd37ba7008cbbfc76e9b90117e126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Fri, 17 Aug 2018 21:43:37 +0200 Subject: [PATCH 016/109] [Compose] New SOGo image --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3c9f292039..871961a8ce 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -136,7 +136,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.33 + image: mailcow/sogo:1.34 build: ./data/Dockerfiles/sogo environment: - DBNAME=${DBNAME} From 6cee038a639e89a2c6475320c8a3900f32a457ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Fri, 17 Aug 2018 21:44:17 +0200 Subject: [PATCH 017/109] [Dovecot] IMPORTANT: Disables 'any' and 'all authenticated' ACL settings! See wiki how to revert this, if you need it. --- data/conf/dovecot/dovecot.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index 187c61b49c..dd8db8a351 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -255,7 +255,8 @@ protocol sieve { managesieve_logout_format = bytes=%i/%o } plugin { - acl_anyone = allow + # Allow "any" or "authenticated" to be used in ACLs + #acl_anyone = allow acl_shared_dict = file:/var/vmail/shared-mailboxes.db acl = vfile quota = dict:Userquota::proxy::sqlquota From 3fd99e4f6d2939b1a643dd1a6654ea434e1e6ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Fri, 17 Aug 2018 22:32:42 +0200 Subject: [PATCH 018/109] [Web] Important fix: Ignore untrusted headers --- data/web/inc/prerequisites.inc.php | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index 0ec41fab93..c07d4d2dd4 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -80,25 +80,7 @@ function get_remote_ip($anonymize = null) { elseif ($anonymize !== true && $anonymize !== false) { $anonymize = true; } - $remote = ''; - if ($_SERVER['HTTP_CLIENT_IP']) { - $remote = $_SERVER['HTTP_CLIENT_IP']; - } - elseif ($_SERVER['HTTP_X_FORWARDED_FOR']) { - $remote = $_SERVER['HTTP_X_FORWARDED_FOR']; - } - elseif ($_SERVER['HTTP_X_FORWARDED']) { - $remote = $_SERVER['HTTP_X_FORWARDED']; - } - elseif ($_SERVER['HTTP_FORWARDED_FOR']) { - $remote = $_SERVER['HTTP_FORWARDED_FOR']; - } - elseif ($_SERVER['HTTP_FORWARDED']) { - $remote = $_SERVER['HTTP_FORWARDED']; - } - elseif ($_SERVER['REMOTE_ADDR']) { - $remote = $_SERVER['REMOTE_ADDR']; - } + $remote = $_SERVER['REMOTE_ADDR']; if (filter_var($remote, FILTER_VALIDATE_IP) === false) { return '0.0.0.0'; } From 819e94883a3f2adabf8f4079c76830460878092a Mon Sep 17 00:00:00 2001 From: DynamicThijs <40541903+DynamicThijs@users.noreply.github.com> Date: Sat, 18 Aug 2018 10:28:07 +0200 Subject: [PATCH 019/109] Update lang.nl.php --- data/web/lang/lang.nl.php | 115 +++++++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 21 deletions(-) diff --git a/data/web/lang/lang.nl.php b/data/web/lang/lang.nl.php index 2587dc1c88..385c0c04a4 100644 --- a/data/web/lang/lang.nl.php +++ b/data/web/lang/lang.nl.php @@ -16,50 +16,101 @@ $lang['footer']['delete_now'] = 'Nu verwijderen'; $lang['footer']['cancel'] = 'Annuleren'; -$lang['danger']['dkim_domain_or_sel_invalid'] = "DKIM domain or selector invalid"; +$lang['danger']['mysql_error'] = "MySQL-fout: %s"; +$lang['danger']['redis_error'] = "Redis-fout: %s"; +$lang['danger']['unknown_tfa_method'] = "Onbekende tweefactorauthenticatiemethode"; +$lang['danger']['totp_verification_failed'] = "TOTP-verificatie mislukt"; +$lang['success']['verified_totp_login'] = "TOTP succesvol geverifieerd"; +$lang['danger']['u2f_verification_failed'] = "U2F-verificatie mislukt: %s"; +$lang['success']['verified_u2f_login'] = "U2F succesvol geverifieerd"; +$lang['success']['verified_yotp_login'] = "Yubico OTP succesvol geverifieerd"; +$lang['danger']['yotp_verification_failed'] = "Yubico OTP-verificatie mislukt: %s"; +$lang['danger']['ip_list_empty'] = "Lijst met toegestane IP-adressen kan niet leeg zijn"; +$lang['danger']['rspamd_ui_pw_length'] = "Rspamd-wachtwoord moet minstens 6 tekens lang zijn"; +$lang['success']['rspamd_ui_pw_set'] = "Rspamd-wachtwoord succesvol ingesteld"; +$lang['danger']['unknown'] = "Er is een onbekende fout opgetreden"; +$lang['danger']['malformed_username'] = "Ongeldige gebruikersnaam"; +$lang['info']['awaiting_tfa_confirmation'] = "In afwachting van tweefactorauthenticatie..."; +$lang['success']['logged_in_as'] = "Succesvol ingelogd als %s"; +$lang['danger']['login_failed'] = "Aanmelding mislukt"; +$lang['danger']['set_acl_failed'] = "ALC kon niet worden ingesteld"; +$lang['danger']['no_user_defined'] = "Geen gebruiker gespecificeerd"; +$lang['danger']['script_empty'] = "Script kan niet leeg zijn"; +$lang['danger']['sieve_error'] = "Sieve-fout: %s"; +$lang['danger']['value_missing'] = "Niet alle waarden zijn ingevuld"; +$lang['danger']['filter_type'] = "Verkeerd filtertype"; +$lang['danger']['domain_cannot_match_hostname'] = "Domein kan niet gelijk zijn aan hostname"; +$lang['warning']['domain_added_sogo_failed'] = "Domein is toegevoegd, maar het hestarten van SOGo mislukte. Controleer de serverlogs."; +$lang['danger']['rl_timeframe'] = "Ratelimit time frame is incorrect"; +$lang['success']['deleted_syncjobs'] = "Synchronisatietaken %s zijn verwijderd"; +$lang['success']['deleted_syncjob'] = "Synchronisatietaak %s is verwijderd"; +$lang['success']['delete_filters'] = "Filters %s zijn verwijderd"; +$lang['success']['delete_filter'] = "Filter %s is verwijderd"; +$lang['danger']['invalid_bcc_map_type'] = "Ongeldig BCC-kaart type"; +$lang['danger']['bcc_empty'] = "BCC-bestemming kan niet leeg zijn"; +$lang['danger']['bcc_must_be_email'] = "BCC-kaart %s is geen geldig e-mailadres"; +$lang['danger']['bcc_exists'] = "BCC-kaart %s bestaat voor type %s"; +$lang['success']['bcc_saved'] = "BCC-kaart is opgeslagen"; +$lang['success']['bcc_edited'] = "BCC-kaart %s is gewijzigd"; +$lang['success']['bcc_deleted'] = "BCC-kaarten %s zijn verwijderd"; +$lang['danger']['private_key_error'] = "Privésleutel-fout: %s"; +$lang['danger']['map_content_empty'] = "Inhoud kan niet leeg zijn"; +$lang['success']['settings_map_added'] = "Instellingen toegevoegd"; +$lang['danger']['settings_map_invalid'] = "Instellingen ongeldig"; +$lang['danger']['settings_map_removed'] = "Instellingen verwijderd: %s"; +$lang['danger']['invalid_host'] = "Ongeldige host gespecificeerd: %s"; +$lang['danger']['relayhost_invalid'] = "Relayhost %s is ongeldig"; +$lang['success']['saved_settings'] = "Instellingen opgeslagen"; +$lang['success']['db_init_complete'] = "Database-initialisatie voltooid"; + +$lang['warning']['session_ua'] = "Token ongeldig: gebruikersagentvalidatie mislukt"; +$lang['warning']['session_token'] = "Token ongeldig: komt niet overeen"; + +$lang['danger']['dkim_domain_or_sel_invalid'] = "DKIM-domein %s ongeldig"; $lang['success']['dkim_removed'] = "DKIM-sleutel %s is verwijderd"; $lang['success']['dkim_added'] = "DKIM-sleutel is opgeslagen"; $lang['danger']['access_denied'] = "Toegang geweigerd of ongeldige gegevens"; -$lang['danger']['domain_invalid'] = "Domeinnaam is ongeldig"; +$lang['danger']['domain_invalid'] = "Domeinnaam %s is ongeldig"; $lang['danger']['mailbox_quota_exceeds_domain_quota'] = "Max. postvakquotum is groter dan domeinquotum"; $lang['danger']['object_is_not_numeric'] = "Waarde %s is niet numeriek"; $lang['success']['domain_added'] = "Domein %s is toegevoegd"; $lang['success']['items_deleted'] = "Onderdeel %s is verwijderd"; +$lang['success']['item_deleted'] = "Onderdeel %s is verwijderd"; $lang['danger']['alias_empty'] = "Aliasadres moet ingevuld worden"; $lang['danger']['last_key'] = 'De laatste sleutel kan niet worden verwijderd'; $lang['danger']['goto_empty'] = "Doeladres moet ingevuld worden"; $lang['danger']['policy_list_from_exists'] = "Er bestaat al een vermelding met dezelfde naam"; $lang['danger']['policy_list_from_invalid'] = "Invoer is ongeldig"; -$lang['danger']['alias_invalid'] = "Aliasadres is ongeldig"; -$lang['danger']['goto_invalid'] = "Doeladres is ongeldig"; -$lang['danger']['alias_domain_invalid'] = "Aliasdomein is ongeldig"; -$lang['danger']['target_domain_invalid'] = "Doeladres is ongeldig"; +$lang['danger']['alias_invalid'] = "Aliasadres %s is ongeldig"; +$lang['danger']['goto_invalid'] = "Doeladres %s is ongeldig"; +$lang['danger']['alias_domain_invalid'] = "Aliasdomein %s is ongeldig"; +$lang['danger']['target_domain_invalid'] = "Doeladres %s is ongeldig"; $lang['danger']['object_exists'] = "Object %s bestaat al"; $lang['danger']['domain_exists'] = "Domain %s bestaat al"; $lang['danger']['alias_goto_identical'] = "Het alias- en doeladres mogen niet identiek zijn"; -$lang['danger']['aliasd_targetd_identical'] = "Het aliasdomein mag niet identiek zijn aan het doeldomein"; +$lang['danger']['aliasd_targetd_identical'] = "Aliasdomein %s mag niet identiek zijn aan het doeldomein"; $lang['danger']['maxquota_empty'] = 'Max. postvakquotum moet groter dan 0 zijn.'; -$lang['success']['alias_added'] = "Aliasadres(sen) zijn toegevoegd"; -$lang['success']['alias_modified'] = "Wijzigingen aan alias(sen) %s zijn opgeslagen"; +$lang['success']['alias_added'] = "Aliasadres %s is toegevoegd"; +$lang['success']['alias_modified'] = "Wijzigingen aan alias %s zijn opgeslagen"; $lang['success']['mailbox_modified'] = "Wijzigingen aan postvak %s zijn opgeslagen"; $lang['success']['resource_modified'] = "Wijzigingen aan postvak %s zijn opgeslagen"; $lang['success']['object_modified'] = "Wijzigingen aan object %s zijn opgeslagen"; $lang['success']['f2b_modified'] = "Wijzigingen aan Fail2ban parameters zijn opgeslagen"; -$lang['danger']['targetd_not_found'] = "Doeldomein niet gevonden"; +$lang['danger']['targetd_not_found'] = "Doeldomein %s niet gevonden"; $lang['success']['aliasd_added'] = "Aliasdomein %s is toegevoegd"; $lang['success']['aliasd_modified'] = "Wijzigingen aan aliasadres %s zijn opgeslagen"; $lang['success']['domain_modified'] = "Wijzigingen aan domein %s zijn opgeslagen"; $lang['success']['domain_admin_modified'] = "Wijzigingen aan domeinbeheerder %s zijn opgeslagen"; $lang['success']['domain_admin_added'] = "Domeinbeheerder %s is toegevoegd"; $lang['success']['admin_modified'] = "Wijzigingen aan de beheerder zijn opgeslagen"; -$lang['danger']['username_invalid'] = "Gebruikersnaam kan niet worden gebruikt"; +$lang['danger']['username_invalid'] = "Gebruikersnaam %s kan niet worden gebruikt"; $lang['danger']['password_mismatch'] = "De ingevoerde wachtwoorden komen niet overeen"; $lang['danger']['password_complexity'] = "Wachtwoord voldoet niet aan de vereisten (6 tekens lang, letters en nummers)"; $lang['danger']['password_empty'] = "Het wachtwoord moet ingevuld worden"; $lang['danger']['login_failed'] = "Aanmelding mislukt"; $lang['danger']['mailbox_invalid'] = "Naam van het postvak is ongeldig"; -$lang['danger']['description_invalid'] = 'Beschrijving van de hulpbron is ongeldig'; -$lang['danger']['resource_invalid'] = "Naam van de hulpbron is ongeldig"; +$lang['danger']['description_invalid'] = 'Beschrijving voor %s is ongeldig'; +$lang['danger']['resource_invalid'] = "Naam van de hulpbron %s is ongeldig"; $lang['danger']['is_alias'] = "Aliasadres %s bestaat al"; $lang['danger']['is_alias_or_mailbox'] = "Aliasadres of postvak %s bestaat al"; $lang['danger']['is_spam_alias'] = "Spam-aliasadres %s bestaat al"; @@ -82,7 +133,7 @@ $lang['danger']['domain_quota_m_in_use'] = "Domeinquotum moet gelijk zijn aan, of groter zijn dan %s MiB"; $lang['danger']['mailboxes_in_use'] = "Max. aantal postvakken moet gelijk zijn aan, of groter zijn dan %d"; $lang['danger']['aliases_in_use'] = "Max. aantal aliassen moet gelijk zijn aan, of groter zijn dan %d"; -$lang['danger']['sender_acl_invalid'] = "ACL-waarde van afzender is ongeldig"; +$lang['danger']['sender_acl_invalid'] = "ACL-waarde van afzender %s is ongeldig"; $lang['danger']['domain_not_empty'] = "Kan geen domein in gebruik verwijderen"; $lang['danger']['validity_missing'] = 'Wijs een geldigheidstermijn toe'; $lang['user']['loading'] = "Bezig met laden..."; @@ -242,10 +293,10 @@ $lang['edit']['scope'] = 'Omvang'; $lang['edit']['grant_types'] = 'Grant types'; $lang['edit']['redirect_uri'] = 'Doorstuur/Callback URL'; -$lang['edit']['hostname'] = 'Hostnaam'; +$lang['edit']['hostname'] = 'Hostname'; $lang['edit']['encryption'] = 'Versleuteling'; $lang['edit']['maxage'] = 'Maximale leeftijd van berichten (in dagen) die extern worden opgehaald
(0 = negeer leeftijd)'; -$lang['edit']['maxbytespersecond'] = 'Max. bytes per seconde (0 = onbeperkt)'; +$lang['edit']['maxbytespersecond'] = 'Max. bytes per seconde
(0 = onbeperkt)'; $lang['edit']['automap'] = 'Probeer mappen automatisch te koppelen ("Verstuurde items", "Verstuurd" => "Verstuurd" etc.)'; $lang['edit']['skipcrossduplicates'] = 'Sla duplicaten verspreid over mappen over (wie het eerst komt, het eerst maalt)'; $lang['add']['automap'] = 'Probeer mappen automatisch te koppelen ("Verstuurde items", "Verstuurd" => "Verstuurd" etc.)'; @@ -254,6 +305,7 @@ $lang['edit']['mins_interval'] = 'Interval (min)'; $lang['edit']['exclude'] = 'Sluit objecten uit (regex)'; $lang['edit']['save'] = 'Wijzigingen opslaan'; +$lang['edit']['username'] = 'Gebruikersnaam'; $lang['edit']['max_mailboxes'] = 'Max. mogelijke postvakken'; $lang['edit']['title'] = 'Wijzig object'; $lang['edit']['target_address'] = 'Doeladres(sen) (kommagescheiden)'; @@ -280,16 +332,17 @@ $lang['edit']['full_name'] = 'Volledige naam'; $lang['edit']['quota_mb'] = 'Quotum (MiB)'; $lang['edit']['sender_acl'] = 'Sta toe om te verzenden als'; +$lang['edit']['sender_acl_disabled'] = '↳ Verzendcontrole is uitgeschakeld'; $lang['edit']['previous'] = 'Vorige pagina'; $lang['edit']['unchanged_if_empty'] = 'Laat leeg wanneer onveranderd'; -$lang['edit']['dont_check_sender_acl'] = "Schakel verzendcontrole uit voor domein %s inclusief aliasdomeinen"; +$lang['edit']['dont_check_sender_acl'] = "Schakel verzendcontrole uit voor domein %s (inclusief aliasdomeinen)"; $lang['edit']['multiple_bookings'] = 'Meerdere boekingen'; $lang['edit']['kind'] = 'Soort'; $lang['edit']['resource'] = 'Hulpbron'; $lang['add']['syncjob'] = 'Voeg een nieuwe synchronisatietaak toe'; $lang['add']['syncjob_hint'] = 'Wees ervan bewust dat wachtwoorden onversleuteld moeten worden opgeslagen.'; -$lang['add']['hostname'] = 'Hostnaam'; +$lang['add']['hostname'] = 'Hostname'; $lang['add']['port'] = 'Poort'; $lang['add']['username'] = 'Gebruikersnaam'; $lang['add']['enc_method'] = 'Versleutelingsmethode'; @@ -301,8 +354,12 @@ $lang['edit']['delete2duplicates'] = 'Verwijder duplicaten op de bestemming'; $lang['edit']['delete1'] = 'Verwijder van oorsprong wanneer voltooid'; $lang['edit']['delete2'] = 'Verwijder berichten die zich niet in de oorsprong bevinden'; +$lang['add']['custom_params'] = 'Aangepaste parameters'; +$lang['add']['subscribeall'] = 'Abonneer op alle mappen'; +$lang['add']['timeout1'] = 'Time-out voor verbinding met externe host'; +$lang['add']['timeout2'] = 'Time-out voor verbinding met lokale host'; -$lang['add']['domain_matches_hostname'] = 'Domein %s komt overeen met hostnaam'; +$lang['add']['domain_matches_hostname'] = 'Domein %s komt overeen met hostname'; $lang['add']['domain'] = 'Domein'; $lang['add']['active'] = 'Actief'; $lang['add']['multiple_bookings'] = 'Meerdere boekingen'; @@ -332,6 +389,8 @@ $lang['add']['password_repeat'] = 'Herhaal wachtwoord'; $lang['add']['restart_sogo_hint'] = 'SOGo dient opnieuw opgestart te worden nadat een domein is toegevoegd'; $lang['add']['goto_null'] = 'Houd e-mail achterwege'; +$lang['add']['goto_ham'] = 'Leer als ham'; +$lang['add']['goto_spam'] = 'Leer als spam'; $lang['add']['validation_success'] = 'Succesvol gevalideerd'; $lang['add']['activate_filter_warn'] = 'Alle overige filters zullen worden gedeactiveerd zodra deze geactiveerd.'; $lang['add']['validate'] = 'Valideer'; @@ -510,10 +569,12 @@ $lang['success']['ui_texts'] = "Wijzigingen aan UI-labels zijn opgeslagen"; $lang['success']['reset_main_logo'] = "Het standaardlogo is hersteld"; $lang['success']['items_released'] = "Geselecteerde onderdelen zijn vrijgegeven"; +$lang['success']['item_released'] = "Onderdeel %s vrijgegeven"; $lang['danger']['imagick_exception'] = "Error: Er is een probleem opgetreden met Imagick tijdens het lezen van de afbeelding"; $lang['quarantine']['quarantine'] = "Quarantaine"; -$lang['quarantine']['qinfo'] = "Het quarantainesysteem slaat geweigerde e-mail op, terwijl het voor de afzender als niet ontvangen bestempeld is."; +$lang['quarantine']['learn_spam_delete'] = "Onthoud als spam en verwijder"; +$lang['quarantine']['qinfo'] = 'Het quarantainesysteem slaat geweigerde e-mail op, terwijl het voor de afzender als niet ontvangen bestempeld is.
"' . $lang['quarantine']['learn_spam_delete'] . '" traint het systeem om toekomstige soortgelijke e-mails direct als spam te classificeren.
Wees er van bewust dat wanneer er meerdere berichten worden onderzocht, dit mogelijk enige tijd kan duren.'; $lang['quarantine']['release'] = "Vrijgeven"; $lang['quarantine']['empty'] = 'Geen resultaten'; $lang['quarantine']['toggle_all'] = 'Selecteer alles'; @@ -531,20 +592,32 @@ $lang['quarantine']['text_plain_content'] = "Inhoud (tekst)"; $lang['quarantine']['text_from_html_content'] = "Inhoud (geconverteerde html)"; $lang['quarantine']['atts'] = "Bijlagen"; +$lang['danger']['fuzzy_learn_error'] = "Fuzzy hash training-fout: %s"; +$lang['danger']['spam_learn_error'] = "Spamtraining-fout: %s"; +$lang['success']['qlearn_spam'] = "Bericht %s werd als spam geclassificeerd en is verwijderd"; $lang['header']['quarantine'] = "Quarantaine"; $lang['header']['debug'] = "Debug"; +$lang['debug']['log_info'] = '

Mailcow in-geheugen logs worden verzameld in Redis-lijsten en worden elke minuut bijgesneden naar LOG_LINES (%d) om de stabiliteit te garanderen.
Logs in-geheugen zijn niet bedoeld om te blijven staan. Alle applicaties die in-geheugen loggen, worden ook naar het Docker-proces gelogd.
De in-geheugen logs zouden gebruikt moeten worden voor het oplossen van kleine problemen met containers.

Externe logs worden verzameld doormiddel van de API van de applicaties.

Statische logs zijn over het algemeen activiteitenlogs, die niet naar het Docker-proces worden gestuurd

'; + +$lang['debug']['in_memory_logs'] = 'Logs in-geheugen'; +$lang['debug']['external_logs'] = 'Externe logs'; +$lang['debug']['static_logs'] = 'Statische logs'; + $lang['quarantine']['release_body'] = "We hebben het oorspronkelijke bericht als eml-bestand meegestuurd."; $lang['danger']['release_send_failed'] = "Het volgende bericht kon niet worden vrijgegeven: %s"; $lang['quarantine']['release_subject'] = "Mogelijk schadelijk quarantaine-item %s"; +$lang['mailbox']['bcc_map'] = "BCC-kaart"; $lang['mailbox']['bcc_map_type'] = "BCC-type"; $lang['mailbox']['bcc_type'] = "BCC-type"; $lang['mailbox']['bcc_sender_map'] = "Afzenderkaarten"; $lang['mailbox']['bcc_rcpt_map'] = "Ontvangerkaarten"; $lang['mailbox']['bcc_local_dest'] = "Lokale bestemming"; -$lang['mailbox']['bcc_destinations'] = "BCC bestemming(en)"; +$lang['mailbox']['bcc_destinations'] = "BCC-bestemmingen"; +$lang['mailbox']['bcc_destination'] = "BCC-bestemming"; +$lang['edit']['bcc_dest_format'] = 'Een BCC-bestemming dient één geldig e-mailadres te zijn.'; $lang['mailbox']['bcc'] = "BCC"; $lang['mailbox']['bcc_maps'] = "BCC-kaarten"; From 140326012cfc3db8e9c746487b4893fb336a1acc Mon Sep 17 00:00:00 2001 From: Michael Kuron Date: Sun, 19 Aug 2018 10:07:44 +0200 Subject: [PATCH 020/109] Fix length of remote column in logs table Otherwise a full non-anonymized IPv6 address won't fit --- data/web/inc/init_db.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 95c54472ef..c318d6341e 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "16082018_2019"; + $db_version = "19082018_1004"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -376,7 +376,7 @@ function init_db_schema() { "call" => "TEXT", "user" => "VARCHAR(64) NOT NULL", "role" => "VARCHAR(32) NOT NULL", - "remote" => "VARCHAR(32) NOT NULL", + "remote" => "VARCHAR(39) NOT NULL", "time" => "INT(11) NOT NULL" ), "keys" => array( From d64a89473ea53fb49ad9dfd13af8ffd89cc417f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Tue, 21 Aug 2018 17:41:04 +0200 Subject: [PATCH 021/109] [Web] Add multiple DKIM at once (+ button to auto-fill missing keys) [Web] Duplicate DKIM keys from a single domain to a single or multiple domains [Web] WIP: Started Ratelimit rework [Web] Show RL in overview of mailbox and domains [Web] Move RL function out of mailbox functions file [Web] Some language fixes/changes --- data/web/admin.php | 80 ++++++++-- data/web/css/admin.css | 3 + data/web/css/mailcow.css | 1 + data/web/edit.php | 12 +- data/web/img/cow_mailcow.svg | 31 ++-- data/web/inc/functions.dkim.inc.php | 160 +++++++++++-------- data/web/inc/functions.mailbox.inc.php | 131 +--------------- data/web/inc/functions.ratelimit.inc.php | 188 +++++++++++++++++++++++ data/web/inc/prerequisites.inc.php | 1 + data/web/js/admin.js | 12 ++ data/web/js/debug.js | 2 +- data/web/js/mailbox.js | 16 ++ data/web/json_api.php | 72 ++++++++- data/web/lang/lang.de.php | 9 ++ data/web/lang/lang.en.php | 11 +- 15 files changed, 503 insertions(+), 226 deletions(-) create mode 100644 data/web/inc/functions.ratelimit.inc.php diff --git a/data/web/admin.php b/data/web/admin.php index d97bc141d2..d27344311c 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -208,6 +208,8 @@
@@ -229,7 +231,7 @@ else { ?>
-
+

Domain:

@@ -240,6 +242,8 @@ } foreach(mailbox('get', 'alias_domains', $domain) as $alias_domain) { if (!empty($dkim = dkim('details', $alias_domain))) { + $dkim_domains[] = $alias_domain; + ($GLOBALS['SHOW_DKIM_PRIV_KEYS'] === true) ?: $dkim['privkey'] = base64_encode('Please set $SHOW_DKIM_PRIV_KEYS to true to show DKIM private keys.'); ?>
@@ -261,7 +265,7 @@ else { ?>
diff --git a/data/web/css/admin.css b/data/web/css/admin.css index bd6ce1a5a2..a53d721c79 100644 --- a/data/web/css/admin.css +++ b/data/web/css/admin.css @@ -71,3 +71,6 @@ body.modal-open { .table-condensed .input-sm { width: 100%!important; } +.full-width-select { + width: 100%!important; +} diff --git a/data/web/css/mailcow.css b/data/web/css/mailcow.css index 56d129dde6..374688a199 100644 --- a/data/web/css/mailcow.css +++ b/data/web/css/mailcow.css @@ -101,6 +101,7 @@ legend { -ms-user-select: none -o-user-select: none; user-select: none; + font-size: 12pt; } .navbar .navbar-brand { padding-top: 5px; diff --git a/data/web/edit.php b/data/web/edit.php index 1efbbed3b2..c4903c2859 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -153,7 +153,7 @@ !empty($_GET["domain"])) { $domain = $_GET["domain"]; $result = mailbox('get', 'domain_details', $domain); - $rl = mailbox('get', 'ratelimit', $domain); + $rl = ratelimit('get', 'domain', $domain); $rlyhosts = relayhost('get'); if (!empty($result)) { ?> @@ -266,7 +266,7 @@
- +

@@ -329,7 +329,7 @@ !empty($_GET["aliasdomain"])) { $alias_domain = html_entity_decode(rawurldecode($_GET["aliasdomain"])); $result = mailbox('get', 'alias_domain_details', $alias_domain); - $rl = mailbox('get', 'ratelimit', $alias_domain); + $rl = ratelimit('get', 'domain', $alias_domain); if (!empty($result)) { ?>

@@ -368,7 +368,7 @@
- +

@@ -522,7 +522,7 @@
- +
diff --git a/data/web/img/cow_mailcow.svg b/data/web/img/cow_mailcow.svg index bea3f82630..d457782144 100644 --- a/data/web/img/cow_mailcow.svg +++ b/data/web/img/cow_mailcow.svg @@ -13,9 +13,9 @@ id="Layer_1" x="0px" y="0px" - width="446.22601" - height="396.02499" - viewBox="0 0 446.226 396.02499" + width="374.82101" + height="356.871" + viewBox="0 0 374.821 356.871" enable-background="new 0 0 1600 1200" xml:space="preserve" inkscape:version="0.91 r13725" @@ -36,19 +36,19 @@ inkscape:window-height="1138" id="namedview140" showgrid="false" - inkscape:zoom="1.1125147" - inkscape:cx="261.00704" - inkscape:cy="233.97883" + inkscape:zoom="1.5733334" + inkscape:cx="264.82839" + inkscape:cy="340.43592" inkscape:window-x="814" inkscape:window-y="0" inkscape:window-maximized="0" - inkscape:current-layer="Layer_1" + inkscape:current-layer="g3" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" /> 'danger', - 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_domain_or_sel_invalid' - ); - return false; - } - if ($redis->hGet('DKIM_PUB_KEYS', $domain)) { + $domains = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['domains'])); + $domains = array_filter($domains); + foreach ($domains as $domain) { + if (!is_valid_domain_name($domain) || !is_numeric($key_length)) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_domain_or_sel_invalid' + 'msg' => array('dkim_domain_or_sel_invalid', $domain) ); - return false; - } - if (!ctype_alnum($dkim_selector)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_domain_or_sel_invalid' - ); - return false; - } - $config = array( - "digest_alg" => "sha256", - "private_key_bits" => $key_length, - "private_key_type" => OPENSSL_KEYTYPE_RSA, - ); - if ($keypair_ressource = openssl_pkey_new($config)) { - $key_details = openssl_pkey_get_details($keypair_ressource); - $pubKey = implode(array_slice( - array_filter( - explode(PHP_EOL, $key_details['key']) - ), 1, -1) + continue; + } + if ($redis->hGet('DKIM_PUB_KEYS', $domain)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data), + 'msg' => array('dkim_domain_or_sel_invalid', $domain) ); - // Save public key and selector to redis - try { - $redis->hSet('DKIM_PUB_KEYS', $domain, $pubKey); - $redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector); + continue; } - catch (RedisException $e) { + if (!ctype_alnum($dkim_selector)) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => array('redis_error', $e) + 'msg' => array('dkim_domain_or_sel_invalid', $domain) ); - return false; + continue; } - // Export private key and save private key to redis - openssl_pkey_export($keypair_ressource, $privKey); - if (isset($privKey) && !empty($privKey)) { + $config = array( + "digest_alg" => "sha256", + "private_key_bits" => $key_length, + "private_key_type" => OPENSSL_KEYTYPE_RSA, + ); + if ($keypair_ressource = openssl_pkey_new($config)) { + $key_details = openssl_pkey_get_details($keypair_ressource); + $pubKey = implode(array_slice( + array_filter( + explode(PHP_EOL, $key_details['key']) + ), 1, -1) + ); + // Save public key and selector to redis try { - $redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, trim($privKey)); + $redis->hSet('DKIM_PUB_KEYS', $domain, $pubKey); + $redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector); } catch (RedisException $e) { $_SESSION['return'][] = array( @@ -77,23 +65,79 @@ function dkim($_action, $_data = null) { 'log' => array(__FUNCTION__, $_action, $_data), 'msg' => array('redis_error', $e) ); - return false; + continue; + } + // Export private key and save private key to redis + openssl_pkey_export($keypair_ressource, $privKey); + if (isset($privKey) && !empty($privKey)) { + try { + $redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, trim($privKey)); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data), + 'msg' => array('redis_error', $e) + ); + continue; + } } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data), + 'msg' => array('dkim_added', $domain) + ); + } + else { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data), + 'msg' => array('dkim_domain_or_sel_invalid', $domain) + ); + continue; } + } + break; + case 'duplicate': + if ($_SESSION['mailcow_cc_role'] != "admin") { $_SESSION['return'][] = array( - 'type' => 'success', + 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_added' + 'msg' => 'access_denied' ); - return true; + return false; } - else { + $from_domain = $_data['from_domain']; + $from_domain_dkim = dkim('details', $from_domain); + if (empty($from_domain_dkim)) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_domain_or_sel_invalid' + 'msg' => array('dkim_domain_or_sel_invalid', $from_domain) + ); + continue; + } + $to_domains = (array)$_data['to_domain']; + $to_domains = array_filter($to_domains); + foreach ($to_domains as $to_domain) { + try { + $redis->hSet('DKIM_PUB_KEYS', $to_domain, $from_domain_dkim['pubkey']); + $redis->hSet('DKIM_SELECTORS', $to_domain, $from_domain_dkim['dkim_selector']); + $redis->hSet('DKIM_PRIV_KEYS', $from_domain_dkim['dkim_selector'] . '.' . $to_domain, trim($from_domain_dkim['privkey'])); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data), + 'msg' => array('redis_error', $e) + ); + continue; + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data), + 'msg' => array('dkim_duplicated', $from_domain, $to_domain) ); - return false; } break; case 'import': @@ -129,7 +173,7 @@ function dkim($_action, $_data = null) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_domain_or_sel_invalid' + 'msg' => array('dkim_domain_or_sel_invalid', $domain) ); return false; } @@ -137,7 +181,7 @@ function dkim($_action, $_data = null) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_domain_or_sel_invalid' + 'msg' => array('dkim_domain_or_sel_invalid', $domain) ); return false; } @@ -145,7 +189,7 @@ function dkim($_action, $_data = null) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_domain_or_sel_invalid' + 'msg' => array('dkim_domain_or_sel_invalid', $domain) ); return false; } @@ -178,7 +222,7 @@ function dkim($_action, $_data = null) { $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data), - 'msg' => 'dkim_added' + 'msg' => array('dkim_added', $domain) ); return true; break; @@ -203,13 +247,7 @@ function dkim($_action, $_data = null) { } $dkimdata['dkim_txt'] = 'v=DKIM1;k=rsa;t=s;s=email;p=' . $redis_dkim_key_data; $dkimdata['dkim_selector'] = $redis->hGet('DKIM_SELECTORS', $_data); - $dkimdata['privkey'] = $redis->hGet('DKIM_PRIV_KEYS', $dkimdata['dkim_selector'] . $_data); - if ($GLOBALS['SHOW_DKIM_PRIV_KEYS'] === true) { - $dkimdata['privkey'] = base64_encode($redis->hGet('DKIM_PRIV_KEYS', $dkimdata['dkim_selector'] . '.' . $_data)); - } - else { - $dkimdata['privkey'] = base64_encode('Please set $SHOW_DKIM_PRIV_KEYS to true to show DKIM private keys.'); - } + $dkimdata['privkey'] = base64_encode($redis->hGet('DKIM_PRIV_KEYS', $dkimdata['dkim_selector'] . '.' . $_data)); } return $dkimdata; break; diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 92d55e8b0b..0db7259450 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1291,86 +1291,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); } break; - case 'ratelimit': - if (!is_array($_data['object'])) { - $objects = array(); - $objects[] = $_data['object']; - } - else { - $objects = $_data['object']; - } - foreach ($objects as $object) { - $rl_value = intval($_data['rl_value']); - $rl_frame = $_data['rl_frame']; - if (!in_array($rl_frame, array('s', 'm', 'h'))) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'rl_timeframe' - ); - continue; - } - if (is_valid_domain_name($object)) { - if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - continue; - } - } - elseif (filter_var($object, FILTER_VALIDATE_EMAIL)) { - if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - continue; - } - } - else { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - continue; - } - if (empty($rl_value)) { - try { - $redis->hDel('RL_VALUE', $object); - } - catch (RedisException $e) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('redis_error', $e) - ); - continue; - } - } - else { - try { - $redis->hSet('RL_VALUE', $object, $rl_value . ' / 1' . $rl_frame); - } - catch (RedisException $e) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('redis_error', $e) - ); - continue; - } - } - $_SESSION['return'][] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('object_modified', $object) - ); - } - break; case 'syncjob': if (!is_array($_data['id'])) { $ids = array(); @@ -2670,51 +2590,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } return $aliases; break; - case 'ratelimit': - if (is_valid_domain_name($_data)) { - if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - return false; - } - } - elseif (filter_var($_data, FILTER_VALIDATE_EMAIL)) { - if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - return false; - } - } - else { - return false; - } - try { - if ($rl_value = $redis->hGet('RL_VALUE', $_data)) { - $rl = explode(' / 1', $rl_value); - $data['value'] = $rl[0]; - $data['frame'] = $rl[1]; - return $data; - } - else { - return false; - } - } - catch (RedisException $e) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('redis_error', $e) - ); - return false; - } - return false; - break; case 'alias_details': $aliasdata = array(); $stmt = $pdo->prepare("SELECT @@ -2759,6 +2634,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { break; case 'alias_domain_details': $aliasdomaindata = array(); + $rl = ratelimit('get', 'domain', $_data); $stmt = $pdo->prepare("SELECT `alias_domain`, `target_domain`, @@ -2775,6 +2651,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $aliasdomaindata['alias_domain'] = $row['alias_domain']; $aliasdomaindata['target_domain'] = $row['target_domain']; $aliasdomaindata['active'] = $row['active']; + $aliasdomaindata['rl'] = $rl; $aliasdomaindata['active_int'] = $row['active_int']; $aliasdomaindata['created'] = $row['created']; $aliasdomaindata['modified'] = $row['modified']; @@ -2848,6 +2725,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { AND `domain` = :domain"); $stmt->execute(array(':domain' => $row['domain'])); $MailboxDataDomain = $stmt->fetch(PDO::FETCH_ASSOC); + $rl = ratelimit('get', 'domain', $_data); $domaindata['max_new_mailbox_quota'] = ($row['quota'] * 1048576) - $MailboxDataDomain['in_use']; if ($domaindata['max_new_mailbox_quota'] > ($row['maxquota'] * 1048576)) { $domaindata['max_new_mailbox_quota'] = ($row['maxquota'] * 1048576); @@ -2864,6 +2742,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $domaindata['relayhost'] = $row['relayhost']; $domaindata['backupmx'] = $row['backupmx']; $domaindata['backupmx_int'] = $row['backupmx_int']; + $domaindata['rl'] = $rl; $domaindata['active'] = $row['active']; $domaindata['active_int'] = $row['active_int']; $domaindata['relay_all_recipients'] = $row['relay_all_recipients']; @@ -2887,6 +2766,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } $mailboxdata = array(); + $rl = ratelimit('get', 'mailbox', $_data); $stmt = $pdo->prepare("SELECT `domain`.`backupmx`, `mailbox`.`username`, @@ -2918,6 +2798,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $mailboxdata['max_new_quota'] = ($DomainQuota['maxquota'] * 1048576); } $mailboxdata['username'] = $row['username']; + $mailboxdata['rl'] = $rl; $mailboxdata['is_relayed'] = $row['backupmx']; $mailboxdata['name'] = $row['name']; $mailboxdata['active'] = $row['active']; diff --git a/data/web/inc/functions.ratelimit.inc.php b/data/web/inc/functions.ratelimit.inc.php new file mode 100644 index 0000000000..8218a7bd5a --- /dev/null +++ b/data/web/inc/functions.ratelimit.inc.php @@ -0,0 +1,188 @@ + 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => 'rl_timeframe' + ); + continue; + } + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => 'access_denied' + ); + continue; + } + if (empty($rl_value)) { + try { + $redis->hDel('RL_VALUE', $object); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('redis_error', $e) + ); + continue; + } + } + else { + try { + $redis->hSet('RL_VALUE', $object, $rl_value . ' / 1' . $rl_frame); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('redis_error', $e) + ); + continue; + } + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('object_modified', $object) + ); + } + break; + case 'mailbox': + if (!is_array($_data['object'])) { + $objects = array(); + $objects[] = $_data['object']; + } + else { + $objects = $_data['object']; + } + foreach ($objects as $object) { + $rl_value = intval($_data['rl_value']); + $rl_frame = $_data['rl_frame']; + if (!in_array($rl_frame, array('s', 'm', 'h'))) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => 'rl_timeframe' + ); + continue; + } + if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object) + || ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin')) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => 'access_denied' + ); + continue; + } + if (empty($rl_value)) { + try { + $redis->hDel('RL_VALUE', $object); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('redis_error', $e) + ); + continue; + } + } + else { + try { + $redis->hSet('RL_VALUE', $object, $rl_value . ' / 1' . $rl_frame); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('redis_error', $e) + ); + continue; + } + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('object_modified', $object) + ); + } + break; + } + break; + case 'get': + switch ($_scope) { + case 'domain': + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { + return false; + } + try { + if ($rl_value = $redis->hGet('RL_VALUE', $_data)) { + $rl = explode(' / 1', $rl_value); + $data['value'] = $rl[0]; + $data['frame'] = $rl[1]; + return $data; + } + else { + return false; + } + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('redis_error', $e) + ); + return false; + } + return false; + break; + case 'mailbox': + if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data) + || ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin')) { + return false; + } + try { + if ($rl_value = $redis->hGet('RL_VALUE', $_data)) { + $rl = explode(' / 1', $rl_value); + $data['value'] = $rl[0]; + $data['frame'] = $rl[1]; + return $data; + } + else { + return false; + } + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), + 'msg' => array('redis_error', $e) + ); + return false; + } + return false; + break; + } + break; + } +} \ No newline at end of file diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index c07d4d2dd4..a5e03672f3 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -132,6 +132,7 @@ function get_remote_ip($anonymize = null) { require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.policy.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.dkim.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fwdhost.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.ratelimit.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.relayhost.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rsettings.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php'; diff --git a/data/web/js/admin.js b/data/web/js/admin.js index a4fe801e3f..24725f606a 100644 --- a/data/web/js/admin.js +++ b/data/web/js/admin.js @@ -9,6 +9,10 @@ jQuery(function($){ e.preventDefault(); $('#import_dkim_arrow').toggleClass("animation"); }); + $("#duplicate_dkim_legend").on('click', function(e) { + e.preventDefault(); + $('#duplicate_dkim_arrow').toggleClass("animation"); + }); $("#rspamd_preset_1").on('click', function(e) { e.preventDefault(); $("form[data-id=rsetting]").find("#desc").val(lang.rsettings_preset_1); @@ -19,6 +23,14 @@ jQuery(function($){ $("form[data-id=rsetting]").find("#desc").val(lang.rsettings_preset_2); $("form[data-id=rsetting]").find("#content").val('priority = 10;\nrcpt = "/postmaster@.*/";\nwant_spam = yes;'); }); + $("#dkim_missing_keys").on('click', function(e) { + e.preventDefault(); + var domains = []; + $('.dkim_missing').each(function() { + domains.push($(this).val()); + }); + $('#dkim_add_domains').val(domains); + }); function draw_domain_admins() { ft_domainadmins = FooTable.init('#domainadminstable', { "columns": [ diff --git a/data/web/js/debug.js b/data/web/js/debug.js index 37f457460a..bf08716730 100644 --- a/data/web/js/debug.js +++ b/data/web/js/debug.js @@ -171,7 +171,7 @@ jQuery(function($){ {"name":"user","title":"User"}, {"name":"role","title":"Role"}, {"name":"remote","title":"IP"}, - {"name":"msg","title":lang.message}, + {"name":"msg","title":lang.message,"style":{"word-break":"break-all"}}, {"name":"call","title":"Call","breakpoints": "all"}, ], "rows": $.ajax({ diff --git a/data/web/js/mailbox.js b/data/web/js/mailbox.js index 072eea63a1..95b4dc61e0 100644 --- a/data/web/js/mailbox.js +++ b/data/web/js/mailbox.js @@ -264,6 +264,7 @@ jQuery(function($){ }, }, {"name":"max_quota_for_mbox","title":lang.mailbox_quota,"breakpoints":"xs sm","style":{"width":"125px"}}, + {"name":"rl","title":"RL","breakpoints":"xs sm md","style":{"width":"125px"}}, {"name":"backupmx","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.backup_mx,"breakpoints":"xs sm"}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active}, {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"240px","width":"240px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} @@ -280,6 +281,13 @@ jQuery(function($){ item.aliases = item.aliases_in_domain + " / " + item.max_num_aliases_for_domain; item.mailboxes = item.mboxes_in_domain + " / " + item.max_num_mboxes_for_domain; item.quota = item.quota_used_in_domain + "/" + item.max_quota_for_domain; + if (!item.rl) { + item.rl = '∞'; + } else { + item.rl = $.map(item.rl, function(e){ + return e; + }).join('/1'); + } item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox); item.chkbox = ''; item.action = '
'; @@ -342,6 +350,7 @@ jQuery(function($){ }, }, {"name":"messages","filterable": false,"title":lang.msg_num,"breakpoints":"xs sm md"}, + {"name":"rl","title":"RL","breakpoints":"xs sm md","style":{"width":"125px"}}, {"name":"active","filterable": false,"title":lang.active}, {"name":"action","filterable": false,"sortable": false,"style":{"min-width":"250px","text-align":"right"},"type":"html","title":lang.action,"breakpoints":"xs sm md"} ], @@ -357,6 +366,13 @@ jQuery(function($){ $.each(data, function (i, item) { item.quota = item.quota_used + "/" + item.quota; item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox); + if (!item.rl) { + item.rl = '∞'; + } else { + item.rl = $.map(item.rl, function(e){ + return e; + }).join('/1'); + } item.chkbox = ''; if (role == "admin") { item.action = '
' + diff --git a/data/web/json_api.php b/data/web/json_api.php index bbf452f915..fba933c48f 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -135,6 +135,9 @@ function process_add_return($return) { case "dkim": process_add_return(dkim('add', $attr)); break; + case "dkim_duplicate": + process_add_return(dkim('duplicate', $attr)); + break; case "dkim_import": process_add_return(dkim('import', $attr)); break; @@ -181,6 +184,7 @@ function process_get_return($data) { break; } break; + case "domain": switch ($object) { case "all": @@ -208,6 +212,67 @@ function process_get_return($data) { } break; + case "rl-domain": + switch ($object) { + case "all": + $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')); + if (!empty($domains)) { + foreach ($domains as $domain) { + if ($details = ratelimit('get', 'domain', $domain)) { + $details['domain'] = $domain; + $data[] = $details; + } + else { + continue; + } + } + process_get_return($data); + } + else { + echo '{}'; + } + break; + + default: + $data = ratelimit('get', 'domain', $object); + process_get_return($data); + break; + } + break; + + case "rl-mbox": + switch ($object) { + case "all": + $domains = mailbox('get', 'domains'); + if (!empty($domains)) { + foreach ($domains as $domain) { + $mailboxes = mailbox('get', 'mailboxes', $domain); + if (!empty($mailboxes)) { + foreach ($mailboxes as $mailbox) { + if ($details = ratelimit('get', 'mailbox', $mailbox)) { + $details['mailbox'] = $mailbox; + $data[] = $details; + } + else { + continue; + } + } + } + } + process_get_return($data); + } + else { + echo '{}'; + } + break; + + default: + $data = ratelimit('get', 'mailbox', $object); + process_get_return($data); + break; + } + break; + case "relayhost": switch ($object) { case "all": @@ -968,8 +1033,11 @@ function process_edit_return($return) { case "domain": process_edit_return(mailbox('edit', 'domain', array_merge(array('domain' => $items), $attr))); break; - case "ratelimit": - process_edit_return(mailbox('edit', 'ratelimit', array_merge(array('object' => $items), $attr))); + case "rl-domain": + process_edit_return(ratelimit('edit', 'domain', array_merge(array('object' => $items), $attr))); + break; + case "rl-mbox": + process_edit_return(ratelimit('edit', 'mailbox', array_merge(array('object' => $items), $attr))); break; case "alias-domain": process_edit_return(mailbox('edit', 'alias_domain', array_merge(array('alias_domain' => $items), $attr))); diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php index 3125f2ae19..ef8805e3ea 100644 --- a/data/web/lang/lang.de.php +++ b/data/web/lang/lang.de.php @@ -65,6 +65,7 @@ $lang['danger']['dkim_domain_or_sel_invalid'] = 'DKIM-Domain oder Selektor nicht korrekt: %s'; $lang['success']['dkim_removed'] = 'DKIM-Key wurde entfernt'; $lang['success']['dkim_added'] = 'DKIM-Key wurde hinzugefügt'; +$lang['success']['dkim_duplicated'] = "DKIM-Key der Domain %s wurde auf Domain %s kopiert"; $lang['danger']['access_denied'] = 'Zugriff verweigert oder unvollständige/ungültige Daten'; $lang['danger']['domain_invalid'] = 'Domainname %s ist ungültig'; $lang['danger']['mailbox_quota_exceeds_domain_quota'] = 'Maximale Größe für Mailboxen überschreitet das Domain Speicherlimit'; @@ -249,6 +250,7 @@ $lang['mailbox']['description'] = 'Beschreibung'; $lang['mailbox']['resources'] = 'Ressourcen'; $lang['mailbox']['domains'] = 'Domains'; +$lang['admin']['domain_s'] = 'Domain(s)'; $lang['mailbox']['mailboxes'] = 'Mailboxen'; $lang['mailbox']['mailbox_quota'] = 'Max. Größe einer Mailbox'; $lang['mailbox']['domain_quota'] = 'Gesamtspeicher'; @@ -436,7 +438,9 @@ $lang['admin']['additional_rows'] = ' zusätzliche Zeilen geladen'; // parses to 'n additional rows were added' $lang['admin']['private_key'] = 'Private Key'; $lang['admin']['import'] = 'Importieren'; +$lang['admin']['duplicate'] = 'Duplizieren'; $lang['admin']['import_private_key'] = 'Private Key importieren'; +$lang['admin']['duplicate_dkim'] = 'DKIM duplizieren'; $lang['admin']['f2b_parameters'] = 'Fail2ban Parameter'; $lang['admin']['f2b_ban_time'] = 'Banzeit (s)'; $lang['admin']['f2b_max_attempts'] = 'Max. Versuche'; @@ -453,6 +457,11 @@ $lang['admin']['dkim_key_valid'] = 'Key gültig'; $lang['admin']['dkim_key_unused'] = 'Key ohne Zuweisung'; $lang['admin']['dkim_key_missing'] = 'Key fehlt'; +$lang['admin']['dkim_from'] = 'Von'; +$lang['admin']['dkim_to'] = 'Nach'; +$lang['admin']['dkim_from_title'] = 'Quellobjekt für Duplizierung'; +$lang['admin']['dkim_to_title'] = 'Ziel-Objekt(e) werden überschrieben'; +$lang['admin']['dkim_domains_wo_keys'] = "Domains mit fehlenden Keys auswählen"; $lang['admin']['add'] = 'Hinzufügen'; $lang['add']['add_domain_restart'] = 'Domain hinzufügen und SOGo neustarten'; $lang['add']['add_domain_only'] = 'Nur Domain hinzufügen'; diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php index ed2fbf25bc..6f345fb0b5 100644 --- a/data/web/lang/lang.en.php +++ b/data/web/lang/lang.en.php @@ -68,7 +68,8 @@ $lang['danger']['dkim_domain_or_sel_invalid'] = "DKIM domain or selector invalid: %s"; $lang['success']['dkim_removed'] = "DKIM key %s has been removed"; -$lang['success']['dkim_added'] = "DKIM key has been saved"; +$lang['success']['dkim_added'] = "DKIM key %s has been saved"; +$lang['success']['dkim_duplicated'] = "DKIM key for domain %s has been copied to %s"; $lang['danger']['access_denied'] = "Access denied or invalid form data"; $lang['danger']['domain_invalid'] = "Domain name %s is invalid"; $lang['danger']['mailbox_quota_exceeds_domain_quota'] = "Max. quota exceeds domain quota limit"; @@ -250,6 +251,7 @@ $lang['mailbox']['alias'] = 'Alias'; $lang['mailbox']['aliases'] = 'Aliases'; $lang['mailbox']['domains'] = 'Domains'; +$lang['admin']['domain_s'] = 'Domain/s'; $lang['mailbox']['mailboxes'] = 'Mailboxes'; $lang['mailbox']['resources'] = 'Resources'; $lang['mailbox']['mailbox_quota'] = 'Max. size of a mailbox'; @@ -445,7 +447,13 @@ $lang['admin']['additional_rows'] = ' additional rows were added'; // parses to 'n additional rows were added' $lang['admin']['private_key'] = 'Private key'; $lang['admin']['import'] = 'Import'; +$lang['admin']['duplicate'] = 'Duplicate'; $lang['admin']['import_private_key'] = 'Import private key'; +$lang['admin']['duplicate_dkim'] = 'Duplicate DKIM record'; +$lang['admin']['dkim_from'] = 'From'; +$lang['admin']['dkim_to'] = 'To'; +$lang['admin']['dkim_from_title'] = 'Source domain to copy data from'; +$lang['admin']['dkim_to_title'] = 'Target domain/s - will be overwritten'; $lang['admin']['f2b_parameters'] = 'Fail2ban parameters'; $lang['admin']['f2b_ban_time'] = 'Ban time (s)'; $lang['admin']['f2b_max_attempts'] = 'Max. attempts'; @@ -465,6 +473,7 @@ $lang['admin']['dkim_key_missing'] = 'Key missing'; $lang['admin']['dkim_add_key'] = 'Add ARC/DKIM key'; $lang['admin']['dkim_keys'] = 'ARC/DKIM keys'; +$lang['admin']['dkim_domains_wo_keys'] = "Select domains with missing keys"; $lang['admin']['add'] = 'Add'; $lang['add']['add_domain_restart'] = 'Add domain and restart SOGo'; $lang['add']['add_domain_only'] = 'Add domain only'; From d28fd4070b8b21ca58185e8af56e5142c7847004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Tue, 21 Aug 2018 21:06:22 +0200 Subject: [PATCH 022/109] [Web] Allow to set rate limit in add_domain modal [Web] Cleanup rate limits when deleting objects --- data/web/inc/functions.mailbox.inc.php | 16 +++++++++++++ data/web/inc/functions.ratelimit.inc.php | 4 ++-- data/web/lang/lang.de.php | 1 + data/web/lang/lang.en.php | 5 ++-- data/web/modals/mailbox.php | 30 ++++++++++++++++++------ 5 files changed, 45 insertions(+), 11 deletions(-) diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 0db7259450..13a3393406 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -415,6 +415,9 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); return false; } + if (!empty(intval($_data['rl_value']))) { + ratelimit('edit', 'domain', array('rl_value' => $rl_value, 'rl_frame' => $_data['rl_frame'], 'object' => $domain)); + } if (!empty($restart_sogo)) { $restart_reponse = json_decode(docker('post', 'sogo-mailcow', 'restart'), true); if ($restart_reponse['type'] == "success") { @@ -3094,6 +3097,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { )); try { $redis->hDel('DOMAIN_MAP', $domain); + $redis->hDel('RL_VALUE', $domain); } catch (RedisException $e) { $_SESSION['return'][] = array( @@ -3182,6 +3186,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { )); try { $redis->hDel('DOMAIN_MAP', $alias_domain); + $redis->hDel('RL_VALUE', $domain); } catch (RedisException $e) { $_SESSION['return'][] = array( @@ -3301,6 +3306,17 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ':address' => $gotos['address'] )); } + try { + $redis->hDel('RL_VALUE', $username); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('redis_error', $e) + ); + continue; + } $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), diff --git a/data/web/inc/functions.ratelimit.inc.php b/data/web/inc/functions.ratelimit.inc.php index 8218a7bd5a..2ead02e405 100644 --- a/data/web/inc/functions.ratelimit.inc.php +++ b/data/web/inc/functions.ratelimit.inc.php @@ -62,7 +62,7 @@ function ratelimit($_action, $_scope, $_data = null) { $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('object_modified', $object) + 'msg' => array('rl_saved', $object) ); } break; @@ -123,7 +123,7 @@ function ratelimit($_action, $_scope, $_data = null) { $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), - 'msg' => array('object_modified', $object) + 'msg' => array('rl_saved', $object) ); } break; diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php index ef8805e3ea..5741f968c5 100644 --- a/data/web/lang/lang.de.php +++ b/data/web/lang/lang.de.php @@ -42,6 +42,7 @@ $lang['danger']['domain_cannot_match_hostname'] = "Domain darf nicht dem Hostnamen entsprechen"; $lang['warning']['domain_added_sogo_failed'] = "Domain wurde hinzugefügt; SOGo konnte nicht neugestartet werden"; $lang['danger']['rl_timeframe'] = "Ratelimit Zeitraum ist inkorrekt"; +$lang['success']['rl_saved'] = "Ratelimit für Objekt %s wurde gesetzt"; $lang['success']['deleted_syncjobs'] = "Syncjobs gelöscht: %s"; $lang['success']['deleted_syncjob'] = "Syncjobs ID %s gelöscht"; $lang['success']['delete_filters'] = "Filter gelöscht: %s"; diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php index 6f345fb0b5..0a04f64998 100644 --- a/data/web/lang/lang.en.php +++ b/data/web/lang/lang.en.php @@ -41,7 +41,8 @@ $lang['danger']['filter_type'] = "Wrong filter type"; $lang['danger']['domain_cannot_match_hostname'] = "Domain cannot match hostname"; $lang['warning']['domain_added_sogo_failed'] = "Added domain but failed to restart SOGo, please check your server logs."; -$lang['danger']['rl_timeframe'] = "Ratelimit time frame is incorrect"; +$lang['danger']['rl_timeframe'] = "Rate limit time frame is incorrect"; +$lang['success']['rl_saved'] = "Rate limit for object %s saved"; $lang['success']['deleted_syncjobs'] = "Deleted syncjobs: %s"; $lang['success']['deleted_syncjob'] = "Deleted syncjob ID %s"; $lang['success']['delete_filters'] = "Deleted filters: %s"; @@ -489,7 +490,7 @@ $lang['admin']['rsetting_content'] = 'Rule content'; $lang['admin']['rsetting_none'] = 'No rule available'; $lang['admin']['rsetting_no_selection'] = 'Please select a rule'; -$lang['admin']['rsettings_preset_1'] = 'Disable all but DKIM and ratelimit for authenticated users'; +$lang['admin']['rsettings_preset_1'] = 'Disable all but DKIM and rate limit for authenticated users'; $lang['admin']['rsettings_preset_2'] = 'Postmasters want spam'; $lang['admin']['rsettings_insert_preset'] = 'Insert example preset "%s"'; $lang['admin']['rsetting_add_rule'] = 'Add rule'; diff --git a/data/web/modals/mailbox.php b/data/web/modals/mailbox.php index 94f881e4a8..b4a518930a 100644 --- a/data/web/modals/mailbox.php +++ b/data/web/modals/mailbox.php @@ -123,6 +123,28 @@
+
+
+
+ +
+
+
+
+
+ +
+ +
+
+ +
+
+
@@ -134,13 +156,7 @@
-
-
-
- -
-
-
+
From 1dea230b7b3912f9b0405a55bc4ac00d7a447dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Tue, 21 Aug 2018 21:23:06 +0200 Subject: [PATCH 023/109] [Web] Fix setting a rate limit when adding a domain --- data/web/inc/functions.mailbox.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 13a3393406..200ff0ae30 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -416,7 +416,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } if (!empty(intval($_data['rl_value']))) { - ratelimit('edit', 'domain', array('rl_value' => $rl_value, 'rl_frame' => $_data['rl_frame'], 'object' => $domain)); + ratelimit('edit', 'domain', array('rl_value' => $_data['rl_value'], 'rl_frame' => $_data['rl_frame'], 'object' => $domain)); } if (!empty($restart_sogo)) { $restart_reponse = json_decode(docker('post', 'sogo-mailcow', 'restart'), true); From 5b4b184778ac04bd90fb2745d6d5a19f8423d7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Thu, 23 Aug 2018 08:49:02 +0200 Subject: [PATCH 024/109] [Web] Fixes to mailcow logo (stickers are coming!) [Web] Fix adding multiple domain aliases, fixes #1705 --- data/web/img/cow_mailcow.svg | 316 ++++++++++++------------- data/web/inc/functions.mailbox.inc.php | 42 ++-- 2 files changed, 174 insertions(+), 184 deletions(-) diff --git a/data/web/img/cow_mailcow.svg b/data/web/img/cow_mailcow.svg index d457782144..6ba98e4660 100644 --- a/data/web/img/cow_mailcow.svg +++ b/data/web/img/cow_mailcow.svg @@ -1,5 +1,5 @@ - + image/svg+xml \ No newline at end of file + id="white_1_"> \ No newline at end of file diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 200ff0ae30..b17e204f58 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -637,7 +637,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); return false; } - foreach ($alias_domains as $i => &$alias_domain) { + foreach ($alias_domains as $i => $alias_domain) { $alias_domain = idn_to_ascii(strtolower(trim($alias_domain))); if (!is_valid_domain_name($alias_domain)) { $_SESSION['return'][] = array( @@ -680,30 +680,30 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); continue; } - } - $stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `active`) - VALUES (:alias_domain, :target_domain, :active)"); - $stmt->execute(array( - ':alias_domain' => $alias_domain, - ':target_domain' => $target_domain, - ':active' => $active - )); - try { - $redis->hSet('DOMAIN_MAP', $alias_domain, 1); - } - catch (RedisException $e) { + $stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `active`) + VALUES (:alias_domain, :target_domain, :active)"); + $stmt->execute(array( + ':alias_domain' => $alias_domain, + ':target_domain' => $target_domain, + ':active' => $active + )); + try { + $redis->hSet('DOMAIN_MAP', $alias_domain, 1); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('redis_error', $e) + ); + return false; + } $_SESSION['return'][] = array( - 'type' => 'danger', + 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('redis_error', $e) + 'msg' => array('aliasd_added', htmlspecialchars($alias_domain)) ); - return false; } - $_SESSION['return'][] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('aliasd_added', htmlspecialchars($alias_domain)) - ); break; case 'mailbox': $local_part = strtolower(trim($_data['local_part'])); From 4b09b5b1bb78cb5e5623954bc9680342e982a725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Peters?= Date: Sun, 26 Aug 2018 18:31:44 +0200 Subject: [PATCH 025/109] Update functions.mailbox.inc.php [Web] Remove invalid parameter from sieve_filters update query, fixes #1714 --- data/web/inc/functions.mailbox.inc.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index b17e204f58..dd40fa0eca 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -139,7 +139,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_name` = 'inactive' WHERE `username` = :username AND `filter_type` = :filter_type"); $stmt->execute(array( ':username' => $username, - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), ':filter_type' => $filter_type )); } @@ -3394,4 +3393,4 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox'))) { update_sogo_static_view(); } -} \ No newline at end of file +} From 5e56a46c8434ab4289687a20852678c99b02c429 Mon Sep 17 00:00:00 2001 From: sriccio Date: Tue, 28 Aug 2018 17:14:05 +0200 Subject: [PATCH 026/109] [dovecot] Enhancement to allow to use auth_default_realm When using auth_default_realm in dovecot configuration to setup a default domain name (to allow users to login with only a username instead of the full e-mail address), it breaks the compatibility with imapsync and sogo/sieve vacation. Adding a domain name to dovecot master user/pass fixes this. This never made it do the master branch, so I'm trying a PR again :) See: https://github.com/mailcow/mailcow-dockerized/pull/1331#issuecomment-386534307 --- data/Dockerfiles/dovecot/docker-entrypoint.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/dovecot/docker-entrypoint.sh b/data/Dockerfiles/dovecot/docker-entrypoint.sh index 70ffb701b1..50e91a1295 100755 --- a/data/Dockerfiles/dovecot/docker-entrypoint.sh +++ b/data/Dockerfiles/dovecot/docker-entrypoint.sh @@ -110,8 +110,9 @@ if [[ $(stat -c %U /var/vmail/) != "vmail" ]] ; then chown -R vmail:vmail /var/v # Create random master for SOGo sieve features RAND_USER=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 16 | head -n 1) RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 24 | head -n 1) -echo ${RAND_USER}:$(doveadm pw -s SHA1 -p ${RAND_PASS}) > /usr/local/etc/dovecot/dovecot-master.passwd -echo ${RAND_USER}:${RAND_PASS} > /etc/sogo/sieve.creds + +echo ${RAND_USER}@mailcow.local:$(doveadm pw -s SHA1 -p ${RAND_PASS}) > /usr/local/etc/dovecot/dovecot-master.passwd +echo ${RAND_USER}@mailcow.local:${RAND_PASS} > /etc/sogo/sieve.creds # 401 is user dovecot if [[ ! -f /mail_crypt/ecprivkey.pem || ! -f /mail_crypt/ecpubkey.pem ]]; then From e5b830adeaea28d7c5a79f72b72911cbda0cf668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Fri, 31 Aug 2018 23:33:55 +0200 Subject: [PATCH 027/109] [Dovecot] Fix shared namespace --- data/conf/dovecot/dovecot.conf | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index dd8db8a351..5fc0024d98 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -175,7 +175,7 @@ namespace { type = shared separator = / prefix = Shared/%%u/ - location = maildir:%%h/:CONTROL=~/Shared/%%u:INDEXPVT=~/Shared/%%u + location = maildir:%%h/:INDEX=~/Shared/%%u;CONTROL=~/Shared/%%u subscriptions = no list = children } diff --git a/docker-compose.yml b/docker-compose.yml index 871961a8ce..c1a3a1c8fb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -136,7 +136,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.34 + image: mailcow/sogo:1.35 build: ./data/Dockerfiles/sogo environment: - DBNAME=${DBNAME} From 8a88514dfde20b277ace76b87a126513e040fade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Fri, 7 Sep 2018 16:40:37 +0200 Subject: [PATCH 028/109] [SOGo] Declare /usr/lib/GNUstep/SOGo as volume [Nginx] Mount vols from sogo-mailcow to access /usr/lib/GNUstep/SOGo --- data/Dockerfiles/sogo/Dockerfile | 2 ++ docker-compose.yml | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index 30a06d2425..9d3965a724 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -49,4 +49,6 @@ COPY sogo-full.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg COPY acl.diff /acl.diff CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf +VOLUME /usr/lib/GNUstep/SOGo/ + RUN rm -rf /tmp/* /var/tmp/* diff --git a/docker-compose.yml b/docker-compose.yml index c1a3a1c8fb..353772eb7c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -136,7 +136,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.35 + image: mailcow/sogo:1.36 build: ./data/Dockerfiles/sogo environment: - DBNAME=${DBNAME} @@ -264,6 +264,8 @@ services: - ./data/assets/ssl/:/etc/ssl/mail/:ro - ./data/conf/nginx/:/etc/nginx/conf.d/:rw - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro + volumes_from: + - sogo-mailcow ports: - "${HTTPS_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}" - "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}" From afc18fd46935e201a9be85ab636f0ed0b77209be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 9 Sep 2018 09:47:47 +0200 Subject: [PATCH 029/109] [Rspamd] Update bad asn, move KEEP_SPAM to a custom lua function --- data/conf/rspamd/custom/bad_asn.map | 15 +++---- data/conf/rspamd/local.d/multimap.conf | 15 ------- data/conf/rspamd/lua/rspamd.local.lua | 54 ++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/data/conf/rspamd/custom/bad_asn.map b/data/conf/rspamd/custom/bad_asn.map index 8b7a440788..bc9e10f6b7 100644 --- a/data/conf/rspamd/custom/bad_asn.map +++ b/data/conf/rspamd/custom/bad_asn.map @@ -1,11 +1,10 @@ # High spam networks, disabled by default #201942:5 #Soltia Consulting SL - ipinfo.io -#16276:5 #OVH -#12876:5 #ONLINE S.A.S -#31034:5 -#12874:5 -#30823:5 -#197071:5 +#16276:2 #OVH +#12876:2 #ONLINE S.A.S +#31034:5 #ARUBA-ASN, IT +#12874:5 #FASTWEB, IT +#30823:3 #PKV spam #42831:5 #UK Dedicated Servers Ltd #29119:5 #Aire Networks del Mediterraneo S.L.U. #13335:5 #Cloudflare @@ -17,7 +16,7 @@ #14061:4 #Digitalocean #55293:4 #A2 Hosting #63018:4 #US Dedicated -#197518:2 +#197518:2 #RACKMARKT #44493:2 #46606:2 #49505:2 @@ -25,3 +24,5 @@ #197695:2 #198068:2 #43146:2 +#49100:4 +#39364:4 diff --git a/data/conf/rspamd/local.d/multimap.conf b/data/conf/rspamd/local.d/multimap.conf index da4afaf2d8..c27a9d6315 100644 --- a/data/conf/rspamd/local.d/multimap.conf +++ b/data/conf/rspamd/local.d/multimap.conf @@ -25,13 +25,6 @@ WHITELISTED_FWD_HOST { symbols_set = ["WHITELISTED_FWD_HOST"]; } -KEEP_SPAM { - type = "ip"; - map = "redis://KEEP_SPAM"; - action = "accept"; - symbols_set = ["KEEP_SPAM"]; -} - LOCAL_BL_ASN { require_symbols = "!MAILCOW_WHITE"; type = "asn"; @@ -40,11 +33,3 @@ LOCAL_BL_ASN { description = "Sender's ASN is on the local blacklist"; symbols_set = ["LOCAL_BL_ASN"]; } - -#SPOOFED_SENDER { -# type = "rcpt"; -# filter = "email:domain:tld"; -# map = "redis://DOMAIN_MAP"; -# require_symbols = "AUTH_NA | !RCVD_VIA_SMTP_AUTH"; -# symbols_set = ["SPOOFED_SENDER"]; -#} diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index 7c9efbb47d..92d223b119 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -7,6 +7,60 @@ rspamd_config.MAILCOW_AUTH = { end } +rspamd_config:register_symbol({ + name = 'KEEP_SPAM', + type = 'prefilter', + callback = function(task) + local util = require("rspamd_util") + local rspamd_logger = require "rspamd_logger" + local rspamd_ip = require 'rspamd_ip' + local uname = task:get_user() + if uname then + return false + end + local redis_params = rspamd_parse_redis_server('keep_spam') + local ip = task:get_from_ip() + local from_ip_string = ip:to_string() + ip_check_table = {from_ip_string} + local maxbits = 128 + local minbits = 32 + if ip:get_version() == 4 then + maxbits = 32 + minbits = 8 + end + for i=maxbits,minbits,-1 do + local nip = ip:apply_mask(i):to_string() .. "/" .. i + table.insert(ip_check_table, nip) + end + local function keep_spam_cb(err, data) + if err then + rspamd_logger.infox(rspamd_config, "keep_spam query request for ip %s returned invalid or empty data (\"%s\") or error (\"%s\")", ip, data, err) + return false + else + for k,v in pairs(data) do + if (v and v ~= userdata and v == '1') then + rspamd_logger.infox(rspamd_config, "found ip in keep_spam map, setting pre-result", v) + task:set_pre_result('accept', 'IP matched with forward hosts') + end + end + end + end + table.insert(ip_check_table, 1, 'KEEP_SPAM') + local redis_ret_user = rspamd_redis_make_request(task, + redis_params, -- connect params + 'KEEP_SPAM', -- hash key + false, -- is write + keep_spam_cb, --callback + 'HMGET', -- command + ip_check_table -- arguments + ) + if not redis_ret_user then + rspamd_logger.infox(rspamd_config, "cannot check keep_spam redis map") + end + end, + priority = 19 +}) + rspamd_config:register_symbol({ name = 'TAG_MOO', type = 'postfilter', From ad902f0ad8ab781d08583f4c69d6c70570531671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 9 Sep 2018 09:48:11 +0200 Subject: [PATCH 030/109] [SOGo] Remove HTTP server on port 9192 --- data/Dockerfiles/sogo/supervisord.conf | 7 ------- 1 file changed, 7 deletions(-) diff --git a/data/Dockerfiles/sogo/supervisord.conf b/data/Dockerfiles/sogo/supervisord.conf index 2a8895602c..1c1422b3b8 100644 --- a/data/Dockerfiles/sogo/supervisord.conf +++ b/data/Dockerfiles/sogo/supervisord.conf @@ -16,13 +16,6 @@ command=/usr/sbin/cron -f autorestart=true priority=2 -[program:sogo-webres] -command=/usr/bin/python -u -m SimpleHTTPServer 9192 -directory=/usr/lib/GNUstep/SOGo/ -user=sogo -autorestart=true -priority=4 - [program:bootstrap-sogo] command=/bootstrap-sogo.sh stdout_logfile=/dev/stdout From ea4a26eabfbb19c04a2bcdcb3e510147ab5c65c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 9 Sep 2018 09:51:37 +0200 Subject: [PATCH 031/109] [Nginx] Use SOGo web resources from local mount --- data/conf/nginx/site.conf | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/data/conf/nginx/site.conf b/data/conf/nginx/site.conf index d25d3b6155..9ea4c385bb 100644 --- a/data/conf/nginx/site.conf +++ b/data/conf/nginx/site.conf @@ -156,44 +156,19 @@ server { } location /SOGo.woa/WebServerResources/ { - proxy_pass http://sogo:9192/WebServerResources/; - proxy_set_header Host $http_host; - proxy_cache sogo; - proxy_cache_valid 200 1d; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - #alias /usr/lib/GNUstep/SOGo/WebServerResources/; - expires $expires; - allow all; + alias /usr/lib/GNUstep/SOGo/WebServerResources/; } location /.woa/WebServerResources/ { - proxy_pass http://sogo:9192/WebServerResources/; - proxy_set_header Host $http_host; - proxy_cache sogo; - proxy_cache_valid 200 1d; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - #alias /usr/lib/GNUstep/SOGo/WebServerResources/; - expires $expires; - allow all; + alias /usr/lib/GNUstep/SOGo/WebServerResources/; } location /SOGo/WebServerResources/ { - proxy_pass http://sogo:9192/WebServerResources/; - proxy_set_header Host $http_host; - proxy_cache sogo; - proxy_cache_valid 200 1d; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - #alias /usr/lib/GNUstep/SOGo/WebServerResources/; - allow all; + alias /usr/lib/GNUstep/SOGo/WebServerResources/; } location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) { - proxy_pass http://sogo:9192/$1.SOGo/Resources/$2; - proxy_set_header Host $http_host; - proxy_cache sogo; - proxy_cache_valid 200 1d; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - #alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2; + alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2; } include /etc/nginx/conf.d/site.*.custom; From c9554ca02291e64e56a786217de8d4b34b25544d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 9 Sep 2018 21:17:59 +0200 Subject: [PATCH 032/109] [Compose] Update watchdog image [Watchdog] Fix IP detection with multiple networks [Web] Show API field (no docs, no support, wip) [Web] haveibeenpwned.com implementation [Web] User and domain admin ACL (no docs, no support, wip) [Web] Some minor fixes --- data/Dockerfiles/watchdog/watchdog.sh | 27 ++- data/web/admin.php | 15 +- data/web/css/admin.css | 6 - data/web/css/mailbox.css | 3 - data/web/css/mailcow.css | 10 + data/web/edit.php | 68 +++++- data/web/inc/footer.inc.php | 117 ++-------- data/web/inc/functions.acl.inc.php | 216 ++++++++++++++++++ .../inc/functions.address_rewriting.inc.php | 32 +++ data/web/inc/functions.domain_admin.inc.php | 208 ++++++----------- data/web/inc/functions.inc.php | 50 +--- data/web/inc/functions.mailbox.inc.php | 17 +- data/web/inc/functions.policy.inc.php | 32 +-- data/web/inc/functions.ratelimit.inc.php | 8 + data/web/inc/init_db.inc.php | 34 ++- data/web/inc/prerequisites.inc.php | 3 +- data/web/inc/triggers.inc.php | 2 +- data/web/js/admin.js | 4 + data/web/js/api.js | 4 +- data/web/js/edit.js | 12 +- data/web/js/mailbox.js | 19 +- data/web/js/mailcow.js | 193 ++++++++++++++++ data/web/js/sha1.min.js | 1 + data/web/json_api.php | 6 + data/web/lang/lang.de.php | 23 +- data/web/lang/lang.en.php | 21 ++ data/web/mailbox.php | 15 +- data/web/modals/admin.php | 4 +- data/web/modals/mailbox.php | 7 +- data/web/modals/user.php | 4 +- data/web/quarantine.php | 2 +- data/web/user.php | 89 ++------ docker-compose.yml | 2 +- 33 files changed, 793 insertions(+), 461 deletions(-) create mode 100644 data/web/inc/functions.acl.inc.php create mode 100644 data/web/js/mailcow.js create mode 100644 data/web/js/sha1.min.js diff --git a/data/Dockerfiles/watchdog/watchdog.sh b/data/Dockerfiles/watchdog/watchdog.sh index c06abbc244..ec3d5aca2a 100755 --- a/data/Dockerfiles/watchdog/watchdog.sh +++ b/data/Dockerfiles/watchdog/watchdog.sh @@ -59,10 +59,10 @@ function mail_error() { log_msg "Sent notification email to ${1}" } - get_container_ip() { # ${1} is container CONTAINER_ID=() + CONTAINER_IPS=() CONTAINER_IP= LOOP_C=1 until [[ ${CONTAINER_IP} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || [[ ${LOOP_C} -gt 5 ]]; do @@ -72,15 +72,21 @@ get_container_ip() { # returned id can have multiple elements (if scaled), shuffle for random test CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf)) if [[ ! -z ${CONTAINER_ID} ]]; then - for matched_container in "${CONTAINER_ID[@]}"; do - CONTAINER_IP=$(curl --silent http://dockerapi:8080/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress') - # grep will do nothing if one of these vars is empty - [[ -z ${CONTAINER_IP} ]] && continue - [[ -z ${IPV4_NETWORK} ]] && continue - # only return ips that are part of our network - if ! grep -q ${IPV4_NETWORK} <(echo ${CONTAINER_IP}); then - CONTAINER_IP= - fi + for matched_container in "${CONTAINER_ID[@]}"; do + CONTAINER_IPS=($(curl --silent http://dockerapi:8080/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress')) + for ip_match in "${CONTAINER_IPS[@]}"; do + # grep will do nothing if one of these vars is empty + [[ -z ${ip_match} ]] && continue + [[ -z ${IPV4_NETWORK} ]] && continue + # only return ips that are part of our network + if ! grep -q ${IPV4_NETWORK} <(echo ${ip_match}); then + continue + else + CONTAINER_IP=${ip_match} + break + fi + done + [[ ! -z ${CONTAINER_IP} ]] && break done fi LOOP_C=$((LOOP_C + 1)) @@ -88,7 +94,6 @@ get_container_ip() { [[ ${LOOP_C} -gt 5 ]] && echo 240.0.0.0 || echo ${CONTAINER_IP} } -# Check functions nginx_checks() { err_count=0 diff_c=0 diff --git a/data/web/admin.php b/data/web/admin.php index d27344311c..749c96b64f 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -29,7 +29,7 @@
- +
@@ -44,7 +44,7 @@
-
+
:
@@ -76,12 +76,10 @@
-
- - - diff --git a/data/web/css/admin.css b/data/web/css/admin.css index a53d721c79..bc89f1ddf3 100644 --- a/data/web/css/admin.css +++ b/data/web/css/admin.css @@ -65,12 +65,6 @@ body.modal-open { font-size:9pt; background:transparent; } -.bootstrap-select { - width: auto!important; -} .table-condensed .input-sm { width: 100%!important; } -.full-width-select { - width: 100%!important; -} diff --git a/data/web/css/mailbox.css b/data/web/css/mailbox.css index da2e96e362..488150d39a 100644 --- a/data/web/css/mailbox.css +++ b/data/web/css/mailbox.css @@ -5,9 +5,6 @@ table.footable>tbody>tr.footable-empty>td { .pagination a { text-decoration: none !important; } -.panel panel-default { - overflow: visible !important; -} .btn-group { width: max-content; } diff --git a/data/web/css/mailcow.css b/data/web/css/mailcow.css index 374688a199..04d1b87449 100644 --- a/data/web/css/mailcow.css +++ b/data/web/css/mailcow.css @@ -148,3 +148,13 @@ nav .glyphicon { color: #5a5a5a; white-space: nowrap; } +.haveibeenpwned { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.full-width-select { + width: 100%!important; +} \ No newline at end of file diff --git a/data/web/edit.php b/data/web/edit.php index c4903c2859..417f2a7cec 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -92,7 +92,7 @@
- @@ -111,7 +111,7 @@
- +
@@ -140,6 +140,30 @@
+
+
+
+

ACL

+
+
+
+ +
+
+ +
+
+
+
- +

@@ -278,14 +302,14 @@
-
+
-
+
@@ -300,14 +324,14 @@
-
+
-
+
@@ -474,7 +498,7 @@
- +
@@ -527,6 +551,30 @@
+
+
+
+

ACL

+
+
+
+ +
+
+ +
+
+
+
- +
@@ -965,7 +1013,7 @@ + + diff --git a/data/web/modals/admin.php b/data/web/modals/admin.php index 7e8656e552..8bca0d87e5 100644 --- a/data/web/modals/admin.php +++ b/data/web/modals/admin.php @@ -67,7 +67,7 @@
- ".htmlspecialchars($domain).""; @@ -79,7 +79,7 @@
- +
diff --git a/data/web/modals/mailbox.php b/data/web/modals/mailbox.php index b4a518930a..160ab178c4 100644 --- a/data/web/modals/mailbox.php +++ b/data/web/modals/mailbox.php @@ -23,7 +23,7 @@
- ".htmlspecialchars($domain).""; @@ -48,10 +48,9 @@
- +
- - (Generate) +
diff --git a/data/web/modals/user.php b/data/web/modals/user.php index 62ccf1b1cc..5e0849e2fd 100644 --- a/data/web/modals/user.php +++ b/data/web/modals/user.php @@ -37,7 +37,7 @@
- +
@@ -155,7 +155,7 @@
- +
diff --git a/data/web/quarantine.php b/data/web/quarantine.php index 87f565a168..3e1935866a 100644 --- a/data/web/quarantine.php +++ b/data/web/quarantine.php @@ -18,7 +18,7 @@
-
+
- +
-
+
@@ -299,9 +280,7 @@
- +
@@ -309,7 +288,7 @@
-

- +
-
- +

@@ -354,26 +329,22 @@
- +
-
+
-
+
- +

@@ -381,28 +352,22 @@
- +
-
+
-
+
- -
- +
@@ -411,11 +376,9 @@
- +
-
+
- +
diff --git a/docker-compose.yml b/docker-compose.yml index 353772eb7c..cd0c69f8fa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -330,7 +330,7 @@ services: - /lib/modules:/lib/modules:ro watchdog-mailcow: - image: mailcow/watchdog:1.19 + image: mailcow/watchdog:1.21 # Debug #command: /watchdog.sh build: ./data/Dockerfiles/watchdog From 1a5ec7655ec24ec7c2093e09c858a20440a06835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 9 Sep 2018 21:52:35 +0200 Subject: [PATCH 033/109] [Compose] Update watchdog image --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index cd0c69f8fa..b8cdbeea8c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -330,7 +330,7 @@ services: - /lib/modules:/lib/modules:ro watchdog-mailcow: - image: mailcow/watchdog:1.21 + image: mailcow/watchdog:1.22 # Debug #command: /watchdog.sh build: ./data/Dockerfiles/watchdog From 29aeb5b85d52eb39805dbaf70c1e475b73dbd679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 9 Sep 2018 21:52:48 +0200 Subject: [PATCH 034/109] [Watchdog] Fix SOGo check, fixes #1750 --- data/Dockerfiles/watchdog/watchdog.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/data/Dockerfiles/watchdog/watchdog.sh b/data/Dockerfiles/watchdog/watchdog.sh index ec3d5aca2a..64795ad3c3 100755 --- a/data/Dockerfiles/watchdog/watchdog.sh +++ b/data/Dockerfiles/watchdog/watchdog.sh @@ -143,7 +143,6 @@ sogo_checks() { while [ ${err_count} -lt ${THRESHOLD} ]; do host_ip=$(get_container_ip sogo-mailcow) err_c_cur=${err_count} - /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /WebServerResources/css/theme-default.css -p 9192 -R md-default-theme 1>&2; err_count=$(( ${err_count} + $? )) /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /SOGo.index/ -p 20000 -R "SOGo\.MainUI" 1>&2; err_count=$(( ${err_count} + $? )) [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) From ce604232e26fdca6a39b00e69b717255c97d4852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Mon, 10 Sep 2018 10:56:32 +0200 Subject: [PATCH 035/109] [Web] Add missing data-acl for sync jobs --- data/web/mailbox.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/mailbox.php b/data/web/mailbox.php index 328808376f..7e865fbb71 100644 --- a/data/web/mailbox.php +++ b/data/web/mailbox.php @@ -184,7 +184,7 @@
-
+
- +
@@ -403,10 +403,10 @@
@@ -415,7 +415,7 @@
- +
- +
@@ -438,41 +438,41 @@
- +
- +
- +
/ - +
/ - +

- +
- +
- +
@@ -490,9 +490,9 @@ - [] - [whitelist] - [blacklist] + [] + [whitelist] + [blacklist] @@ -527,10 +527,10 @@
@@ -539,17 +539,17 @@
- +
- +
- +
- +
@@ -564,19 +564,19 @@
- +
- +

- @@ -586,7 +586,7 @@ ?>
- +
@@ -648,19 +648,19 @@
- +
- +
- - + +

- +

@@ -754,21 +754,21 @@
- +
- +
- +
- +
diff --git a/data/web/autodiscover.php b/data/web/autodiscover.php index f5bcbf8fec..9a167af771 100644 --- a/data/web/autodiscover.php +++ b/data/web/autodiscover.php @@ -27,7 +27,8 @@ } } -$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name; +//$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name; +$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, diff --git a/data/web/edit.php b/data/web/edit.php index 417f2a7cec..a2eb4fb728 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -39,13 +39,13 @@
- +
- +
- +
@@ -58,7 +58,7 @@
- +
@@ -92,7 +92,7 @@
- @@ -111,13 +111,13 @@
- +
- +
@@ -136,7 +136,7 @@
- +
@@ -159,7 +159,7 @@
- +
@@ -189,7 +189,7 @@
- +
- +
- +
- +
- +
- @@ -257,7 +257,7 @@
- +
@@ -280,17 +280,17 @@
- +
-
- +

@@ -304,15 +304,15 @@
- +
- + - +
@@ -326,15 +326,15 @@
- +
- + - +
@@ -362,7 +362,7 @@
- +
@@ -374,7 +374,7 @@
- +
@@ -382,17 +382,17 @@
- +
-
- +
- +
@@ -438,13 +438,13 @@
max. MiB
- +
-
- +
- +
@@ -524,7 +524,7 @@
- +
@@ -536,17 +536,17 @@
- +
-
- +
@@ -570,7 +570,7 @@
- +
@@ -589,19 +589,19 @@
- +
- +
- +
@@ -613,7 +613,7 @@
- +
@@ -636,13 +636,13 @@
- +
- @@ -652,7 +652,7 @@
- @@ -673,7 +673,7 @@
- +
@@ -719,7 +719,7 @@
- +
@@ -766,7 +766,7 @@
- +
@@ -933,7 +933,7 @@
- +
@@ -984,7 +984,7 @@
- +
diff --git a/data/web/inc/footer.inc.php b/data/web/inc/footer.inc.php index 14d2acf248..9e8daf7b81 100644 --- a/data/web/inc/footer.inc.php +++ b/data/web/inc/footer.inc.php @@ -59,7 +59,7 @@ function setLang(sel) { }); $('#u2f_status_auth').html('

Initializing, please wait...

'); $('#ConfirmTFAModal').on('shown.bs.modal', function(){ - $(this).find('#token').focus(); + $(this).find('input[name=token]').focus(); // If U2F if(document.getElementById("u2f_auth_data") !== null) { $.ajax({ @@ -146,7 +146,7 @@ function setLang(sel) { }); // CSRF - $('').attr('id', 'csrf_token').attr('name', 'csrf_token').appendTo('form'); + $('').attr('name', 'csrf_token').appendTo('form'); if (sessionStorage.scrollTop != "undefined") { $(window).scrollTop(sessionStorage.scrollTop); } diff --git a/data/web/inc/functions.docker.inc.php b/data/web/inc/functions.docker.inc.php index dbd26375c9..9c63eec7fa 100644 --- a/data/web/inc/functions.docker.inc.php +++ b/data/web/inc/functions.docker.inc.php @@ -2,10 +2,13 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $extra_headers = null) { global $DOCKER_TIMEOUT; $curl = curl_init(); - curl_setopt($curl, CURLOPT_HTTPHEADER,array( 'Content-Type: application/json' )); + curl_setopt($curl, CURLOPT_HTTPHEADER,array('Content-Type: application/json' )); + // We are using our mail certificates for dockerapi, the names will not match, the certs are trusted anyway + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); switch($action) { case 'get_id': - curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json'); + curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/json'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_POST, 0); curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT); @@ -38,7 +41,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex } return false; case 'containers': - curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json'); + curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/json'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_POST, 0); curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT); @@ -74,7 +77,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex break; case 'info': if (empty($service_name)) { - curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json'); + curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/json'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_POST, 0); curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT); @@ -82,7 +85,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex else { $container_id = docker('get_id', $service_name); if (ctype_xdigit($container_id)) { - curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/' . $container_id . '/json'); + curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/' . $container_id . '/json'); } else { // logger(array('return' => array( @@ -144,7 +147,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex if (!empty($attr1)) { $container_id = docker('get_id', $service_name); if (ctype_xdigit($container_id) && ctype_alnum($attr1)) { - curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/' . $container_id . '/' . $attr1); + curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/' . $container_id . '/' . $attr1); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT); if (!empty($attr2)) { @@ -158,19 +161,19 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex if ($response === false) { $err = curl_error($curl); curl_close($curl); - logger(array('return' => array(array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers), - 'msg' => $err, - )))); + // logger(array('return' => array(array( + // 'type' => 'danger', + // 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers), + // 'msg' => $err, + // )))); return $err; } else { curl_close($curl); - logger(array('return' => array(array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers), - )))); + // logger(array('return' => array(array( + // 'type' => 'success', + // 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers), + // )))); if (empty($response)) { return true; } diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 94eada4f3c..f915d5d077 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -18,6 +18,17 @@ function last_login($user) { return false; } } +function flush_memcached() { + try { + $m = new Memcached(); + $m->addServer('memcached', 11211); + $m->flush(); + } + catch ( Exception $e ) { + // Dunno + } +} + function logger($_data = false) { /* logger() will be called as last function @@ -510,6 +521,7 @@ function update_sogo_static_view() { $stmt = $pdo->query("REPLACE INTO _sogo_static_view SELECT * from sogo_view"); $stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');"); } + flush_memcached(); } function edit_user_account($_data) { global $lang; diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 8393c5f660..e06ac397f0 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -2776,6 +2776,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { `mailbox`.`active` AS `active_int`, CASE `mailbox`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, `mailbox`.`domain`, + `mailbox`.`maildir`, `mailbox`.`quota`, `quota2`.`bytes`, `attributes`, @@ -2806,6 +2807,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $mailboxdata['active'] = $row['active']; $mailboxdata['active_int'] = $row['active_int']; $mailboxdata['domain'] = $row['domain']; + $mailboxdata['maildir'] = $row['maildir']; $mailboxdata['quota'] = $row['quota']; $mailboxdata['attributes'] = json_decode($row['attributes'], true); $mailboxdata['quota_used'] = intval($row['bytes']); @@ -3054,6 +3056,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); continue; } + $exec_fields = array('cmd' => 'maildir_cleanup', 'maildir' => $domain); + $maildir_gc = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true); + if ($maildir_gc['type'] != 'success') { + $_SESSION['return'][] = array( + 'type' => 'warning', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'Could not move maildir to garbage collector: ' . $maildir_gc['msg'] + ); + } + return false; $stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain"); $stmt->execute(array( ':domain' => $domain, @@ -3078,17 +3090,17 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $stmt->execute(array( ':domain' => '%@'.$domain, )); - $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :domain"); + $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` LIKE :domain"); $stmt->execute(array( ':domain' => '%@'.$domain, )); - $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` = :domain"); + $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` LIKE :domain"); $stmt->execute(array( ':domain' => '%@'.$domain, )); $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain"); $stmt->execute(array( - ':domain' => '%@'.$domain, + ':domain' => $domain, )); $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :domain"); $stmt->execute(array( @@ -3227,6 +3239,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); continue; } + $maildir = mailbox('get', 'mailbox_details', $username)['maildir']; + $exec_fields = array('cmd' => 'maildir_cleanup', 'maildir' => $maildir); + $maildir_gc = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true); + if ($maildir_gc['type'] != 'success') { + $_SESSION['return'][] = array( + 'type' => 'warning', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'Could not move maildir to garbage collector: ' . $maildir_gc['msg'] + ); + } $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username"); $stmt->execute(array( ':username' => $username diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 58566ab735..571713be1c 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "01092018_1902"; + $db_version = "21092018_1902"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index aedda083fd..209c7184dc 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -35,7 +35,7 @@ $mins -= $hrs * 60; $offset = sprintf('%+d:%02d', $hrs*$sgn, $mins); -$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name; +$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, @@ -46,11 +46,20 @@ $pdo = new PDO($dsn, $database_user, $database_pass, $opt); } catch (PDOException $e) { +// Stop when SQL connection fails ?> -
Connection to database failed.

The following error was reported:
getMessage();?>
+
Connection to database failed.

The following error was reported:
getMessage();?>
+
Connection to dockerapi container failed.

The following error was reported:
-
+' + ' Test' + ' ' + lang.edit + '' + - ' ' + lang.remove + '' + + ' ' + lang.remove + '' + ''; item.chkbox = ''; }); } else if (table == 'forwardinghoststable') { $.each(data, function (i, item) { item.action = ''; if (item.keep_spam == "yes") { item.keep_spam = lang.no; @@ -145,7 +145,7 @@ jQuery(function($){ item.chkbox = ''; item.action = ''; }); diff --git a/data/web/js/api.js b/data/web/js/api.js index a573d7f441..e8293dbc68 100644 --- a/data/web/js/api.js +++ b/data/web/js/api.js @@ -71,7 +71,7 @@ $(document).ready(function() { }); // General API edit actions - $(document).on('click', '#edit_selected', function(e) { + $(document).on('click', "[data-action='edit_selected']", function(e) { e.preventDefault(); var id = $(this).data('id'); var api_url = $(this).data('api-url'); @@ -159,7 +159,7 @@ $(document).ready(function() { }); // General API add actions - $(document).on('click', '#add_item', function(e) { + $(document).on('click', "[data-action='add_item']", function(e) { e.preventDefault(); var id = $(this).data('id'); var api_url = $(this).data('api-url'); @@ -252,7 +252,7 @@ $(document).ready(function() { }); // General API delete actions - $(document).on('click', '#delete_selected', function(e) { + $(document).on('click', "[data-action='delete_selected']", function(e) { e.preventDefault(); var id = $(this).data('id'); // If clicked element #delete_selected has data-item attribute, it is added to "items" @@ -283,6 +283,7 @@ $(document).ready(function() { keyboard: false }) .one('click', '#IsConfirmed', function(e) { + if (is_active($('#IsConfirmed'))) { return false; } $.ajax({ type: "POST", dataType: "json", diff --git a/data/web/js/edit.js b/data/web/js/edit.js index f91f6b70dc..45690710ec 100644 --- a/data/web/js/edit.js +++ b/data/web/js/edit.js @@ -10,37 +10,43 @@ $(document).ready(function() { }); $("#disable_sender_check").click(function( event ) { if ($("form[data-id='editmailbox'] #disable_sender_check:checked").length > 0) { - $('#sender_acl').prop('disabled', true); - $('#sender_acl').selectpicker('refresh'); + $('#editSelectSenderACL').prop('disabled', true); + $('#editSelectSenderACL').selectpicker('refresh'); } else { - $('#sender_acl').prop('disabled', false); - $('#sender_acl').selectpicker('refresh'); + $('#editSelectSenderACL').prop('disabled', false); + $('#editSelectSenderACL').selectpicker('refresh'); } }); if ($("form[data-id='editalias'] .goto_checkbox:checked").length > 0) { $('#textarea_alias_goto').prop('disabled', true); } + $("#script_data").numberedtextarea({allowTabChar: true}); + + $("#mailbox-password-warning-close").click(function( event ) { + $('#mailbox-passwd-hidden-info').addClass('hidden'); + $('#mailbox-passwd-form-groups').removeClass('hidden'); + }); }); -if ($("#multiple_bookings_select").val() == "custom") { +if ($("#editSelectMultipleBookings").val() == "custom") { $("#multiple_bookings_custom_div").show(); - $("#multiple_bookings").val($("#multiple_bookings_custom").val()); + $('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val()); } -$("#multiple_bookings_select").change(function() { - $("#multiple_bookings").val($("#multiple_bookings_select").val()); - if ($("#multiple_bookings").val() == "custom") { +$("#editSelectMultipleBookings").change(function() { + $('input[name=multiple_bookings]').val($("#editSelectMultipleBookings").val()); + if ($('input[name=multiple_bookings]').val() == "custom") { $("#multiple_bookings_custom_div").show(); } else { $("#multiple_bookings_custom_div").hide(); } }); -if ($("#sender_acl option[value='\*']:selected").length > 0){ +if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){ $("#sender_acl_disabled").show(); } -$('#sender_acl').change(function() { - if ($("#sender_acl option[value='\*']:selected").length > 0){ +$('#editSelectSenderACL').change(function() { + if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){ $("#sender_acl_disabled").show(); } else { @@ -48,7 +54,7 @@ $('#sender_acl').change(function() { } }); $("#multiple_bookings_custom").bind("change keypress keyup blur", function() { - $("#multiple_bookings").val($("#multiple_bookings_custom").val()); + $('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val()); }); jQuery(function($){ // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript diff --git a/data/web/js/mailbox.js b/data/web/js/mailbox.js index 34f3ec20b5..836ec872ee 100644 --- a/data/web/js/mailbox.js +++ b/data/web/js/mailbox.js @@ -6,7 +6,6 @@ $(document).ready(function() { var domain_list = []; $.ajax({ dataType: 'json', - 'async': false, url: '/api/v1/get/domain/all', jsonp: false, error: function () { @@ -85,10 +84,10 @@ $(document).ready(function() { event.preventDefault(); $('[data-hibp]').trigger('input'); var random_passwd = Math.random().toString(36).slice(-8) - $('#password').prop('type', 'text'); - $('#password').val(random_passwd); - $('#password2').prop('type', 'text'); - $('#password2').val(random_passwd); + $(this).closest("form").find("input[name='password']").prop('type', 'text'); + $(this).closest("form").find("input[name='password2']").prop('type', 'text'); + $(this).closest("form").find("input[name='password']").val(random_passwd); + $(this).closest("form").find("input[name='password2']").val(random_passwd); }); $(".goto_checkbox").click(function( event ) { @@ -302,7 +301,7 @@ jQuery(function($){ item.action = '
'; if (role == "admin") { item.action += ' ' + lang.edit + '' + - ' ' + lang.remove + ''; + ' ' + lang.remove + ''; } else { item.action += ' ' + lang.edit + ''; @@ -386,14 +385,14 @@ jQuery(function($){ if (acl_data.login_as === 1) { item.action = ''; } else { item.action = ''; } item.in_use = '
' + @@ -461,7 +460,7 @@ jQuery(function($){ } item.action = ''; item.chkbox = ''; item.name = escapeHtml(item.name); @@ -520,7 +519,7 @@ jQuery(function($){ $.each(data, function (i, item) { item.action = ''; item.chkbox = ''; item.local_dest = escapeHtml(item.local_dest); @@ -583,7 +582,7 @@ jQuery(function($){ item.recipient_map_new = escapeHtml(item.recipient_map_new); item.action = ''; item.chkbox = ''; }); @@ -638,7 +637,7 @@ jQuery(function($){ $.each(data, function (i, item) { item.action = ''; item.chkbox = ''; item.goto = escapeHtml(item.goto.replace(/,/g, " ")); @@ -713,7 +712,7 @@ jQuery(function($){ $.each(data, function (i, item) { item.action = '' + '
'; item.chkbox = ''; @@ -781,7 +780,7 @@ jQuery(function($){ item.server_w_port = escapeHtml(item.user1) + '@' + item.host1 + ':' + item.port1; item.action = ''; item.chkbox = ''; if (item.is_running == 1) { @@ -852,7 +851,7 @@ jQuery(function($){ item.filter_type = '
' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '
' item.action = ''; item.chkbox = '' }); diff --git a/data/web/js/mailcow.js b/data/web/js/mailcow.js index d9019c235d..89cfabf53d 100644 --- a/data/web/js/mailcow.js +++ b/data/web/js/mailcow.js @@ -110,7 +110,7 @@ $(document).ready(function() { // Disable disallowed inputs $('[data-acl="0"]').each(function(){ - if ($(this).attr('class') == 'btn-group') { + if ($(this).hasClass('btn-group')) { $(this).find('a').each(function(){ $(this).removeClass('dropdown-toggle') .removeAttr('data-toggle') @@ -124,7 +124,7 @@ $(document).ready(function() { $(this).find('button').each(function() { $(this).attr("disabled", true); }); - } else if ($(this).attr('class') == 'input-group') { + } else if ($(this).hasClass('input-group')) { $(this).find('input').each(function() { $(this).removeClass('dropdown-toggle') .removeAttr('data-toggle') diff --git a/data/web/js/quarantine.js b/data/web/js/quarantine.js index 21ec9ddc9d..f84380990a 100644 --- a/data/web/js/quarantine.js +++ b/data/web/js/quarantine.js @@ -28,7 +28,7 @@ jQuery(function($){ $.each(data, function (i, item) { item.action = ''; item.chkbox = ''; }); diff --git a/data/web/js/user.js b/data/web/js/user.js index 226d039a48..5649d6c6df 100644 --- a/data/web/js/user.js +++ b/data/web/js/user.js @@ -64,7 +64,7 @@ jQuery(function($){ $.each(data, function (i, item) { if (acl_data.spam_alias === 1) { item.action = ''; item.chkbox = ''; item.address = escapeHtml(item.address); @@ -123,7 +123,7 @@ jQuery(function($){ if (acl_data.syncjobs === 1) { item.action = ''; item.chkbox = ''; } diff --git a/data/web/mailbox.php b/data/web/mailbox.php index 7e865fbb71..70d8dbb68a 100644 --- a/data/web/mailbox.php +++ b/data/web/mailbox.php @@ -44,10 +44,10 @@ @@ -74,10 +74,10 @@
@@ -101,10 +101,10 @@ @@ -134,10 +134,10 @@ @@ -161,10 +161,10 @@ @@ -188,12 +188,12 @@ @@ -218,13 +218,13 @@ @@ -249,13 +249,13 @@ @@ -277,10 +277,10 @@ diff --git a/data/web/modals/admin.php b/data/web/modals/admin.php index 8bca0d87e5..2cce623e64 100644 --- a/data/web/modals/admin.php +++ b/data/web/modals/admin.php @@ -17,13 +17,13 @@
- +
- +
@@ -35,7 +35,7 @@
- +
@@ -60,7 +60,7 @@
- + a-z A-Z - _ .
@@ -79,13 +79,13 @@
- +
- +
@@ -97,7 +97,7 @@
- +
@@ -115,11 +115,11 @@