diff --git a/.github/workflows/close_old_issues_and_prs.yml b/.github/workflows/close_old_issues_and_prs.yml index 21ab3a8e..64002617 100644 --- a/.github/workflows/close_old_issues_and_prs.yml +++ b/.github/workflows/close_old_issues_and_prs.yml @@ -14,7 +14,7 @@ jobs: pull-requests: write steps: - name: Mark/Close Stale Issues and Pull Requests 🗑️ - uses: actions/stale@v8.0.0 + uses: actions/stale@v7.0.0 with: repo-token: ${{ secrets.STALE_ACTION_PAT }} days-before-stale: 60 diff --git a/data/Dockerfiles/dockerapi/dockerapi.py b/data/Dockerfiles/dockerapi/dockerapi.py index 1ab651b5..9e699c22 100644 --- a/data/Dockerfiles/dockerapi/dockerapi.py +++ b/data/Dockerfiles/dockerapi/dockerapi.py @@ -380,15 +380,7 @@ class DockerUtils: if 'maildir' in request_json: for container in self.docker_client.containers.list(filters={"id": container_id}): sane_name = re.sub(r'\W+', '', request_json['maildir']) - vmail_name = request_json['maildir'].replace("'", "'\\''") - cmd_vmail = "if [[ -d '/var/vmail/" + vmail_name + "' ]]; then /bin/mv '/var/vmail/" + vmail_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi" - index_name = request_json['maildir'].split("/") - if len(index_name) > 1: - index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''") - cmd_vmail_index = "if [[ -d '/var/vmail_index/" + index_name + "' ]]; then /bin/mv '/var/vmail_index/" + index_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "_index'; fi" - cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index] - else: - cmd = ["/bin/bash", "-c", cmd_vmail] + cmd = ["/bin/bash", "-c", "if [[ -d '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' ]]; then /bin/mv '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"] maildir_cleanup = container.exec_run(cmd, user='vmail') return exec_run_handler('generic', maildir_cleanup) # api call: container_post - post_action: exec - cmd: rspamd - task: worker_password diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index 5c5cf99c..13b5d317 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -80,40 +80,28 @@ def refreshF2boptions(): global f2boptions global quit_now global exit_code - - f2boptions = {} - if not r.get('F2B_OPTIONS'): - f2boptions['ban_time'] = r.get('F2B_BAN_TIME') - f2boptions['max_ban_time'] = r.get('F2B_MAX_BAN_TIME') - f2boptions['ban_time_increment'] = r.get('F2B_BAN_TIME_INCREMENT') - f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS') - f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') - f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') - f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6') + f2boptions = {} + f2boptions['ban_time'] = int + f2boptions['max_attempts'] = int + f2boptions['retry_window'] = int + f2boptions['netban_ipv4'] = int + f2boptions['netban_ipv6'] = int + f2boptions['ban_time'] = r.get('F2B_BAN_TIME') or 1800 + f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS') or 10 + f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') or 600 + f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') or 32 + f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6') or 128 + r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False)) else: try: + f2boptions = {} f2boptions = json.loads(r.get('F2B_OPTIONS')) except ValueError: print('Error loading F2B options: F2B_OPTIONS is not json') quit_now = True exit_code = 2 - verifyF2boptions(f2boptions) - r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False)) - -def verifyF2boptions(f2boptions): - verifyF2boption(f2boptions,'ban_time', 1800) - verifyF2boption(f2boptions,'max_ban_time', 10000) - verifyF2boption(f2boptions,'ban_time_increment', True) - verifyF2boption(f2boptions,'max_attempts', 10) - verifyF2boption(f2boptions,'retry_window', 600) - verifyF2boption(f2boptions,'netban_ipv4', 32) - verifyF2boption(f2boptions,'netban_ipv6', 128) - -def verifyF2boption(f2boptions, f2boption, f2bdefault): - f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault - def refreshF2bregex(): global f2bregex global quit_now @@ -572,7 +560,6 @@ def ban(address): global lock refreshF2boptions() BAN_TIME = int(f2boptions['ban_time']) - BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) MAX_ATTEMPTS = int(f2boptions['max_attempts']) RETRY_WINDOW = int(f2boptions['retry_window']) NETBAN_IPV4 = '/' + str(f2boptions['netban_ipv4']) @@ -609,10 +596,11 @@ def ban(address): bans[net]['attempts'] += 1 bans[net]['last_attempt'] = time.time() + active_window = time.time() - bans[net]['last_attempt'] + if bans[net]['attempts'] >= MAX_ATTEMPTS: cur_time = int(round(time.time())) - NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] - logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 )) + logCrit('Banning %s for %d minutes' % (net, BAN_TIME / 60)) if type(ip) is ipaddress.IPv4Address: with lock: if backend == 'iptables': @@ -640,7 +628,7 @@ def ban(address): ban_dict = get_ban_ip_dict(net, "ip6") nft_exec_dict(ban_dict) - r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + NET_BAN_TIME) + r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + BAN_TIME) else: logWarn('%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net)) @@ -685,8 +673,7 @@ def unban(net): r.hdel('F2B_ACTIVE_BANS', '%s' % net) r.hdel('F2B_QUEUE_UNBAN', '%s' % net) if net in bans: - bans[net]['attempts'] = 0 - bans[net]['ban_counter'] += 1 + del bans[net] def permBan(net, unban=False): global lock @@ -853,7 +840,7 @@ def watch(): logWarn('%s matched rule id %s (%s)' % (addr, rule_id, item['data'])) ban(addr) except Exception as ex: - logWarn('Error reading log line from pubsub: %s' % ex) + logWarn('Error reading log line from pubsub') quit_now = True exit_code = 2 @@ -959,8 +946,6 @@ def autopurge(): time.sleep(10) refreshF2boptions() BAN_TIME = int(f2boptions['ban_time']) - MAX_BAN_TIME = int(f2boptions['max_ban_time']) - BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) MAX_ATTEMPTS = int(f2boptions['max_attempts']) QUEUE_UNBAN = r.hgetall('F2B_QUEUE_UNBAN') if QUEUE_UNBAN: @@ -968,9 +953,7 @@ def autopurge(): unban(str(net)) for net in bans.copy(): if bans[net]['attempts'] >= MAX_ATTEMPTS: - NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] - TIME_SINCE_LAST_ATTEMPT = time.time() - bans[net]['last_attempt'] - if TIME_SINCE_LAST_ATTEMPT > NET_BAN_TIME or TIME_SINCE_LAST_ATTEMPT > MAX_BAN_TIME: + if time.time() - bans[net]['last_attempt'] > BAN_TIME: unban(net) def isIpNetwork(address): diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index 0ff47206..c8713e04 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.2-fpm-alpine3.17 +FROM php:8.1-fpm-alpine3.17 LABEL maintainer "Andre Peters " # renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced @@ -12,7 +12,7 @@ ARG MEMCACHED_PECL_VERSION=3.2.0 # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced ARG REDIS_PECL_VERSION=5.3.7 # renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced -ARG COMPOSER_VERSION=2.5.5 +ARG COMPOSER_VERSION=2.5.4 RUN apk add -U --no-cache autoconf \ aspell-dev \ @@ -52,7 +52,6 @@ RUN apk add -U --no-cache autoconf \ libxpm-dev \ libzip \ libzip-dev \ - linux-headers \ make \ mysql-client \ openldap-dev \ @@ -76,7 +75,7 @@ RUN apk add -U --no-cache autoconf \ --with-webp \ --with-xpm \ --with-avif \ - && docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets sysvsem zip bcmath gmp \ + && docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets zip bcmath gmp \ && docker-php-ext-configure imap --with-imap --with-imap-ssl \ && docker-php-ext-install -j 4 imap \ && curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER_VERSION} \ @@ -100,7 +99,6 @@ RUN apk add -U --no-cache autoconf \ libxml2-dev \ libxpm-dev \ libzip-dev \ - linux-headers \ make \ openldap-dev \ pcre-dev \ diff --git a/data/assets/nextcloud/nextcloud.conf b/data/assets/nextcloud/nextcloud.conf index eda2c779..3755c4a7 100644 --- a/data/assets/nextcloud/nextcloud.conf +++ b/data/assets/nextcloud/nextcloud.conf @@ -24,7 +24,7 @@ server { add_header X-Download-Options "noopen" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Permitted-Cross-Domain-Policies "none" always; - add_header X-Robots-Tag "noindex, nofollow" always; + add_header X-Robots-Tag "none" always; add_header X-XSS-Protection "1; mode=block" always; fastcgi_hide_header X-Powered-By; diff --git a/data/web/api/openapi.yaml b/data/web/api/openapi.yaml index 65bd1211..5e07c4b3 100644 --- a/data/web/api/openapi.yaml +++ b/data/web/api/openapi.yaml @@ -3176,10 +3176,8 @@ paths: example: attr: ban_time: "86400" - ban_time_increment: "1" blacklist: "10.100.6.5/32,10.100.8.4/32" max_attempts: "5" - max_ban_time: "86400" netban_ipv4: "24" netban_ipv6: "64" retry_window: "600" @@ -3193,17 +3191,11 @@ paths: description: the backlisted ips or hostnames separated by comma type: string ban_time: - description: the time an ip should be banned + description: the time a ip should be banned type: number - ban_time_increment: - description: if the time of the ban should increase each time - type: boolean max_attempts: description: the maximum numbe of wrong logins before a ip is banned type: number - max_ban_time: - description: the maximum time an ip should be banned - type: number netban_ipv4: description: the networks mask to ban for ipv4 type: number @@ -4121,12 +4113,10 @@ paths: response: value: ban_time: 604800 - ban_time_increment: 1 blacklist: |- 45.82.153.37/32 92.118.38.52/32 max_attempts: 1 - max_ban_time: 604800 netban_ipv4: 32 netban_ipv6: 128 perm_bans: diff --git a/data/web/css/build/011-datatables.css b/data/web/css/build/011-datatables.css index d262f07c..d03514ff 100644 --- a/data/web/css/build/011-datatables.css +++ b/data/web/css/build/011-datatables.css @@ -342,10 +342,6 @@ div.dataTables_wrapper div.dt-row { position: relative; } -div.dataTables_wrapper span.sorting-value { - display: none; -} - div.dataTables_scrollHead table.dataTable { margin-bottom: 0 !important; } diff --git a/data/web/css/site/mailbox.css b/data/web/css/site/mailbox.css index e896abca..f62ead31 100644 --- a/data/web/css/site/mailbox.css +++ b/data/web/css/site/mailbox.css @@ -66,6 +66,4 @@ table tbody tr td input[type="checkbox"] { padding: .2em .4em .3em !important; background-color: #ececec!important; } -.badge.bg-info .bi { - font-size: inherit; -} + diff --git a/data/web/css/themes/mailcow-darkmode.css b/data/web/css/themes/mailcow-darkmode.css index abaa7499..6e0db0e9 100644 --- a/data/web/css/themes/mailcow-darkmode.css +++ b/data/web/css/themes/mailcow-darkmode.css @@ -20,11 +20,6 @@ legend { background-color: #7a7a7a !important; border-color: #5c5c5c !important; } -.btn-dark { - color: #000 !important;; - background-color: #f6f6f6 !important;; - border-color: #ddd !important;; -} .btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle { border-color: #7a7a7a !important; } @@ -304,22 +299,22 @@ a:hover { } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover { background-color: #7a7a7a !important; } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before { background-color: #7a7a7a !important; border: 1.5px solid #5c5c5c !important; color: #fff !important; } -table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, +table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before { background-color: #949494; } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, -table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, +table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { background-color: #444444; } @@ -332,7 +327,7 @@ table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { } .btn.btn-outline-secondary { color: #fff !important; - border-color: #7a7a7a !important; + border-color: #7a7a7a !important; } .btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { background-color: #9b9b9b !important; diff --git a/data/web/inc/functions.fail2ban.inc.php b/data/web/inc/functions.fail2ban.inc.php index 2c4aa41d..2a7f11e8 100644 --- a/data/web/inc/functions.fail2ban.inc.php +++ b/data/web/inc/functions.fail2ban.inc.php @@ -239,9 +239,7 @@ function fail2ban($_action, $_data = null) { $is_now = fail2ban('get'); if (!empty($is_now)) { $ban_time = intval((isset($_data['ban_time'])) ? $_data['ban_time'] : $is_now['ban_time']); - $ban_time_increment = (isset($_data['ban_time_increment']) && $_data['ban_time_increment'] == "1") ? 1 : 0; $max_attempts = intval((isset($_data['max_attempts'])) ? $_data['max_attempts'] : $is_now['max_attempts']); - $max_ban_time = intval((isset($_data['max_ban_time'])) ? $_data['max_ban_time'] : $is_now['max_ban_time']); $retry_window = intval((isset($_data['retry_window'])) ? $_data['retry_window'] : $is_now['retry_window']); $netban_ipv4 = intval((isset($_data['netban_ipv4'])) ? $_data['netban_ipv4'] : $is_now['netban_ipv4']); $netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']); @@ -258,8 +256,6 @@ function fail2ban($_action, $_data = null) { } $f2b_options = array(); $f2b_options['ban_time'] = ($ban_time < 60) ? 60 : $ban_time; - $f2b_options['ban_time_increment'] = ($ban_time_increment == 1) ? true : false; - $f2b_options['max_ban_time'] = ($max_ban_time < 60) ? 60 : $max_ban_time; $f2b_options['netban_ipv4'] = ($netban_ipv4 < 8) ? 8 : $netban_ipv4; $f2b_options['netban_ipv6'] = ($netban_ipv6 < 8) ? 8 : $netban_ipv6; $f2b_options['netban_ipv4'] = ($netban_ipv4 > 32) ? 32 : $netban_ipv4; diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 4dc2418c..de1855fa 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -1015,58 +1015,20 @@ function formatBytes($size, $precision = 2) { } return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; } -function update_sogo_static_view($mailbox = null) { +function update_sogo_static_view() { if (getenv('SKIP_SOGO') == "y") { return true; } global $pdo; global $lang; - - $mailbox_exists = false; - if ($mailbox !== null) { - // Check if the mailbox exists - $stmt = $pdo->prepare("SELECT username FROM mailbox WHERE username = :mailbox AND active = '1'"); - $stmt->execute(array(':mailbox' => $mailbox)); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - if ($row){ - $mailbox_exists = true; - } + $stmt = $pdo->query("SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_NAME = 'sogo_view'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`) + SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view"); + $stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');"); } - - $query = "REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`) - SELECT - mailbox.username, - mailbox.domain, - mailbox.username, - IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.force_pw_update')) = '0', - IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.sogo_access')) = 1, password, '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'), - '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'), - mailbox.name, - mailbox.username, - IFNULL(GROUP_CONCAT(ga.aliases ORDER BY ga.aliases SEPARATOR ' '), ''), - IFNULL(gda.ad_alias, ''), - IFNULL(external_acl.send_as_acl, ''), - mailbox.kind, - mailbox.multiple_bookings - FROM - mailbox - LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)') - LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username - LEFT OUTER JOIN grouped_sender_acl_external external_acl ON external_acl.username = mailbox.username - WHERE - mailbox.active = '1'"; - - if ($mailbox_exists) { - $query .= " AND mailbox.username = :mailbox"; - $stmt = $pdo->prepare($query); - $stmt->execute(array(':mailbox' => $mailbox)); - } else { - $query .= " GROUP BY mailbox.username"; - $stmt = $pdo->query($query); - } - - $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) { diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 4e036b99..4529ee7b 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1264,13 +1264,11 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { )); } - update_sogo_static_view($username); $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_added', htmlspecialchars($username)) ); - return true; break; case 'resource': $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46); @@ -3132,10 +3130,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_modified', $username) ); - - update_sogo_static_view($username); } - return true; break; case 'mailbox_templates': if ($_SESSION['mailcow_cc_role'] != "admin") { @@ -5058,15 +5053,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); continue; } - - update_sogo_static_view($username); $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_removed', htmlspecialchars($username)) ); } - return true; break; case 'mailbox_templates': if ($_SESSION['mailcow_cc_role'] != "admin") { @@ -5272,7 +5264,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } break; } - if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource')) && getenv('SKIP_SOGO') != "y") { + if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox', 'resource')) && getenv('SKIP_SOGO') != "y") { update_sogo_static_view(); } } diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js index 07dfed8c..23ef1d25 100644 --- a/data/web/js/site/admin.js +++ b/data/web/js/site/admin.js @@ -117,8 +117,8 @@ jQuery(function($){ data: 'tfa_active', defaultContent: '', render: function (data, type) { - if(data == 1) return '1'; - else return '0'; + if(data == 1) return ''; + else return ''; } }, { @@ -126,8 +126,8 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - if(data == 1) return '1'; - else return '0'; + if(data == 1) return ''; + else return ''; } }, { @@ -260,8 +260,8 @@ jQuery(function($){ data: 'tfa_active', defaultContent: '', render: function (data, type) { - if(data == 1) return '1'; - else return '0'; + if(data == 1) return ''; + else return ''; } }, { @@ -269,8 +269,8 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - if(data == 1) return '1'; - else return '0'; + if(data == 1) return ''; + else return ''; } }, { @@ -337,7 +337,7 @@ jQuery(function($){ data: 'keep_spam', defaultContent: '', render: function(data, type){ - return 'yes'==data?'yes':'no'==data&&'no'; + return 'yes'==data?'':'no'==data&&''; } }, { @@ -414,8 +414,8 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - if(data == 1) return '1'; - else return '0'; + if(data == 1) return ''; + else return ''; } }, { @@ -492,8 +492,8 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - if(data == 1) return '1'; - else return '0'; + if(data == 1) return ''; + else return ''; } }, { diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index d7fca848..f4039268 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -607,7 +607,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 6, render: function (data, type) { - return 1==data?'1':(0==data?'0':2==data&&'—'); + return 1==data?'':(0==data?'':2==data&&'—'); } }, { @@ -754,7 +754,7 @@ jQuery(function($){ data: 'attributes.gal', defaultContent: '', render: function (data, type) { - return 1==data?'1':'0'; + return 1==data?'':''; } }, { @@ -762,7 +762,7 @@ jQuery(function($){ data: 'attributes.backupmx', defaultContent: '', render: function (data, type) { - return 1==data?'1':'0'; + return 1==data?'':''; } }, { @@ -770,7 +770,7 @@ jQuery(function($){ data: 'attributes.relay_all_recipients', defaultContent: '', render: function (data, type) { - return 1==data?'1':'0'; + return 1==data?'':''; } }, { @@ -778,7 +778,7 @@ jQuery(function($){ data: 'attributes.relay_unknown_only', defaultContent: '', render: function (data, type) { - return 1==data?'1':'0'; + return 1==data?'':''; } }, { @@ -787,7 +787,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 4, render: function (data, type) { - return 1==data?'1':'0'; + return 1==data?'':''; } }, { @@ -1093,7 +1093,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 4, render: function (data, type) { - return 1==data?'1':(0==data?'0':2==data&&'—'); + return 1==data?'':(0==data?'':2==data&&'—'); } }, { @@ -1164,13 +1164,13 @@ jQuery(function($){ item.attributes.quota = humanFileSize(item.attributes.quota); - item.attributes.tls_enforce_in = '' + (item.attributes.tls_enforce_in == 1 ? '1' : '0') + ''; - item.attributes.tls_enforce_out = '' + (item.attributes.tls_enforce_out == 1 ? '1' : '0') + ''; - item.attributes.pop3_access = '' + (item.attributes.pop3_access == 1 ? '1' : '0') + ''; - item.attributes.imap_access = '' + (item.attributes.imap_access == 1 ? '1' : '0') + ''; - item.attributes.smtp_access = '' + (item.attributes.smtp_access == 1 ? '1' : '0') + ''; - item.attributes.sieve_access = '' + (item.attributes.sieve_access == 1 ? '1' : '0') + ''; - item.attributes.sogo_access = '' + (item.attributes.sogo_access == 1 ? '1' : '0') + ''; + item.attributes.tls_enforce_in = ''; + item.attributes.tls_enforce_out = ''; + item.attributes.pop3_access = ''; + item.attributes.imap_access = ''; + item.attributes.smtp_access = ''; + item.attributes.sieve_access = ''; + item.attributes.sogo_access = ''; if (item.attributes.quarantine_notification === 'never') { item.attributes.quarantine_notification = lang.never; } else if (item.attributes.quarantine_notification === 'hourly') { @@ -1188,6 +1188,7 @@ jQuery(function($){ item.attributes.quarantine_category = lang.q_all; } + if (item.template.toLowerCase() == "default"){ item.action = '
' + ' ' + lang.edit + '' + @@ -1328,7 +1329,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 4, render: function (data, type) { - return 1==data?'1':(0==data?'0':2==data&&'—'); + return 1==data?'':(0==data?'':2==data&&'—'); } }, { @@ -1439,7 +1440,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'1':(0==data?'0':2==data&&'—'); + return 1==data?'':(0==data?'':2==data&&'—'); } }, { @@ -1577,7 +1578,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'1':(0==data?'0':2==data&&'—'); + return 1==data?'':(0==data?'':2==data&&'—'); } }, { @@ -1674,7 +1675,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'1':0==data&&'0'; + return 1==data?'':0==data&&''; } }, { @@ -1781,7 +1782,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'1':0==data&&'0'; + return 1==data?'':0==data&&''; } }, { @@ -1916,7 +1917,7 @@ jQuery(function($){ data: 'sogo_visible', defaultContent: '', render: function(data, type){ - return 1==data?'1':0==data&&'0'; + return 1==data?'':0==data&&''; } }, { @@ -1935,7 +1936,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 6, render: function (data, type) { - return 1==data?'1':0==data&&'0'; + return 1==data?'':0==data&&''; } }, { @@ -1951,10 +1952,6 @@ jQuery(function($){ table.on('responsive-resize', function (e, datatable, columns){ hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table'); }); - - table.on( 'draw', function (){ - $('#alias_table [data-bs-toggle="tooltip"]').tooltip(); - }); } function draw_aliasdomain_table() { // just recalc width if instance already exists @@ -2034,7 +2031,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'1':0==data&&'0'; + return 1==data?'':0==data&&''; } }, { @@ -2170,7 +2167,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'1':0==data&&'0'; + return 1==data?'':0==data&&''; } }, { diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index 712b8c77..5e119fbd 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -105,8 +105,7 @@ "timeout2": "Časový limit pro připojení k lokálnímu serveru", "username": "Uživatelské jméno", "validate": "Ověřit", - "validation_success": "Úspěšně ověřeno", - "tags": "Štítky" + "validation_success": "Úspěšně ověřeno" }, "admin": { "access": "Přístupy", @@ -334,11 +333,7 @@ "username": "Uživatelské jméno", "validate_license_now": "Ověřit GUID na licenčním serveru", "verify": "Ověřit", - "yes": "✓", - "f2b_ban_time_increment": "Délka banu je prodlužována s každým dalším banem", - "f2b_max_ban_time": "Maximální délka banu (s)", - "ip_check": "Kontrola IP", - "ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v
System > Nastavení > Options > Přizpůsobení" + "yes": "✓" }, "danger": { "access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři", diff --git a/data/web/lang/lang.da-dk.json b/data/web/lang/lang.da-dk.json index 5846181b..61a553e6 100644 --- a/data/web/lang/lang.da-dk.json +++ b/data/web/lang/lang.da-dk.json @@ -1048,7 +1048,7 @@ "spamfilter_table_empty": "Intet data at vise", "spamfilter_table_remove": "slet", "spamfilter_table_rule": "Regl", - "spamfilter_wl": "Hvidliste", + "spamfilter_wl": "Hvisliste", "spamfilter_wl_desc": "Hvidlistede e-mail-adresser til aldrig at klassificeres som spam. Wildcards kan bruges. Et filter anvendes kun på direkte aliaser (aliaser med en enkelt målpostkasse) eksklusive catch-aliaser og selve en postkasse.", "spamfilter_yellow": "Gul: denne besked kan være spam, vil blive tagget som spam og flyttes til din junk-mappe", "status": "Status", diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 4bd4b3fa..8ff1cf06 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -175,12 +175,10 @@ "empty": "Keine Einträge vorhanden", "excludes": "Diese Empfänger ausschließen", "f2b_ban_time": "Bannzeit in Sekunden", - "f2b_ban_time_increment": "Bannzeit erhöht sich mit jedem Bann", "f2b_blacklist": "Blacklist für Netzwerke und Hosts", "f2b_filter": "Regex-Filter", "f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. Die Aktualisierung der Liste dauert einige Sekunden.", "f2b_max_attempts": "Max. Versuche", - "f2b_max_ban_time": "Maximale Bannzeit in Sekunden", "f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)", "f2b_netban_ipv6": "Netzbereich für IPv6-Banns (8-128)", "f2b_parameters": "Fail2ban-Parameter", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index df83987c..bfac011e 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -177,12 +177,10 @@ "empty": "No results", "excludes": "Excludes these recipients", "f2b_ban_time": "Ban time (s)", - "f2b_ban_time_increment": "Ban time is incremented with each ban", "f2b_blacklist": "Blacklisted networks/hosts", "f2b_filter": "Regex filters", "f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. List updates will take a few seconds to be applied.", "f2b_max_attempts": "Max. attempts", - "f2b_max_ban_time": "Max. ban time (s)", "f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)", "f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)", "f2b_parameters": "Fail2ban parameters", diff --git a/data/web/lang/lang.es-es.json b/data/web/lang/lang.es-es.json index e56e6bdd..d9c3bfd3 100644 --- a/data/web/lang/lang.es-es.json +++ b/data/web/lang/lang.es-es.json @@ -141,11 +141,9 @@ "empty": "Sin resultados", "excludes": "Excluye a estos destinatarios", "f2b_ban_time": "Tiempo de restricción (s)", - "f2b_ban_time_increment": "Tiempo de restricción se incrementa con cada restricción", "f2b_blacklist": "Redes y hosts en lista negra", "f2b_list_info": "Un host o red en lista negra siempre superará a una entidad de la lista blanca. Las actualizaciones de la lista tardarán unos segundos en aplicarse.", "f2b_max_attempts": "Max num. de intentos", - "f2b_max_ban_time": "Max tiempo de restricción (s)", "f2b_netban_ipv4": "Tamaño de subred IPv4 para aplicar la restricción (8-32)", "f2b_netban_ipv6": "Tamaño de subred IPv6 para aplicar la restricción (8-128)", "f2b_parameters": "Parametros Fail2ban", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index d64f62f7..ef19d186 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -24,7 +24,7 @@ "spam_policy": "Liste Noire/Liste Blanche", "spam_score": "Score SPAM", "syncjobs": "Tâches de synchronisation", - "tls_policy": "Politique TLS", + "tls_policy": "Police TLS", "unlimited_quota": "Quota illimité pour les boites de courriel", "domain_desc": "Modifier la description du domaine", "domain_relayhost": "Changer le relais pour un domaine", @@ -106,8 +106,7 @@ "validate": "Valider", "validation_success": "Validation réussie", "bcc_dest_format": "La destination Cci doit être une seule adresse e-mail valide.
Si vous avez besoin d'envoyer une copie à plusieurs adresses, créez un alias et utilisez-le ici.", - "tags": "Etiquettes", - "app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application" + "tags": "Etiquettes" }, "admin": { "access": "Accès", @@ -172,13 +171,11 @@ "edit": "Editer", "empty": "Aucun résultat", "excludes": "Exclure ces destinataires", - "f2b_ban_time": "Durée du bannissement (s)", - "f2b_ban_time_increment": "Durée du bannissement est augmentée à chaque bannissement", + "f2b_ban_time": "Durée du bannissement(s)", "f2b_blacklist": "Réseaux/Domaines sur Liste Noire", "f2b_filter": "Filtre(s) Regex", "f2b_list_info": "Un hôte ou un réseau sur liste noire l'emportera toujours sur une entité de liste blanche. L'application des mises à jour de liste prendra quelques secondes.", "f2b_max_attempts": "Nb max. de tentatives", - "f2b_max_ban_time": "Max. durée du bannissement (s)", "f2b_netban_ipv4": "Taille du sous-réseau IPv4 pour l'application du bannissement (8-32)", "f2b_netban_ipv6": "Taille du sous-réseau IPv6 pour l'application du bannissement (8-128)", "f2b_parameters": "Paramètres Fail2ban", @@ -588,7 +585,7 @@ "unchanged_if_empty": "Si non modifié, laisser en blanc", "username": "Nom d'utilisateur", "validate_save": "Valider et sauver", - "lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (.*google\\.com pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut)", + "lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (.*google\\.com pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut).", "mailbox_relayhost_info": "S'applique uniquement à la boîte aux lettres et aux alias directs, remplace le relayhost du domaine." }, "footer": { @@ -1091,12 +1088,9 @@ "username": "Nom d'utilisateur", "verify": "Vérification", "waiting": "En attente", - "week": "semaine", + "week": "Semaine", "weekly": "Hebdomadaire", - "weeks": "semaines", - "months": "mois", - "year": "année", - "years": "années" + "weeks": "semaines" }, "warning": { "cannot_delete_self": "Impossible de supprimer l’utilisateur connecté", diff --git a/data/web/lang/lang.it-it.json b/data/web/lang/lang.it-it.json index 4d21547c..d8d6978c 100644 --- a/data/web/lang/lang.it-it.json +++ b/data/web/lang/lang.it-it.json @@ -175,12 +175,10 @@ "empty": "Nessun risultato", "excludes": "Esclude questi destinatari", "f2b_ban_time": "Tempo di blocco (s)", - "f2b_ban_time_increment": "Tempo di blocco aumenta ad ogni blocco", "f2b_blacklist": "Host/reti in blacklist", "f2b_filter": "Filtri Regex", "f2b_list_info": "Un host oppure una rete in blacklist, avrà sempre un peso maggiore rispetto ad una in whitelist. L'aggiornamento della lista richiede alcuni secondi per la sua entrata in azione.", "f2b_max_attempts": "Tentativi massimi", - "f2b_max_ban_time": "Tempo massimo di blocco (s)", "f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)", "f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)", "f2b_parameters": "Parametri Fail2ban", diff --git a/data/web/lang/lang.nl-nl.json b/data/web/lang/lang.nl-nl.json index 4c2ea0b1..774627ca 100644 --- a/data/web/lang/lang.nl-nl.json +++ b/data/web/lang/lang.nl-nl.json @@ -168,12 +168,10 @@ "empty": "Geen resultaten", "excludes": "Exclusief", "f2b_ban_time": "Verbanningstijd (s)", - "f2b_ban_time_increment": "Verbanningstijd wordt verhoogd met elk verbanning", "f2b_blacklist": "Netwerken/hosts op de blacklist", "f2b_filter": "Regex-filters", "f2b_list_info": "Een host of netwerk op de blacklist staat altijd boven eenzelfde op de whitelist. Het doorvoeren van wijzigingen kan enkele seconden in beslag nemen.", "f2b_max_attempts": "Maximaal aantal pogingen", - "f2b_max_ban_time": "Maximaal verbanningstijd (s)", "f2b_netban_ipv4": "Voer de IPv4-subnetgrootte in waar de verbanning van kracht moet zijn (8-32)", "f2b_netban_ipv6": "Voer de IPv6-subnetgrootte in waar de verbanning van kracht moet zijn (8-128)", "f2b_parameters": "Fail2ban", diff --git a/data/web/sogo-auth.php b/data/web/sogo-auth.php index 40fff585..7ca5e4d9 100644 --- a/data/web/sogo-auth.php +++ b/data/web/sogo-auth.php @@ -60,7 +60,7 @@ elseif (isset($_GET['login'])) { ':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']) )); // redirect to sogo (sogo will get the correct credentials via nginx auth_request - header("Location: /SOGo/so/{$login}"); + header("Location: /SOGo/so/${login}"); exit; } } diff --git a/data/web/templates/admin/tab-config-f2b.twig b/data/web/templates/admin/tab-config-f2b.twig index c15fb72f..bbd3e367 100644 --- a/data/web/templates/admin/tab-config-f2b.twig +++ b/data/web/templates/admin/tab-config-f2b.twig @@ -12,14 +12,6 @@
-
- - -
-
- - -
diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index f8cde7da..36fe053b 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -109,25 +109,25 @@
- - - - - - -
- {{ lang.mailbox.toggle_all }} + {{ lang.mailbox.toggle_all }} {{ lang.mailbox.quick_actions }}