[Web] Use INTL_IDNA_VARIANT_UTS46 in idn_to_ascii (thanks to @Knight1 !)

[Web] Some PHP fixes (warnings, notices)
[Web] Add quota notification tools
This commit is contained in:
andryyy 2019-02-05 00:10:21 +01:00
parent 21741dc061
commit 1e764009bf
No known key found for this signature in database
GPG Key ID: 8EC34FF2794E25EF
25 changed files with 237 additions and 98 deletions

View File

@ -76,8 +76,8 @@ $tfa_data = get_tfa();
</select>
</div>
</div>
<legend data-target="#api" style="margin-top:40px;cursor:pointer" id="api_legend" unselectable="on" data-toggle="collapse">
<span id="api_arrow" style="font-size:12px" class="rotate glyphicon glyphicon-menu-down"></span> API (experimental, work in progress)
<legend data-target="#api" style="margin-top:40px;cursor:pointer" class="arrow-toggle" unselectable="on" data-toggle="collapse">
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> API (experimental, work in progress)
</legend>
<?php
$api = admin_api('get');
@ -283,6 +283,7 @@ $tfa_data = get_tfa();
<a href="#fwdhosts" class="list-group-item"><?=$lang['admin']['forwarding_hosts'];?></a>
<a href="#f2bparams" class="list-group-item"><?=$lang['admin']['f2b_parameters'];?></a>
<a href="#quarantine" class="list-group-item"><?=$lang['admin']['quarantine'];?></a>
<a href="#quota" class="list-group-item">Quota notifications</a>
<a href="#rsettings" class="list-group-item">Rspamd settings map</a>
<a href="#customize" class="list-group-item"><?=$lang['admin']['customize'];?></a>
<a href="#top" class="list-group-item" style="border-top:1px dashed #dadada"> <?=$lang['admin']['to_top'];?></a>
@ -415,8 +416,8 @@ $tfa_data = get_tfa();
<button class="btn btn-sm btn-default" data-action="add_item" data-id="dkim" data-api-url='add/dkim' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
</form>
<legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" id="import_dkim_legend" unselectable="on" data-toggle="collapse">
<span id="import_dkim_arrow" style="font-size:12px" class="rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['import_private_key'];?>
<legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" class="arrow-toggle"" unselectable="on" data-toggle="collapse">
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['import_private_key'];?>
</legend>
<div id="import_dkim" class="collapse">
<form class="form" data-id="dkim_import" role="form" method="post">
@ -436,8 +437,8 @@ $tfa_data = get_tfa();
</form>
</div>
<legend data-target="#duplicate_dkim" style="margin-top:40px;cursor:pointer" id="duplicate_dkim_legend" unselectable="on" data-toggle="collapse">
<span id="duplicate_dkim_arrow" style="font-size:12px" class="rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['duplicate_dkim'];?>
<legend data-target="#duplicate_dkim" style="margin-top:40px;cursor:pointer" class="arrow-toggle" unselectable="on" data-toggle="collapse">
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['duplicate_dkim'];?>
</legend>
<div id="duplicate_dkim" class="collapse">
<form class="form-horizontal" data-id="dkim_duplicate" role="form" method="post">
@ -579,32 +580,36 @@ $tfa_data = get_tfa();
<i><?=$lang['admin']['no_active_bans'];?></i>
<?php
endif;
foreach ($f2b_data['active_bans'] as $active_bans):
?>
<p><span class="label label-info" style="padding:4px;font-size:85%;"><span class="glyphicon glyphicon-filter"></span> <?=$active_bans['network'];?> (<?=$active_bans['banned_until'];?>) -
<?php
if ($active_bans['queued_for_unban'] == 0):
if (!empty($f2b_data['active_bans'])):
foreach ($f2b_data['active_bans'] as $active_bans):
?>
<a data-action="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"unban"}' href="#">[<?=$lang['admin']['queue_unban'];?>]</a>
<a data-action="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"whitelist"}' href="#">[whitelist]</a>
<a data-action="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"blacklist"}' href="#">[blacklist]</a>
<p><span class="label label-info" style="padding:4px;font-size:85%;"><span class="glyphicon glyphicon-filter"></span> <?=$active_bans['network'];?> (<?=$active_bans['banned_until'];?>) -
<?php
if ($active_bans['queued_for_unban'] == 0):
?>
<a data-action="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"unban"}' href="#">[<?=$lang['admin']['queue_unban'];?>]</a>
<a data-action="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"whitelist"}' href="#">[whitelist]</a>
<a data-action="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"blacklist"}' href="#">[blacklist]</a>
<?php
else:
?>
<i><?=$lang['admin']['unban_pending'];?></i>
<?php
endif;
?>
</span></p>
<?php
else:
endforeach;
endif;
if (!empty($f2b_data['perm_bans'])):
foreach ($f2b_data['perm_bans'] as $perm_bans):
?>
<i><?=$lang['admin']['unban_pending'];?></i>
<p>
<span class="label label-danger" style="padding:4px;font-size:85%;"><span class="glyphicon glyphicon-filter"></span> <?=$perm_bans?></span>
</p>
<?php
endif;
?>
</span></p>
<?php
endforeach;
foreach ($f2b_data['perm_bans'] as $perm_bans):
?>
<p>
<span class="label label-danger" style="padding:4px;font-size:85%;"><span class="glyphicon glyphicon-filter"></span> <?=$perm_bans?></span>
</p>
<?php
endforeach;
endforeach;
endif;
?>
</div>
</div>
@ -645,9 +650,12 @@ $tfa_data = get_tfa();
</div>
<div class="row">
<div class="col-sm-12">
<label for="html"><?=$lang['admin']['quarantine_notification_html'];?></label>
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="html"><?=$q_data['html'];?></textarea>
<br>
<legend data-target="#quarantine_template" style="cursor:pointer" class="arrow-toggle" unselectable="on" data-toggle="collapse">
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['quarantine_notification_html'];?>
</legend>
<div id="quarantine_template" class="collapse" >
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="html_tmpl"><?=$q_data['html_tmpl'];?></textarea>
</div>
</div>
</div>
<div class="row">
@ -680,13 +688,63 @@ $tfa_data = get_tfa();
</div>
</div>
<span class="anchor" id="quota"></span>
<div class="panel panel-default">
<div class="panel-heading">Quota notifications</div>
<div class="panel-body">
<p>Quota notications are sent to users once when crossing 80% and once when crossing 95% usage.</p>
<?php $q_data = quota_notification('get');?>
<form class="form" role="form" data-id="quota_notification" method="post">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="sender"><?=$lang['admin']['quarantine_notification_sender'];?>:</label>
<input type="text" class="form-control" name="sender" value="<?=$q_data['sender'];?>" placeholder="quota-warning@localhost">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="subject"><?=$lang['admin']['quarantine_notification_subject'];?>:</label>
<input type="text" class="form-control" name="subject" value="<?=$q_data['subject'];?>" placeholder="Quota warning">
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<legend data-target="#quota_template" style="cursor:pointer" class="arrow-toggle" unselectable="on" data-toggle="collapse">
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['quarantine_notification_html'];?>
</legend>
<div id="quota_template" class="collapse" >
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code collapse in" rows="20" name="html"><?=$q_data['html_tmpl'];?></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-10">
<div class="form-group">
<br>
<a type="button" class="btn btn-sm btn-success" data-action="edit_selected"
data-item="quota_notification"
data-id="quota_notification"
data-api-url='edit/quota_notification'
data-api-attr='{}'><?=$lang['user']['save_changes'];?></a>
</div>
</div>
</div>
</form>
</div>
</div>
<span class="anchor" id="rsettings"></span>
<div class="panel panel-default">
<div class="panel-heading">Rspamd settings map</div>
<div class="panel-body">
<legend>Active settings map</legend>
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="settings_map" readonly><?=file_get_contents('http://nginx:8081/settings.php');?></textarea>
<hr>
<legend data-target="#active_settings_map" style="cursor:pointer" class="arrow-toggle" unselectable="on" data-toggle="collapse">
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> Active settings map
</legend>
<div id="active_settings_map" class="collapse" >
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="settings_map" readonly><?=file_get_contents('http://nginx:8081/settings.php');?></textarea>
</div>
<?php $rsettings = rsettings('get'); ?>
<form class="form" data-id="rsettings" role="form" method="post">
<div class="row">
@ -836,29 +894,33 @@ $tfa_data = get_tfa();
<button class="btn btn-sm btn-default" type="button" id="add_app_link_row"><?=$lang['admin']['add_row'];?></button>
</div></p>
</form>
<legend><?=$lang['admin']['ui_texts'];?></legend>
<legend data-target="#ui_texts" style="cursor:pointer" class="arrow-toggle" unselectable="on" data-toggle="collapse">
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['ui_texts'];?>
</legend>
<div id="ui_texts" class="collapse" >
<?php
$ui_texts = customize('get', 'ui_texts');
?>
<form class="form" data-id="uitexts" role="form" method="post">
<div class="form-group">
<label for="title_name"><?=$lang['admin']['title_name'];?>:</label>
<input type="text" class="form-control" name="title_name" placeholder="mailcow UI" value="<?=$ui_texts['title_name'];?>">
</div>
<div class="form-group">
<label for="main_name"><?=$lang['admin']['main_name'];?>:</label>
<input type="text" class="form-control" name="main_name" placeholder="mailcow UI" value="<?=$ui_texts['main_name'];?>">
</div>
<div class="form-group">
<label for="apps_name"><?=$lang['admin']['apps_name'];?>:</label>
<input type="text" class="form-control" name="apps_name" placeholder="mailcow Apps" value="<?=$ui_texts['apps_name'];?>">
</div>
<div class="form-group">
<label for="help_text"><?=$lang['admin']['help_text'];?>:</label>
<textarea class="form-control" id="help_text" name="help_text" rows="7"><?=$ui_texts['help_text'];?></textarea>
</div>
<button class="btn btn-default" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</form>
<form class="form" data-id="uitexts" role="form" method="post">
<div class="form-group">
<label for="title_name"><?=$lang['admin']['title_name'];?>:</label>
<input type="text" class="form-control" name="title_name" placeholder="mailcow UI" value="<?=$ui_texts['title_name'];?>">
</div>
<div class="form-group">
<label for="main_name"><?=$lang['admin']['main_name'];?>:</label>
<input type="text" class="form-control" name="main_name" placeholder="mailcow UI" value="<?=$ui_texts['main_name'];?>">
</div>
<div class="form-group">
<label for="apps_name"><?=$lang['admin']['apps_name'];?>:</label>
<input type="text" class="form-control" name="apps_name" placeholder="mailcow Apps" value="<?=$ui_texts['apps_name'];?>">
</div>
<div class="form-group">
<label for="help_text"><?=$lang['admin']['help_text'];?>:</label>
<textarea class="form-control" id="help_text" name="help_text" rows="7"><?=$ui_texts['help_text'];?></textarea>
</div>
<button class="btn btn-default" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</form>
</div>
</div>
</div>
</div>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -44,8 +44,8 @@ function bcc($_action, $_data = null, $attr = null) {
);
return false;
}
$domain = idn_to_ascii($local_dest);
$local_dest_sane = '@' . idn_to_ascii($local_dest);
$domain = idn_to_ascii($local_dest, 0, INTL_IDNA_VARIANT_UTS46);
$local_dest_sane = '@' . idn_to_ascii($local_dest, 0, INTL_IDNA_VARIANT_UTS46);
}
elseif (filter_var($local_dest, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) {
@ -265,7 +265,7 @@ function recipient_map($_action, $_data = null, $attr = null) {
$new_dest = strtolower(trim($_data['recipient_map_new']));
$active = intval($_data['active']);
if (is_valid_domain_name($old_dest)) {
$old_dest_sane = '@' . idn_to_ascii($old_dest);
$old_dest_sane = '@' . idn_to_ascii($old_dest, 0, INTL_IDNA_VARIANT_UTS46);
}
elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
$old_dest_sane = $old_dest;
@ -331,7 +331,7 @@ function recipient_map($_action, $_data = null, $attr = null) {
continue;
}
if (is_valid_domain_name($old_dest)) {
$old_dest_sane = '@' . idn_to_ascii($old_dest);
$old_dest_sane = '@' . idn_to_ascii($old_dest, 0, INTL_IDNA_VARIANT_UTS46);
}
elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
$old_dest_sane = $old_dest;

View File

@ -32,7 +32,8 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
$containers = json_decode($response, true);
if (!empty($containers)) {
foreach ($containers as $container) {
if ($container['Config']['Labels']['com.docker.compose.service'] == $service_name
if (isset($container['Config']['Labels']['com.docker.compose.service'])
&& $container['Config']['Labels']['com.docker.compose.service'] == $service_name
&& $container['Config']['Labels']['com.docker.compose.project'] == strtolower(getenv('COMPOSE_PROJECT_NAME'))) {
return trim($container['Id']);
}
@ -120,7 +121,8 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
if (!empty($decoded_response)) {
if (empty($service_name)) {
foreach ($decoded_response as $container) {
if ($container['Config']['Labels']['com.docker.compose.project'] == strtolower(getenv('COMPOSE_PROJECT_NAME'))) {
if (isset($container['Config']['Labels']['com.docker.compose.project'])
&& $container['Config']['Labels']['com.docker.compose.project'] == strtolower(getenv('COMPOSE_PROJECT_NAME'))) {
unset($container['Config']['Env']);
$out[$container['Config']['Labels']['com.docker.compose.service']]['State'] = $container['State'];
$out[$container['Config']['Labels']['com.docker.compose.service']]['Config'] = $container['Config'];
@ -128,7 +130,8 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
}
}
else {
if ($decoded_response['Config']['Labels']['com.docker.compose.project'] == strtolower(getenv('COMPOSE_PROJECT_NAME'))) {
if (isset($decoded_response['Config']['Labels']['com.docker.compose.project'])
&& $decoded_response['Config']['Labels']['com.docker.compose.project'] == strtolower(getenv('COMPOSE_PROJECT_NAME'))) {
unset($container['Config']['Env']);
$out[$decoded_response['Config']['Labels']['com.docker.compose.service']]['State'] = $decoded_response['State'];
$out[$decoded_response['Config']['Labels']['com.docker.compose.service']]['Config'] = $decoded_response['Config'];

View File

@ -118,6 +118,7 @@ function fail2ban($_action, $_data = null) {
if (valid_network($network)) {
$redis->hSet('F2B_BLACKLIST', $network, 1);
$redis->hDel('F2B_WHITELIST', $network, 1);
$response = docker('post', 'netfilter-mailcow', 'restart');
}
}
}

View File

@ -680,7 +680,7 @@ function is_valid_domain_name($domain_name) {
if (empty($domain_name)) {
return false;
}
$domain_name = idn_to_ascii($domain_name);
$domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46);
return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
&& preg_match("/^.{1,253}$/", $domain_name)
&& preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));

View File

@ -322,7 +322,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
return false;
}
$domain = idn_to_ascii(strtolower(trim($_data['domain'])));
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
$description = $_data['description'];
$aliases = $_data['aliases'];
$mailboxes = $_data['mailboxes'];
@ -493,7 +493,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
if (empty($goto)) {
continue;
}
$goto_domain = idn_to_ascii(substr(strstr($goto, '@'), 1));
$goto_domain = idn_to_ascii(substr(strstr($goto, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
$goto_local_part = strstr($goto, '@', true);
$goto = $goto_local_part.'@'.$goto_domain;
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
@ -531,7 +531,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
if (in_array($address, $gotos)) {
continue;
}
$domain = idn_to_ascii(substr(strstr($address, '@'), 1));
$domain = idn_to_ascii(substr(strstr($address, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
$local_part = strstr($address, '@', true);
$address = $local_part.'@'.$domain;
$domaindata = mailbox('get', 'domain_details', $domain);
@ -637,7 +637,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$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'])));
$target_domain = idn_to_ascii(strtolower(trim($_data['target_domain'])), 0, INTL_IDNA_VARIANT_UTS46);
if (!isset($_SESSION['acl']['alias_domains']) || $_SESSION['acl']['alias_domains'] != "1" ) {
$_SESSION['return'][] = array(
'type' => 'danger',
@ -663,7 +663,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
return false;
}
foreach ($alias_domains as $i => $alias_domain) {
$alias_domain = idn_to_ascii(strtolower(trim($alias_domain)));
$alias_domain = idn_to_ascii(strtolower(trim($alias_domain)), 0, INTL_IDNA_VARIANT_UTS46);
if (!is_valid_domain_name($alias_domain)) {
$_SESSION['return'][] = array(
'type' => 'danger',
@ -735,7 +735,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
break;
case 'mailbox':
$local_part = strtolower(trim($_data['local_part']));
$domain = idn_to_ascii(strtolower(trim($_data['domain'])));
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
$username = $local_part . '@' . $domain;
if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
$_SESSION['return'][] = array(
@ -938,7 +938,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
break;
case 'resource':
$domain = idn_to_ascii(strtolower(trim($_data['domain'])));
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
$description = $_data['description'];
$local_part = preg_replace('/[^\da-z]/i', '', preg_quote($description, '/'));
$name = $local_part . '@' . $domain;
@ -1056,11 +1056,11 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
case 'alias_domain':
$alias_domains = (array)$_data['alias_domain'];
foreach ($alias_domains as $alias_domain) {
$alias_domain = idn_to_ascii(strtolower(trim($alias_domain)));
$alias_domain = idn_to_ascii(strtolower(trim($alias_domain)), 0, INTL_IDNA_VARIANT_UTS46);
$is_now = mailbox('get', 'alias_domain_details', $alias_domain);
if (!empty($is_now)) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$target_domain = (!empty($_data['target_domain'])) ? idn_to_ascii(strtolower(trim($_data['target_domain']))) : $is_now['target_domain'];
$target_domain = (!empty($_data['target_domain'])) ? idn_to_ascii(strtolower(trim($_data['target_domain'])), 0, INTL_IDNA_VARIANT_UTS46) : $is_now['target_domain'];
}
else {
$_SESSION['return'][] = array(
@ -1676,7 +1676,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
continue;
}
if ($is_now['address'] != $address) {
$domain = idn_to_ascii(substr(strstr($address, '@'), 1));
$domain = idn_to_ascii(substr(strstr($address, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
$local_part = strstr($address, '@', true);
$address = $local_part.'@'.$domain;
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
@ -1810,7 +1810,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$domains = $_data['domain'];
}
foreach ($domains as $domain) {
$domain = idn_to_ascii($domain);
$domain = idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46);
if (!is_valid_domain_name($domain)) {
$_SESSION['return'][] = array(
'type' => 'danger',
@ -2887,7 +2887,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
break;
case 'domain_details':
$domaindata = array();
$_data = idn_to_ascii(strtolower(trim($_data)));
$_data = idn_to_ascii(strtolower(trim($_data)), 0, INTL_IDNA_VARIANT_UTS46);
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
@ -3308,7 +3308,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
continue;
}
$domain = idn_to_ascii(strtolower(trim($domain)));
$domain = idn_to_ascii(strtolower(trim($domain)), 0, INTL_IDNA_VARIANT_UTS46);
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
WHERE `domain` = :domain");
$stmt->execute(array(':domain' => $domain));

View File

@ -26,7 +26,7 @@ function policy($_action, $_scope, $_data = null) {
);
return false;
}
$object = idn_to_ascii(strtolower(trim($object)));
$object = idn_to_ascii(strtolower(trim($object)), 0, INTL_IDNA_VARIANT_UTS46);
}
else {
$_SESSION['return'][] = array(
@ -183,7 +183,7 @@ function policy($_action, $_scope, $_data = null) {
);
continue;
}
$object = idn_to_ascii(strtolower(trim($object)));
$object = idn_to_ascii(strtolower(trim($object)), 0, INTL_IDNA_VARIANT_UTS46);
}
else {
$_SESSION['return'][] = array(
@ -277,7 +277,7 @@ function policy($_action, $_scope, $_data = null) {
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
$_data = idn_to_ascii(strtolower(trim($_data)));
$_data = idn_to_ascii(strtolower(trim($_data)), 0, INTL_IDNA_VARIANT_UTS46);
}
// WHITELIST

View File

@ -83,7 +83,7 @@ function quarantine($_action, $_data = null) {
$max_size = $_data['max_size'];
$subject = $_data['subject'];
$sender = $_data['sender'];
$html = $_data['html'];
$html = $_data['html_tmpl'];
$exclude_domains = (array)$_data['exclude_domains'];
try {
$redis->Set('Q_RETENTION_SIZE', intval($retention_size));
@ -436,9 +436,9 @@ function quarantine($_action, $_data = null) {
$settings['release_format'] = $redis->Get('Q_RELEASE_FORMAT');
$settings['subject'] = $redis->Get('Q_SUBJ');
$settings['sender'] = $redis->Get('Q_SENDER');
$settings['html'] = htmlspecialchars($redis->Get('Q_HTML'));
if (empty($settings['html'])) {
$settings['html'] = htmlspecialchars(file_get_contents("/tpls/quarantine.tpl"));
$settings['html_tmpl'] = htmlspecialchars($redis->Get('Q_HTML'));
if (empty($settings['html_tmpl'])) {
$settings['html_tmpl'] = htmlspecialchars(file_get_contents("/tpls/quarantine.tpl"));
}
}
catch (RedisException $e) {

View File

@ -0,0 +1,65 @@
<?php
function quota_notification($_action, $_data = null) {
global $redis;
global $lang;
$_data_log = $_data;
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'access_denied'
);
return false;
}
switch ($_action) {
case 'edit':
$retention_size = $_data['retention_size'];
if ($_data['release_format'] == 'attachment' || $_data['release_format'] == 'raw') {
$release_format = $_data['release_format'];
}
else {
$release_format = 'raw';
}
$subject = $_data['subject'];
$sender = $_data['sender'];
$html = $_data['html_tmpl'];
try {
$redis->Set('QW_SENDER', $sender);
$redis->Set('QW_SUBJ', $subject);
$redis->Set('QW_HTML', $html);
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('redis_error', $e)
);
return false;
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'saved_settings'
);
break;
case 'get':
try {
$settings['subject'] = $redis->Get('QW_SUBJ');
$settings['sender'] = $redis->Get('QW_SENDER');
$settings['html_tmpl'] = htmlspecialchars($redis->Get('QW_HTML'));
if (empty($settings['html_tmpl'])) {
$settings['html_tmpl'] = htmlspecialchars(file_get_contents("/tpls/quota.tpl"));
}
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('redis_error', $e)
);
return false;
}
return $settings;
break;
}
}

View File

@ -7,7 +7,7 @@ function tls_policy_maps($_action, $_data = null, $attr = null) {
}
switch ($_action) {
case 'add':
$dest = idn_to_ascii(trim($_data['dest']));
$dest = idn_to_ascii(trim($_data['dest']), 0, INTL_IDNA_VARIANT_UTS46);
$policy = strtolower(trim($_data['policy']));
$parameters = (isset($_data['parameters']) && !empty($_data['parameters'])) ? $_data['parameters'] : '';
if (!empty($parameters)) {

View File

@ -7,10 +7,6 @@
<meta name="theme-color" content="#F5D76E"/>
<meta http-equiv="Referrer-Policy" content="same-origin">
<title><?=$UI_TEXTS['title_name'];?></title>
<!--[if lt IE 9]>
<script src="/js/html5shiv.min.js"></script>
<script src="/js/respond.min.js"></script>
<![endif]-->
<?php if (strtolower(trim($DEFAULT_THEME)) != "lumen"): ?>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.7/<?= strtolower(trim($DEFAULT_THEME)); ?>/bootstrap.min.css">
<?php endif;
@ -117,12 +113,14 @@
<?php
endforeach;
$app_links = customize('get', 'app_links');
foreach ($app_links as $row) {
foreach ($row as $key => $val):
?>
if ($app_links) {
foreach ($app_links as $row) {
foreach ($row as $key => $val):
?>
<li><a href="<?= htmlspecialchars($val); ?>"><?= htmlspecialchars($key); ?></a></li>
<?php
endforeach;
<?php
endforeach;
}
}
?>
</ul>

View File

@ -157,6 +157,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.p
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.domain_admin.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.admin.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quarantine.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quota_notification.inc.php';
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';

View File

@ -44,18 +44,18 @@ $autodiscover_config = array(
// The autoconfig service will additionally announce the STARTTLS-enabled ports, specified in the "tlsport" variable.
'imap' => array(
'server' => $mailcow_hostname,
'port' => array_pop(explode(':', getenv('IMAPS_PORT'))),
'tlsport' => array_pop(explode(':', getenv('IMAP_PORT'))),
'port' => array_key_last(explode(':', getenv('IMAPS_PORT'))),
'tlsport' => array_key_last(explode(':', getenv('IMAP_PORT'))),
),
'pop3' => array(
'server' => $mailcow_hostname,
'port' => array_pop(explode(':', getenv('POPS_PORT'))),
'tlsport' => array_pop(explode(':', getenv('POP_PORT'))),
'port' => array_key_last(explode(':', getenv('POPS_PORT'))),
'tlsport' => array_key_last(explode(':', getenv('POP_PORT'))),
),
'smtp' => array(
'server' => $mailcow_hostname,
'port' => array_pop(explode(':', getenv('SMTPS_PORT'))),
'tlsport' => array_pop(explode(':', getenv('SUBMISSION_PORT'))),
'port' => array_key_last(explode(':', getenv('SMTPS_PORT'))),
'tlsport' => array_key_last(explode(':', getenv('SUBMISSION_PORT'))),
),
'activesync' => array(
'url' => 'https://'.$mailcow_hostname.($https_port == 443 ? '' : ':'.$https_port).'/Microsoft-Server-ActiveSync',

View File

@ -1161,6 +1161,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
case "quarantine":
process_edit_return(quarantine('edit', $attr));
break;
case "quota_notification":
process_edit_return(quota_notification('edit', $attr));
break;
case "mailq":
process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr)));
break;

View File

@ -642,8 +642,11 @@ $lang['admin']['quarantine_retention_size'] = "Rückhaltungen pro Mailbox:<br><s
$lang['admin']['quarantine_max_size'] = "Maximale Größe in MiB (größere Elemente werden verworfen):<br><small>0 bedeutet <b>nicht</b> unlimitert.</small>";
$lang['admin']['quarantine_exclude_domains'] = "Domains und Alias-Domains ausschließen";
$lang['admin']['quarantine_notification_sender'] = "Benachrichtigungs-E-Mail Absender";
$lang['admin']['quota_notification_sender'] = "Benachrichtigungs-E-Mail Absender";
$lang['admin']['quarantine_notification_subject'] = "Benachrichtigungs-E-Mail Betreff";
$lang['admin']['quota_notification_subject'] = "Benachrichtigungs-E-Mail Betreff";
$lang['admin']['quarantine_notification_html'] = "Benachrichtigungs-E-Mail Inhalt:<br><small>Leer lassen, um Standard-Template wiederherzustellen.</small>";
$lang['admin']['quota_notification_html'] = "Benachrichtigungs-E-Mail Inhalt:<br><small>Leer lassen, um Standard-Template wiederherzustellen.</small>";
$lang['admin']['quarantine_release_format'] = "Format freigegebener Mails";
$lang['admin']['quarantine_release_format_raw'] = "Unverändertes Original";
$lang['admin']['quarantine_release_format_att'] = "Als Anhang";

View File

@ -682,6 +682,9 @@ $lang['admin']['quarantine_release_format_att'] = "As attachment";
$lang['admin']['quarantine_notification_sender'] = "Notification email sender";
$lang['admin']['quarantine_notification_subject'] = "Notification email subject";
$lang['admin']['quarantine_notification_html'] = "Notification email template:<br><small>Leave empty to restore default template.</small>";
$lang['admin']['quota_notification_sender'] = "Notification email sender";
$lang['admin']['quota_notification_subject'] = "Notification email subject";
$lang['admin']['quota_notification_html'] = "Notification email template:<br><small>Leave empty to restore default template.</small>";
$lang['admin']['ui_texts'] = "UI labels and texts";
$lang['admin']['help_text'] = "Override help text below login mask (HTML allowed)";
$lang['admin']['title_name'] = '"mailcow UI" website title';