From b52ee0a706f1b4d0fb7989c8805623d2c842ea47 Mon Sep 17 00:00:00 2001 From: andryyy Date: Tue, 29 Oct 2019 08:39:57 +0100 Subject: [PATCH] [Rspamd] Fix map permissions for www [Web] Allow to manage global maps in UI (WIP) --- data/Dockerfiles/rspamd/docker-entrypoint.sh | 8 +- data/web/admin.php | 44 +++ data/web/inc/ajax/regex_validation.php | 25 ++ .../inc/ajax/show_rspamd_global_filters.php | 3 + data/web/inc/functions.fail2ban.inc.php | 4 +- data/web/inc/functions.rsettings.inc.php | 160 --------- data/web/inc/functions.rspamd.inc.php | 311 ++++++++++++++++++ data/web/inc/prerequisites.inc.php | 2 +- data/web/inc/vars.inc.php | 2 +- data/web/js/site/admin.js | 28 ++ data/web/js/site/mailbox.js | 5 +- data/web/json_api.php | 3 + data/web/lang/lang.de.php | 10 +- data/web/lang/lang.en.php | 9 +- 14 files changed, 441 insertions(+), 173 deletions(-) create mode 100644 data/web/inc/ajax/regex_validation.php create mode 100644 data/web/inc/ajax/show_rspamd_global_filters.php delete mode 100644 data/web/inc/functions.rsettings.inc.php create mode 100644 data/web/inc/functions.rspamd.inc.php diff --git a/data/Dockerfiles/rspamd/docker-entrypoint.sh b/data/Dockerfiles/rspamd/docker-entrypoint.sh index ab5f0a10..5c9f8e49 100755 --- a/data/Dockerfiles/rspamd/docker-entrypoint.sh +++ b/data/Dockerfiles/rspamd/docker-entrypoint.sh @@ -8,6 +8,8 @@ touch /etc/rspamd/rspamd.conf.local \ chmod 755 /var/lib/rspamd +addgroup --system --gid 82 www-access + [[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated by mailcow' > /etc/rspamd/override.d/worker-controller-password.inc DOVECOT_V4= @@ -49,8 +51,10 @@ touch /etc/rspamd/custom/global_mime_from_blacklist.map \ /etc/rspamd/custom/bad_words_de.map # www-data (82) group needs to write to these files -chown -R _rspamd:82 /etc/rspamd/custom -chmod -R g+w /etc/rspamd/custom +chown root:root /etc/rspamd/custom/ +chmod 0755 /etc/rspamd/custom/ +chown -R _rspamd:www-access /etc/rspamd/custom/* +chmod -R 664 /etc/rspamd/custom/* # Run hooks for file in /hooks/*; do diff --git a/data/web/admin.php b/data/web/admin.php index b0481e5a..4e18822d 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -17,6 +17,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
  • +
  • @@ -1135,6 +1136,49 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
    + +
    +
    +
    + +
    +
    +

    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    + + +
    +
    +
    + +
    +
    +
    +
    diff --git a/data/web/inc/ajax/regex_validation.php b/data/web/inc/ajax/regex_validation.php new file mode 100644 index 00000000..6bd8c931 --- /dev/null +++ b/data/web/inc/ajax/regex_validation.php @@ -0,0 +1,25 @@ + $regex) { + if (empty($regex) || substr($regex, 0, 1) == "#") { + continue; + } + if (empty($regex) || substr($regex, 0, 1) != "/") { + echo json_encode(array('type' => 'danger', 'msg' => 'Line ' . ($line + 1) . ': Invalid regex')); + exit(); + } + if (@preg_match($regex, 'Lorem Ipsum') === false) { + echo json_encode(array('type' => 'danger', 'msg' => 'Line ' . ($line + 1) . ': Invalid regex "' . $regex . '"')); + exit(); + } + } + echo json_encode(array('type' => 'success', 'msg' => $lang['add']['validation_success'])); +} +?> diff --git a/data/web/inc/ajax/show_rspamd_global_filters.php b/data/web/inc/ajax/show_rspamd_global_filters.php new file mode 100644 index 00000000..7c7affe8 --- /dev/null +++ b/data/web/inc/ajax/show_rspamd_global_filters.php @@ -0,0 +1,3 @@ + 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'access_denied' - ); - return false; - } - $content = $_data['content']; - $desc = $_data['desc']; - $active = intval($_data['active']); - if (empty($content)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'map_content_empty' - ); - return false; - } - try { - $stmt = $pdo->prepare("INSERT INTO `settingsmap` (`content`, `desc`, `active`) - VALUES (:content, :desc, :active)"); - $stmt->execute(array( - ':content' => $content, - ':desc' => $desc, - ':active' => $active - )); - } - catch (PDOException $e) { - $_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' => 'settings_map_added' - ); - break; - case 'edit': - if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'access_denied' - ); - return false; - } - $ids = (array)$_data['id']; - foreach ($ids as $id) { - $is_now = rsettings('details', $id); - if (!empty($is_now)) { - $content = (!empty($_data['content'])) ? $_data['content'] : $is_now['content']; - $desc = (!empty($_data['desc'])) ? $_data['desc'] : $is_now['desc']; - $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int']; - } - else { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('settings_map_invalid', $id) - ); - continue; - } - $content = trim($content); - try { - $stmt = $pdo->prepare("UPDATE `settingsmap` SET - `content` = :content, - `desc` = :desc, - `active` = :active - WHERE `id` = :id"); - $stmt->execute(array( - ':content' => $content, - ':desc' => $desc, - ':active' => $active, - ':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__, $_action, $_data_log), - 'msg' => array('object_modified', htmlspecialchars($ids)) - ); - } - break; - case 'delete': - if ($_SESSION['mailcow_cc_role'] != "admin") { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'access_denied' - ); - return false; - } - $ids = (array)$_data['id']; - foreach ($ids as $id) { - try { - $stmt = $pdo->prepare("DELETE FROM `settingsmap` 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; - } - $_SESSION['return'][] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => array('settings_map_removed', htmlspecialchars($id)) - ); - } - break; - case 'get': - if ($_SESSION['mailcow_cc_role'] != "admin") { - return false; - } - $settingsmaps = array(); - $stmt = $pdo->query("SELECT `id`, `desc`, `active` FROM `settingsmap`"); - $settingsmaps = $stmt->fetchAll(PDO::FETCH_ASSOC); - return $settingsmaps; - break; - case 'details': - if ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) { - return false; - } - $settingsmapdata = array(); - $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; - } -} \ No newline at end of file diff --git a/data/web/inc/functions.rspamd.inc.php b/data/web/inc/functions.rspamd.inc.php new file mode 100644 index 00000000..22d405a3 --- /dev/null +++ b/data/web/inc/functions.rspamd.inc.php @@ -0,0 +1,311 @@ + 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'access_denied' + ); + return false; + } + $content = $_data['content']; + $desc = $_data['desc']; + $active = intval($_data['active']); + if (empty($content)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'map_content_empty' + ); + return false; + } + try { + $stmt = $pdo->prepare("INSERT INTO `settingsmap` (`content`, `desc`, `active`) + VALUES (:content, :desc, :active)"); + $stmt->execute(array( + ':content' => $content, + ':desc' => $desc, + ':active' => $active + )); + } + catch (PDOException $e) { + $_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' => 'settings_map_added' + ); + break; + case 'edit': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'access_denied' + ); + return false; + } + $ids = (array)$_data['id']; + foreach ($ids as $id) { + $is_now = rsettings('details', $id); + if (!empty($is_now)) { + $content = (!empty($_data['content'])) ? $_data['content'] : $is_now['content']; + $desc = (!empty($_data['desc'])) ? $_data['desc'] : $is_now['desc']; + $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int']; + } + else { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('settings_map_invalid', $id) + ); + continue; + } + $content = trim($content); + try { + $stmt = $pdo->prepare("UPDATE `settingsmap` SET + `content` = :content, + `desc` = :desc, + `active` = :active + WHERE `id` = :id"); + $stmt->execute(array( + ':content' => $content, + ':desc' => $desc, + ':active' => $active, + ':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__, $_action, $_data_log), + 'msg' => array('object_modified', htmlspecialchars($ids)) + ); + } + break; + case 'delete': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'access_denied' + ); + return false; + } + $ids = (array)$_data['id']; + foreach ($ids as $id) { + try { + $stmt = $pdo->prepare("DELETE FROM `settingsmap` 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; + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('settings_map_removed', htmlspecialchars($id)) + ); + } + break; + case 'get': + if ($_SESSION['mailcow_cc_role'] != "admin") { + return false; + } + $settingsmaps = array(); + $stmt = $pdo->query("SELECT `id`, `desc`, `active` FROM `settingsmap`"); + $settingsmaps = $stmt->fetchAll(PDO::FETCH_ASSOC); + return $settingsmaps; + break; + case 'details': + if ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) { + return false; + } + $settingsmapdata = array(); + $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; + } +} +function rspamd($_action, $_data = null) { + global $pdo; + global $lang; + global $RSPAMD_MAPS; + $_data_log = $_data; + switch ($_action) { + case 'add': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'access_denied' + ); + return false; + } + $content = $_data['content']; + $desc = $_data['desc']; + $active = intval($_data['active']); + if (empty($content)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'map_content_empty' + ); + return false; + } + try { + $stmt = $pdo->prepare("INSERT INTO `settingsmap` (`content`, `desc`, `active`) + VALUES (:content, :desc, :active)"); + $stmt->execute(array( + ':content' => $content, + ':desc' => $desc, + ':active' => $active + )); + } + catch (PDOException $e) { + $_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' => 'settings_map_added' + ); + break; + case 'edit': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'access_denied' + ); + return false; + } + $maps = (array)$_data['map']; + foreach ($maps as $map) { + if (!in_array($map, $RSPAMD_MAPS)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('global_map_invalid', $map) + ); + continue; + } + try { + if (file_exists('/rspamd_custom_maps/' . $map)) { + $map_content = trim($_data['rspamd_map_data']); + $map_handle = fopen('/rspamd_custom_maps/' . $map, 'w'); + if (!$map_handle) { + throw new Exception('File cannot be opened for writing.'); + } + fwrite($map_handle, $map_content . PHP_EOL); + fclose($map_handle); + } + } + catch (Exception $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('global_map_write_error', htmlspecialchars($map), htmlspecialchars($e->getMessage())) + ); + continue; + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('object_modified', htmlspecialchars($map)) + ); + } + break; + case 'delete': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => 'access_denied' + ); + return false; + } + $ids = (array)$_data['id']; + foreach ($ids as $id) { + try { + $stmt = $pdo->prepare("DELETE FROM `settingsmap` 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; + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data_log), + 'msg' => array('settings_map_removed', htmlspecialchars($id)) + ); + } + break; + case 'get': + if ($_SESSION['mailcow_cc_role'] != "admin") { + return false; + } + $settingsmaps = array(); + $stmt = $pdo->query("SELECT `id`, `desc`, `active` FROM `settingsmap`"); + $settingsmaps = $stmt->fetchAll(PDO::FETCH_ASSOC); + return $settingsmaps; + break; + case 'details': + if ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) { + return false; + } + $settingsmapdata = array(); + $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; + } +} \ No newline at end of file diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index 7215de28..8d4062eb 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -209,7 +209,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailq.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.oauth2.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.ratelimit.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.transports.inc.php'; -require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rsettings.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rspamd.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.tls_policy_maps.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.docker.inc.php'; diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php index bea6c3cf..6d906df5 100644 --- a/data/web/inc/vars.inc.php +++ b/data/web/inc/vars.inc.php @@ -156,7 +156,7 @@ $MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification'] = 'hourly'; $MAILBOX_DEFAULT_ATTRIBUTES['mailbox_format'] = 'maildir:'; // Set visible Rspamd maps in mailcow UI, do not change unless you know what you are doing -$RSPAM_MAPS = array( +$RSPAMD_MAPS = array( 'global_mime_from_blacklist.map', 'global_mime_from_whitelist.map', 'global_rcpt_blacklist.map', diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js index d909a793..1b500a18 100644 --- a/data/web/js/site/admin.js +++ b/data/web/js/site/admin.js @@ -3,6 +3,7 @@ var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456 jQuery(function($){ // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; + function jq(myid) {return "#" + myid.replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1" );} function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})} function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e' + sieveScript + ''); }); // Disable submit button on script change - $('#script_data').on('keyup', function() { + $('.textarea-code').on('keyup', function() { $('#add_filter_btns > #add_sieve_script').attr({"disabled": true}); - $('#validation_msg').html('-'); }); // Validate script data $("#validate_sieve").click(function( event ) { event.preventDefault(); var script = $('#script_data').val(); $.ajax({ - dataType: 'jsonp', + dataType: 'json', url: "/inc/ajax/sieve_validation.php", type: "get", data: { script: script }, diff --git a/data/web/json_api.php b/data/web/json_api.php index d59cfe56..66e9f22e 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -1245,6 +1245,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u case "alias": process_edit_return(mailbox('edit', 'alias', array_merge(array('id' => $items), $attr))); break; + case "rspamd-map": + process_edit_return(rspamd('edit', array_merge(array('map' => $items), $attr))); + break; case "app_links": process_edit_return(customize('edit', 'app_links', $attr)); break; diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php index 3451a322..60fe487c 100644 --- a/data/web/lang/lang.de.php +++ b/data/web/lang/lang.de.php @@ -71,6 +71,8 @@ $lang['danger']['private_key_error'] = "Schlüsselfehler: %s"; $lang['danger']['map_content_empty'] = "Inhalt darf nicht leer sein"; $lang['success']['settings_map_added'] = "Regel wurde gespeichert"; $lang['danger']['settings_map_invalid'] = "Regel ID %s ist ungültig"; +$lang['danger']['global_map_invalid'] = "Rspamd Map %s ist ungültig"; +$lang['danger']['global_map_write_error'] = "Kann globale Map ID %s nicht schreiben: %s"; $lang['success']['settings_map_removed'] = "Regeln wurden entfernt: %s"; $lang['danger']['invalid_host'] = "Ungültiger Host: %s"; $lang['danger']['relayhost_invalid'] = "Mapeintrag %s ist ungültig"; @@ -915,5 +917,9 @@ $lang['mailbox']['alias_domain_backupmx'] = 'Alias-Domain für Relay-Domain inak $lang['danger']['extra_acl_invalid'] = 'Externe Absenderadresse "%s" ist ungültig'; $lang['danger']['extra_acl_invalid_domain'] = 'Externe Absenderadresse "%s" verwendet eine ungültige Domain'; -$lang['admin']['rspamd_global_filters'] = 'Globale Rspamd Filter'; -$lang['admin']['rspamd_global_filters'] = 'Globale Rspamd Filter'; +$lang['admin']['rspamd_global_filters_agree'] = "Ich werde vorsichtig sein!"; +$lang['admin']['rspamd_global_filters'] = 'Globale Filter-Maps'; +$lang['admin']['rspamd_global_filters_info'] = 'Globale Filter-Maps steuern globales White- und Blacklisting dieses Servers. Die akzeptierte Form für Einträge sind ausschließlich Regular Expressions. + Trotz rudimentärer Überprüfung der Map, kann es zu fehlerhaften Einträgen kommen, die Rspamd im schlechtesten Fall mit unvorhersehbarer Funktionalität bestraft.
    + Das korrekte Format lautet "/pattern/options" (Beispiel: /.+@domain\.tld/i).
    + Der Name der Map beschreibt die jeweilige Funktion.'; diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php index f108462c..f170ab1e 100644 --- a/data/web/lang/lang.en.php +++ b/data/web/lang/lang.en.php @@ -72,6 +72,8 @@ $lang['danger']['private_key_error'] = "Private key error: %s"; $lang['danger']['map_content_empty'] = "Map content cannot be empty"; $lang['success']['settings_map_added'] = "Added settings map entry"; $lang['danger']['settings_map_invalid'] = "Settings map ID %s invalid"; +$lang['danger']['global_map_invalid'] = "Global map ID %s invalid"; +$lang['danger']['global_map_write_error'] = "Could not write global map ID %s: %s"; $lang['success']['settings_map_removed'] = "Removed settings map ID %s"; $lang['danger']['invalid_host'] = "Invalid host specified: %s"; $lang['danger']['relayhost_invalid'] = "Map entry %s is invalid"; @@ -940,5 +942,8 @@ $lang['mailbox']['alias_domain_backupmx'] = 'Alias domain inactive for relay dom $lang['danger']['extra_acl_invalid'] = 'External sender address "%s" is invalid'; $lang['danger']['extra_acl_invalid_domain'] = 'External sender "%s" uses an invalid domain'; -$lang['admin']['rspamd_global_filters'] = 'Global Rspamd filters'; -$lang['admin']['rspamd_global_filters_info'] = 'Global Rspamd filters'; +$lang['admin']['rspamd_global_filters_agree'] = "I will be careful!"; +$lang['admin']['rspamd_global_filters'] = 'Global filter maps'; +$lang['admin']['rspamd_global_filters_info'] = 'Global filter maps contain different kind of global black and whitelists. Their names explain their purpose. All content must contain valid regular expression in the format of "/pattern/options" (e.g. /.+@domain\.tld/i).
    + Although rudimentary checks are being executed on each line of regex, Rspamds functionality can be broken, if it fails to read the syntax correctly.'; +