Page MenuHomeWMGMC Issues

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/data/web/admin.php b/data/web/admin.php
index ce3deb69..d97bc141 100644
--- a/data/web/admin.php
+++ b/data/web/admin.php
@@ -1,746 +1,746 @@
<?php
require_once("inc/prerequisites.inc.php");
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") {
require_once("inc/header.inc.php");
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
$tfa_data = get_tfa();
?>
<div class="container">
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#tab-access" aria-controls="tab-access" role="tab" data-toggle="tab"><?=$lang['admin']['access'];?></a></li>
<li role="presentation"><a href="#tab-config" aria-controls="tab-config" role="tab" data-toggle="tab"><?=$lang['admin']['configuration'];?></a></li>
</ul>
<div class="tab-content" style="padding-top:20px">
<div role="tabpanel" class="tab-pane active" id="tab-access">
<div class="panel panel-danger">
<div class="panel-heading"><?=$lang['admin']['admin_details'];?></div>
<div class="panel-body">
<form class="form-horizontal" autocapitalize="none" data-id="admin" autocorrect="off" role="form" method="post">
<?php $admindetails = get_admin_details(); ?>
<div class="form-group">
<label class="control-label col-sm-3" for="admin_user"><?=$lang['admin']['admin'];?>:</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="admin_user" id="admin_user" value="<?=htmlspecialchars($admindetails['username']);?>" required>
&rdsh; <kbd>a-z A-Z - _ .</kbd>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="admin_pass"><?=$lang['admin']['password'];?>:</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="admin_pass" id="admin_pass" placeholder="<?=$lang['admin']['unchanged_if_empty'];?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="admin_pass2"><?=$lang['admin']['password_repeat'];?>:</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="admin_pass2" id="admin_pass2">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<button class="btn btn-default" id="edit_selected" data-id="admin" data-item="admin" data-api-url='edit/self' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</div>
</div>
</form>
<hr>
<div class="row">
<div class="col-sm-3 col-xs-5 text-right"><?=$lang['tfa']['tfa'];?>:</div>
<div class="col-sm-9 col-xs-7">
<p id="tfa_pretty"><?=$tfa_data['pretty'];?></p>
<div id="tfa_additional">
<?php if (!empty($tfa_data['additional'])):
foreach ($tfa_data['additional'] as $key_info): ?>
<form style="display:inline;" method="post">
<input type="hidden" name="unset_tfa_key" value="<?=$key_info['id'];?>" />
<div style="padding:4px;margin:4px" class="label label-<?=($_SESSION['tfa_id'] == $key_info['id']) ? 'success' : 'default'; ?>">
<?=$key_info['key_id'];?>
<a href="#" style="font-weight:bold;color:white" onClick="$(this).closest('form').submit()">[<?=strtolower($lang['admin']['remove']);?>]</a>
</div>
</form>
<?php endforeach;
endif;?>
</div>
<br />
</div>
</div>
<div class="row">
<div class="col-sm-3 col-xs-5 text-right"><?=$lang['tfa']['set_tfa'];?>:</div>
<div class="col-sm-9 col-xs-7">
<select data-width="auto" id="selectTFA" class="selectpicker" title="<?=$lang['tfa']['select'];?>">
<option value="yubi_otp"><?=$lang['tfa']['yubi_otp'];?></option>
<option value="u2f"><?=$lang['tfa']['u2f'];?></option>
<option value="totp"><?=$lang['tfa']['totp'];?></option>
<option value="none"><?=$lang['tfa']['none'];?></option>
</select>
</div>
</div>
</div>
</div>
<div class="hidden panel panel-primary">
<div class="panel-heading">API</div>
<div class="panel-body">
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
<div class="form-group">
<label class="control-label col-sm-3" for="allow_from"><?=$lang['admin']['api_allow_from'];?>:</label>
<div class="col-sm-9">
<textarea class="form-control" rows="5" name="allow_from" id="allow_from" required><?=htmlspecialchars($admindetails['allow_from']);?></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="admin_api_key"><?=$lang['admin']['api_key'];?>:</label>
<div class="col-sm-9">
<input type="text" class="form-control" placeholder="-" value="<?=htmlspecialchars($admindetails['api_key']);?>" readonly>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<label>
<input type="checkbox" name="active" <?=($admindetails['api_active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['activate_api'];?>
</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<div class="btn-group">
<button class="btn btn-default" name="admin_api" type="submit" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-info" name="admin_api_regen_key" type="submit" href="#"><?=$lang['admin']['regen_api_key'];?></button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading"><?=$lang['admin']['domain_admins'];?></div>
<div class="panel-body">
<div class="table-responsive">
<table class="table table-striped" id="domainadminstable"></table>
</div>
<div class="mass-actions-admin">
<div class="btn-group">
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="domain_admins" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
<li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></li>
<li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"disable_tfa":"1"}' href="#"><?=$lang['tfa']['disable_tfa'];?></a></li>
<li role="separator" class="divider"></li>
<li><a id="delete_selected" data-id="domain_admins" data-api-url='delete/domain-admin' href="#"><?=$lang['mailbox']['remove'];?></a></li>
</ul>
<a class="btn btn-sm btn-success" data-id="add_domain_admin" data-toggle="modal" data-target="#addDomainAdminModal" href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add_domain_admin'];?></a>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Rspamd UI</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-sm-9">
<form class="form-horizontal" autocapitalize="none" data-id="admin" autocorrect="off" role="form" method="post">
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<label>
<a href="/rspamd/" target="_blank"><span class="glyphicon glyphicon-new-window" aria-hidden="true"></span> Rspamd UI</a>
</label>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="rspamd_ui_pass"><?=$lang['admin']['password'];?>:</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="rspamd_ui_pass" id="rspamd_ui_pass" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="rspamd_ui_pass2"><?=$lang['admin']['password_repeat'];?>:</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="rspamd_ui_pass2" id="rspamd_ui_pass2" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<button type="submit" class="btn btn-default" id="rspamd_ui" name="rspamd_ui" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</div>
</div>
</form>
</div>
<div class="col-sm-3">
<img class="img-responsive" src="/img/rspamd_logo.png" alt="Rspamd UI" />
</div>
</div>
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tab-config">
<div class="row">
<div id="sidebar-admin" class="col-sm-2 hidden-xs">
<div id="scrollbox" class="list-group">
<a href="#dkim" class="list-group-item"><?=$lang['admin']['dkim_keys'];?></a>
<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="#relayhosts" class="list-group-item">Relayhosts</a>
<a href="#quarantine" class="list-group-item"><?=$lang['admin']['quarantine'];?></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>
</div>
</div>
<div class="col-sm-10">
<span class="anchor" id="dkim"></span>
<div class="panel panel-default">
<div class="panel-heading"><?=$lang['admin']['dkim_keys'];?></div>
<div class="panel-body">
<div class="mass-actions-admin">
<div class="btn-group btn-group-sm">
<button type="button" id="toggle_multi_select_all" data-id="dkim" class="btn btn-default"><?=$lang['mailbox']['toggle_all'];?></button>
<button type="button" id="delete_selected" name="delete_selected" data-id="dkim" data-api-url="delete/dkim" class="btn btn-danger"><?=$lang['admin']['remove'];?></button>
</div>
</div>
<?php
foreach(mailbox('get', 'domains') as $domain) {
if (!empty($dkim = dkim('details', $domain))) {
?>
<div class="row">
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" /></div>
<div class="col-md-3">
<p>Domain: <strong><?=htmlspecialchars($domain);?></strong>
<p class="dkim-label"><span class="label label-success"><?=$lang['admin']['dkim_key_valid'];?></span></p>
<p class="dkim-label"><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
<p class="dkim-label"><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
</p>
</div>
<div class="col-md-8">
<pre><?=$dkim['dkim_txt'];?></pre>
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="<?=$dkim['privkey'];?>"><small>↪ Private key</small></p>
</div>
<hr class="visible-xs visible-sm">
</div>
<?php
}
else {
?>
<div class="row">
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" disabled /></div>
<div class="col-md-3">
<p>Domain: <strong><?=htmlspecialchars($domain);?></strong><br /><span class="label label-danger"><?=$lang['admin']['dkim_key_missing'];?></span></p>
</div>
<div class="col-md-8"><pre>-</pre></div>
<hr class="visible-xs visible-sm">
</div>
<?php
}
foreach(mailbox('get', 'alias_domains', $domain) as $alias_domain) {
if (!empty($dkim = dkim('details', $alias_domain))) {
?>
<div class="row">
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$alias_domain;?>" /></div>
<div class="col-md-2 col-md-offset-1">
<p><small>↳ Alias-Domain: <strong><?=htmlspecialchars($alias_domain);?></strong></small>
<p class="dkim-label"><span class="label label-success"><?=$lang['admin']['dkim_key_valid'];?></span></p>
<p class="dkim-label"><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
<p class="dkim-label"><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
</p>
</div>
<div class="col-md-8">
<pre><?=$dkim['dkim_txt'];?></pre>
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="<?=$dkim['privkey'];?>"><small>↪ Private key</small></p>
</div>
<hr class="visible-xs visible-sm">
</div>
<?php
}
else {
?>
<div class="row">
- <div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" disabled /></div>
+ <div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$alias_domain;?>" disabled /></div>
<div class="col-md-2 col-md-offset-1">
<p><small>↳ Alias-Domain: <strong><?=htmlspecialchars($alias_domain);?></strong><br /></small><span class="label label-danger"><?=$lang['admin']['dkim_key_missing'];?></span></p>
</div>
<div class="col-md-8"><pre>-</pre></div>
<hr class="visible-xs visible-sm">
</div>
<?php
}
}
}
foreach(dkim('blind') as $blind) {
if (!empty($dkim = dkim('details', $blind))) {
?>
<div class="row">
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$blind;?>" /></div>
<div class="col-md-3">
<p>Domain: <strong><?=htmlspecialchars($blind);?></strong>
<p class="dkim-label"><span class="label label-warning"><?=$lang['admin']['dkim_key_unused'];?></span></p>
<p class="dkim-label"><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
<p class="dkim-label"><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
</p>
</div>
<div class="col-md-8">
<pre><?=$dkim['dkim_txt'];?></pre>
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="<?=$dkim['privkey'];?>"><small>↪ Private key</small></p>
</div>
<hr class="visible-xs visible-sm">
</div>
<?php
}
}
?>
<legend style="margin-top:40px"><?=$lang['admin']['dkim_add_key'];?></legend>
<form class="form" data-id="dkim" role="form" method="post">
<div class="form-group">
<label for="domain">Domain</label>
<input class="form-control" id="domain" name="domain" placeholder="example.org" required>
</div>
<div class="form-group">
<label for="domain">Selector</label>
<input class="form-control" id="dkim_selector" name="dkim_selector" value="dkim" required>
</div>
<div class="form-group">
<select data-width="200px" class="form-control" id="key_size" name="key_size" title="<?=$lang['admin']['dkim_key_length'];?>" required>
<option data-subtext="bits">1024</option>
<option data-subtext="bits">2048</option>
</select>
</div>
<button class="btn btn-default" id="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" class="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">
<div class="form-group">
<label for="domain">Domain:</label>
<input class="form-control" id="domain" name="domain" placeholder="example.org" required>
</div>
<div class="form-group">
<label for="domain">Selector:</label>
<input class="form-control" id="dkim_selector" name="dkim_selector" value="dkim" required>
</div>
<div class="form-group">
<label for="private_key_file"><?=$lang['admin']['private_key'];?>:</label>
<textarea class="form-control" rows="5" name="private_key_file" id="private_key_file" required placeholder="-----BEGIN RSA KEY-----"></textarea>
</div>
<button class="btn btn-default" id="add_item" data-id="dkim_import" data-api-url='add/dkim_import' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['import'];?></button>
</form>
</div>
</div>
</div>
<span class="anchor" id="fwdhosts"></span>
<div class="panel panel-default">
<div class="panel-heading"><?=$lang['admin']['forwarding_hosts'];?></div>
<div class="panel-body">
<p style="margin-bottom:40px"><?=$lang['admin']['forwarding_hosts_hint'];?></p>
<div class="table-responsive">
<table class="table table-striped table-condensed" id="forwardinghoststable"></table>
</div>
<div class="mass-actions-admin">
<div class="btn-group btn-group-sm">
<button type="button" id="toggle_multi_select_all" data-id="fwdhosts" class="btn btn-default"><?=$lang['mailbox']['toggle_all'];?></button>
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a id="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"0"}' href="#">Enable spam filter</a></li>
<li><a id="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"1"}' href="#">Disable spam filter</a></li>
<li role="separator" class="divider"></li>
<li><a id="delete_selected" data-id="fwdhosts" data-api-url='delete/fwdhost' href="#"><?=$lang['admin']['remove'];?></a></li>
</ul>
</div>
</div>
<legend><?=$lang['admin']['add_forwarding_host'];?></legend>
<p class="help-block"><?=$lang['admin']['forwarding_hosts_add_hint'];?></p>
<form class="form" data-id="fwdhost" role="form" method="post">
<div class="form-group">
<label for="hostname"><?=$lang['admin']['host'];?></label>
<input class="form-control" id="hostname" name="hostname" placeholder="example.org" required>
</div>
<div class="form-group">
<select data-width="200px" class="form-control" id="filter_spam" name="filter_spam" title="<?=$lang['user']['spamfilter'];?>" required>
<option value="1"><?=$lang['admin']['active'];?></option>
<option value="0"><?=$lang['admin']['inactive'];?></option>
</select>
</div>
<button class="btn btn-default" id="add_item" data-id="fwdhost" data-api-url='add/fwdhost' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
</form>
</div>
</div>
<span class="anchor" id="f2bparams"></span>
<div class="panel panel-default">
<div class="panel-heading"><?=$lang['admin']['f2b_parameters'];?></div>
<div class="panel-body">
<?php
$f2b_data = fail2ban('get');
?>
<form class="form" data-id="f2b" role="form" method="post">
<div class="form-group">
<label for="ban_time"><?=$lang['admin']['f2b_ban_time'];?>:</label>
<input type="number" class="form-control" id="ban_time" name="ban_time" value="<?=$f2b_data['ban_time'];?>" required>
</div>
<div class="form-group">
<label for="max_attempts"><?=$lang['admin']['f2b_max_attempts'];?>:</label>
<input type="number" class="form-control" id="max_attempts" name="max_attempts" value="<?=$f2b_data['max_attempts'];?>" required>
</div>
<div class="form-group">
<label for="retry_window"><?=$lang['admin']['f2b_retry_window'];?>:</label>
<input type="number" class="form-control" id="retry_window" name="retry_window" value="<?=$f2b_data['retry_window'];?>" required>
</div>
<div class="form-group">
<label for="netban_ipv4"><?=$lang['admin']['f2b_netban_ipv4'];?>:</label>
<div class="input-group">
<span class="input-group-addon">/</span>
<input type="number" class="form-control" id="netban_ipv4" name="netban_ipv4" value="<?=$f2b_data['netban_ipv4'];?>" required>
</div>
</div>
<div class="form-group">
<label for="netban_ipv6"><?=$lang['admin']['f2b_netban_ipv6'];?>:</label>
<div class="input-group">
<span class="input-group-addon">/</span>
<input type="number" class="form-control" id="netban_ipv6" name="netban_ipv6" value="<?=$f2b_data['netban_ipv6'];?>" required>
</div>
</div>
<p class="help-block"><?=$lang['admin']['f2b_list_info'];?></p>
<div class="form-group">
<label for="whitelist"><?=$lang['admin']['f2b_whitelist'];?>:</label>
<textarea class="form-control" id="whitelist" name="whitelist" rows="5"><?=$f2b_data['whitelist'];?></textarea>
</div>
<div class="form-group">
<label for="blacklist"><?=$lang['admin']['f2b_blacklist'];?>:</label>
<textarea class="form-control" id="blacklist" name="blacklist" rows="5"><?=$f2b_data['blacklist'];?></textarea>
</div>
<div class="btn-group">
<button class="btn btn-default" id="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<a href="#" role="button" class="btn btn-default" data-toggle="modal" data-container="netfilter-mailcow" data-target="#RestartContainer"><span class="glyphicon glyphicon-refresh"></span> <?= $lang['header']['restart_netfilter']; ?></a>
</div>
</form>
<hr>
<p class="help-block"><?=$lang['admin']['ban_list_info'];?></p>
<?php
if (empty($f2b_data['active_bans']) && empty($f2b_data['perm_bans'])):
?>
<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):
?>
<a id="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 id="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 id="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
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;
?>
</div>
</div>
<span class="anchor" id="relayhosts"></span>
<div class="panel panel-default">
<div class="panel-heading">Relayhosts</div>
<div class="panel-body">
<p style="margin-bottom:40px"><?=$lang['admin']['relayhosts_hint'];?></p>
<div class="table-responsive">
<table class="table table-striped table-condensed" id="relayhoststable"></table>
</div>
<div class="mass-actions-admin">
<div class="btn-group btn-group-sm">
<button type="button" id="toggle_multi_select_all" data-id="rlyhosts" class="btn btn-default"><?=$lang['mailbox']['toggle_all'];?></button>
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a id="edit_selected" data-id="rlyhosts" data-api-url='edit/relayhost' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
<li><a id="edit_selected" data-id="rlyhosts" data-api-url='edit/relayhost' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></li>
<li><a id="delete_selected" data-id="rlyhosts" data-api-url='delete/relayhost' href="#"><?=$lang['admin']['remove'];?></a></li>
</ul>
</div>
</div>
<legend><?=$lang['admin']['add_relayhost'];?></legend>
<p class="help-block"><?=$lang['admin']['add_relayhost_add_hint'];?></p>
<form class="form" data-id="rlyhost" role="form" method="post">
<div class="form-group">
<label for="hostname"><?=$lang['admin']['host'];?></label>
<input class="form-control" id="hostname" name="hostname" required>
</div>
<div class="form-group">
<label for="hostname"><?=$lang['admin']['username'];?></label>
<input class="form-control" id="username" name="username">
</div>
<div class="form-group">
<label for="hostname"><?=$lang['admin']['password'];?></label>
<input class="form-control" id="password" name="password">
</div>
<button class="btn btn-default" id="add_item" data-id="rlyhost" data-api-url='add/relayhost' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
</form>
</div>
</div>
<span class="anchor" id="quarantine"></span>
<div class="panel panel-default">
<div class="panel-heading"><?=$lang['admin']['quarantine'];?></div>
<div class="panel-body">
<?php $q_data = quarantine('settings'); ?>
<form class="form" data-id="quarantine" role="form" method="post">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="retention_size"><?=$lang['admin']['quarantine_retention_size'];?></label>
<input type="number" class="form-control" id="retention_size" name="retention_size" value="<?=$q_data['retention_size'];?>" placeholder="0" required>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="max_size"><?=$lang['admin']['quarantine_max_size'];?></label>
<input type="number" class="form-control" id="max_size" name="max_size" value="<?=$q_data['max_size'];?>" placeholder="0" required>
</div>
</div>
</div>
<div class="form-group">
<label for="exclude_domains"><?=$lang['admin']['quarantine_exclude_domains'];?></label><br />
<select data-width="100%" id="exclude_domains" name="exclude_domains" class="selectpicker" title="<?=$lang['tfa']['select'];?>" multiple>
<?php
foreach (array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')) as $domain):
?>
<option <?=(in_array($domain, $q_data['exclude_domains'])) ? 'selected' : null;?>><?=htmlspecialchars($domain);?></option>
<?php
endforeach;
?>
</select>
</div>
<button class="btn btn-default" id="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</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" rows="20" id="settings_map" name="settings_map" readonly><?=file_get_contents('http://nginx:8081/settings.php');?></textarea>
<hr>
<?php $rsettings = rsettings('get'); ?>
<form class="form" data-id="rsettings" role="form" method="post">
<div class="row">
<div class="col-sm-3">
<div class="list-group">
<?php
if (empty($rsettings)):
?>
<span class="list-group-item"><em><?=$lang['admin']['rsetting_none'];?></em></span>
<?php
else:
foreach ($rsettings as $rsetting):
$rsetting_details = rsettings('details', $rsetting['id']);
?>
<a href="#<?=$rsetting_details['id'];?>" class="list-group-item list-group-item-<?=($rsetting_details['active_int'] == '1') ? 'success' : ''; ?>" data-dont-remember="1" data-toggle="tab"><?=$rsetting_details['desc'];?> (ID #<?=$rsetting['id'];?>)</a>
<?php
endforeach;
endif;
?>
<a href="#" class="list-group-item list-group-item-default"
data-id="add_domain_admin"
data-toggle="modal"
data-dont-remember="1"
data-target="#addRsettingModal"
data-toggle="tab"><?=$lang['admin']['rsetting_add_rule'];?></a>
</div>
</div>
<div class="col-sm-9">
<div class="tab-content">
<?php
if (empty($rsettings)):
?>
<div id="none" class="tab-pane active">
<p class="help-block"><?=$lang['admin']['rsetting_none'];?></p>
</div>
<?php
else:
?>
<div id="none" class="tab-pane active">
<p class="help-block"><?=$lang['admin']['rsetting_no_selection'];?></p>
</div>
<?php
foreach ($rsettings as $rsetting):
$rsetting_details = rsettings('details', $rsetting['id']);
?>
<div id="<?=$rsetting_details['id'];?>" class="tab-pane">
<form class="form" data-id="rsettings" role="form" method="post">
<input type="hidden" name="active" value="0">
<div class="form-group">
<label for="desc"><?=$lang['admin']['rsetting_desc'];?>:</label>
<input type="text" class="form-control" id="desc" name="desc" value="<?=$rsetting_details['desc'];?>">
</div>
<div class="form-group">
<label for="content"><?=$lang['admin']['rsetting_content'];?>:</label>
<textarea class="form-control" id="content" name="content" rows="10"><?=$rsetting_details['content'];?></textarea>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="active" value="1" <?=($rsetting_details['active_int'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['active'];?>
</label>
</div>
<button class="btn btn-default" id="edit_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url='edit/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-danger" id="delete_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url="delete/rsetting" data-api-attr='{}' href="#"><?=$lang['admin']['remove'];?></button>
</form>
</div>
<?php
endforeach;
endif;
?>
</div>
</div>
</div>
</form>
</div>
</div>
<span class="anchor" id="customize"></span>
<div class="panel panel-default">
<div class="panel-heading"><?=$lang['admin']['customize'];?></div>
<div class="panel-body">
<legend><?=$lang['admin']['change_logo'];?></legend>
<p class="help-block"><?=$lang['admin']['logo_info'];?></p>
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
<p>
<input type="file" name="main_logo" class="filestyle" data-buttonName="btn-default" data-buttonText="Select" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml">
<button name="submit_main_logo" type="submit" class="btn btn-default"><span class="glyphicon glyphicon-cloud-upload"></span> <?=$lang['admin']['upload'];?></button>
</p>
</form>
<?php
if ($main_logo = customize('get', 'main_logo')):
$specs = customize('get', 'main_logo_specs');
?>
<div class="row">
<div class="col-sm-3">
<div class="thumbnail">
<img class="img-thumbnail" src="<?=$main_logo;?>" alt="mailcow logo">
<div class="caption">
<span class="label label-info"><?=$specs['geometry']['width'];?>x<?=$specs['geometry']['height'];?> px</span>
<span class="label label-info"><?=$specs['mimetype'];?></span>
<span class="label label-info"><?=$specs['fileSize'];?></span>
</div>
</div>
<hr>
<form class="form-inline" role="form" method="post">
<p><button name="reset_main_logo" type="submit" class="btn btn-xs btn-default"><?=$lang['admin']['reset_default'];?></button></p>
</form>
</div>
</div>
<?php
endif;
?>
<legend><?=$lang['admin']['app_links'];?></legend>
<p class="help-block"><?=$lang['admin']['merged_vars_hint'];?></p>
<form class="form-inline" data-id="app_links" role="form" method="post">
<table class="table table-condensed" style="white-space: nowrap;" id="app_link_table">
<tr>
<th><?=$lang['admin']['app_name'];?></th>
<th><?=$lang['admin']['link'];?></th>
<th>&nbsp;</th>
</tr>
<?php
$app_links = customize('get', 'app_links');
foreach ($app_links as $row) {
foreach ($row as $key => $val):
?>
<tr>
<td><input class="input-sm form-control" data-id="app_links" type="text" name="app" required value="<?=$key;?>"></td>
<td><input class="input-sm form-control" data-id="app_links" type="text" name="href" required value="<?=$val;?>"></td>
<td><a href="#" role="button" class="btn btn-xs btn-default" type="button"><?=$lang['admin']['remove_row'];?></a></td>
</tr>
<?php
endforeach;
}
foreach ($MAILCOW_APPS as $app):
?>
<tr>
<td><input class="input-sm form-control" value="<?=htmlspecialchars($app['name']);?>" disabled></td>
<td><input class="input-sm form-control" value="<?=htmlspecialchars($app['link']);?>" disabled></td>
<td>&nbsp;</td>
</tr>
<?php
endforeach;
?>
</table>
<p><div class="btn-group">
<button class="btn btn-sm btn-default" id="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<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>
<?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" id="title_name" 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" id="main_name" 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" id="apps_name" 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" id="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>
</div>
</div>
</div> <!-- /container -->
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/admin.php';
?>
<script type='text/javascript'>
<?php
$lang_admin = json_encode($lang['admin']);
echo "var lang = ". $lang_admin . ";\n";
echo "var csrf_token = '". $_SESSION['CSRF']['TOKEN'] . "';\n";
echo "var pagination_size = '". $PAGINATION_SIZE . "';\n";
echo "var log_pagination_size = '". $LOG_PAGINATION_SIZE . "';\n";
?>
</script>
<script src="js/footable.min.js"></script>
<script src="js/admin.js"></script>
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
} else {
header('Location: /');
exit();
}
?>
diff --git a/data/web/autodiscover.php b/data/web/autodiscover.php
index 391b4a93..f5bcbf8f 100644
--- a/data/web/autodiscover.php
+++ b/data/web/autodiscover.php
@@ -1,208 +1,208 @@
<?php
require_once 'inc/vars.inc.php';
require_once 'inc/functions.inc.php';
$default_autodiscover_config = $autodiscover_config;
if(file_exists('inc/vars.local.inc.php')) {
include_once 'inc/vars.local.inc.php';
}
$autodiscover_config = array_merge($default_autodiscover_config, $autodiscover_config);
// Redis
$redis = new Redis();
$redis->connect('redis-mailcow', 6379);
error_reporting(0);
$data = trim(file_get_contents("php://input"));
if (strpos($data, 'autodiscover/outlook/responseschema') !== false) {
$autodiscover_config['autodiscoverType'] = 'imap';
if ($autodiscover_config['useEASforOutlook'] == 'yes' &&
// Office for macOS does not support EAS
strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') === false &&
// Outlook 2013 (version 15) or higher
preg_match('/(Outlook|Office).+1[5-9]\./', $_SERVER['HTTP_USER_AGENT'])
) {
$autodiscover_config['autodiscoverType'] = 'activesync';
}
}
$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $database_user, $database_pass, $opt);
$login_user = strtolower(trim($_SERVER['PHP_AUTH_USER']));
$login_pass = trim(htmlspecialchars_decode($_SERVER['PHP_AUTH_PW']));
if (empty($_SERVER['PHP_AUTH_USER']) || empty($_SERVER['PHP_AUTH_PW'])) {
$json = json_encode(
array(
"time" => time(),
"ua" => $_SERVER['HTTP_USER_AGENT'],
"user" => "none",
"service" => "Error: must be authenticated"
)
);
$redis->lPush('AUTODISCOVER_LOG', $json);
header('WWW-Authenticate: Basic realm="' . $_SERVER['HTTP_HOST'] . '"');
header('HTTP/1.0 401 Unauthorized');
exit(0);
}
$login_role = check_login($login_user, $login_pass);
if ($login_role === "user") {
header("Content-Type: application/xml");
echo '<?xml version="1.0" encoding="utf-8" ?>' . PHP_EOL;
?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<?php
if(!$data) {
try {
$json = json_encode(
array(
"time" => time(),
"ua" => $_SERVER['HTTP_USER_AGENT'],
"user" => $_SERVER['PHP_AUTH_USER'],
"service" => "Error: invalid or missing request data"
)
);
$redis->lPush('AUTODISCOVER_LOG', $json);
$redis->lTrim('AUTODISCOVER_LOG', 0, 100);
}
catch (RedisException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'msg' => 'Redis: '.$e
);
return false;
}
list($usec, $sec) = explode(' ', microtime());
?>
<Response>
<Error Time="<?=date('H:i:s', $sec) . substr($usec, 0, strlen($usec) - 2);?>" Id="2477272013">
<ErrorCode>600</ErrorCode>
<Message>Invalid Request</Message>
<DebugData />
</Error>
</Response>
</Autodiscover>
<?php
exit(0);
}
try {
$discover = new SimpleXMLElement($data);
$email = $discover->Request->EMailAddress;
} catch (Exception $e) {
$email = $_SERVER['PHP_AUTH_USER'];
}
$username = trim($email);
try {
$stmt = $pdo->prepare("SELECT `name` FROM `mailbox` WHERE `username`= :username");
$stmt->execute(array(':username' => $username));
$MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
}
catch(PDOException $e) {
die("Failed to determine name from SQL");
}
if (!empty($MailboxData['name'])) {
$displayname = $MailboxData['name'];
}
else {
$displayname = $email;
}
try {
$json = json_encode(
array(
"time" => time(),
"ua" => $_SERVER['HTTP_USER_AGENT'],
"user" => $_SERVER['PHP_AUTH_USER'],
"service" => $autodiscover_config['autodiscoverType']
)
);
$redis->lPush('AUTODISCOVER_LOG', $json);
$redis->lTrim('AUTODISCOVER_LOG', 0, 100);
}
catch (RedisException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'msg' => 'Redis: '.$e
);
return false;
}
if ($autodiscover_config['autodiscoverType'] == 'imap') {
?>
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
<User>
<DisplayName><?=htmlspecialchars($displayname, ENT_XML1 | ENT_QUOTES, 'UTF-8');?></DisplayName>
</User>
<Account>
<AccountType>email</AccountType>
<Action>settings</Action>
<Protocol>
<Type>IMAP</Type>
<Server><?=$autodiscover_config['imap']['server'];?></Server>
<Port><?=$autodiscover_config['imap']['port'];?></Port>
<DomainRequired>off</DomainRequired>
<LoginName><?=$email;?></LoginName>
<SPA>off</SPA>
<SSL>on</SSL>
<AuthRequired>on</AuthRequired>
</Protocol>
<Protocol>
<Type>SMTP</Type>
<Server><?=$autodiscover_config['smtp']['server'];?></Server>
<Port><?=$autodiscover_config['smtp']['port'];?></Port>
<DomainRequired>off</DomainRequired>
<LoginName><?=$email;?></LoginName>
<SPA>off</SPA>
<SSL>on</SSL>
<AuthRequired>on</AuthRequired>
<UsePOPAuth>on</UsePOPAuth>
<SMTPLast>off</SMTPLast>
</Protocol>
<Protocol>
<Type>CalDAV</Type>
<Server>https://<?=$autodiscover_config['caldav']['server'];?><?php if ($autodiscover_config['caldav']['port'] != 443) echo ':'.$autodiscover_config['caldav']['port']; ?>/SOGo/dav/<?=$email;?>/</Server>
<DomainRequired>off</DomainRequired>
<LoginName><?=$email;?></LoginName>
</Protocol>
<Protocol>
<Type>CardDAV</Type>
<Server>https://<?=$autodiscover_config['carddav']['server'];?><?php if ($autodiscover_config['caldav']['port'] != 443) echo ':'.$autodiscover_config['carddav']['port']; ?>/SOGo/dav/<?=$email;?>/</Server>
<DomainRequired>off</DomainRequired>
<LoginName><?=$email;?></LoginName>
</Protocol>
</Account>
</Response>
<?php
}
else if ($autodiscover_config['autodiscoverType'] == 'activesync') {
?>
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006">
<Culture>en:en</Culture>
<User>
<DisplayName><?=htmlspecialchars($displayname, ENT_XML1 | ENT_QUOTES, 'UTF-8');?></DisplayName>
<EMailAddress><?=$email;?></EMailAddress>
</User>
<Action>
<Settings>
<Server>
<Type>MobileSync</Type>
<Url><?=$autodiscover_config['activesync']['url'];?></Url>
<Name><?=$autodiscover_config['activesync']['url'];?></Name>
</Server>
</Settings>
</Action>
</Response>
<?php
}
?>
</Autodiscover>
<?php
}
?>
diff --git a/data/web/edit.php b/data/web/edit.php
index d605d3f4..1efbbed3 100644
--- a/data/web/edit.php
+++ b/data/web/edit.php
@@ -1,972 +1,978 @@
<?php
require_once("inc/prerequisites.inc.php");
$AuthUsers = array("admin", "domainadmin", "user");
if (!isset($_SESSION['mailcow_cc_role']) OR !in_array($_SESSION['mailcow_cc_role'], $AuthUsers)) {
header('Location: /');
exit();
}
require_once("inc/header.inc.php");
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><?=$lang['edit']['title'];?></h3>
</div>
<div class="panel-body">
<?php
if (isset($_SESSION['mailcow_cc_role'])) {
if ($_SESSION['mailcow_cc_role'] == "admin" || $_SESSION['mailcow_cc_role'] == "domainadmin") {
if (isset($_GET["alias"]) &&
!empty($_GET["alias"])) {
$alias = html_entity_decode(rawurldecode($_GET["alias"]));
$result = mailbox('get', 'alias_details', $alias);
if (!empty($result)) {
?>
<h4><?=$lang['edit']['alias'];?></h4>
<br />
<form class="form-horizontal" data-id="editalias" role="form" method="post">
<input type="hidden" value="0" name="active">
+ <div class="form-group">
+ <label class="control-label col-sm-2" for="address"><?=$lang['edit']['alias'];?></label>
+ <div class="col-sm-10">
+ <input class="form-control" type="text" name="address" value="<?=htmlspecialchars($result['address']);?>" />
+ </div>
+ </div>
<div class="form-group">
<label class="control-label col-sm-2" for="goto"><?=$lang['edit']['target_address'];?></label>
<div class="col-sm-10">
<textarea id="textarea_alias_goto" class="form-control" autocapitalize="none" autocorrect="off" rows="10" id="goto" name="goto" required><?= (!preg_match('/^(null|ham|spam)@localhost$/i', $result['goto'])) ? htmlspecialchars($result['goto']) : null; ?></textarea>
<div class="checkbox">
<label><input class="goto_checkbox"id="goto_null" type="checkbox" value="1" name="goto_null" <?= ($result['goto'] == "null@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_null'];?></label>
</div>
<div class="checkbox">
<label><input class="goto_checkbox" id="goto_spam" type="checkbox" value="1" name="goto_spam" <?= ($result['goto'] == "spam@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_spam'];?></label>
</div>
<div class="checkbox">
<label><input class="goto_checkbox" id="goto_ham" type="checkbox" value="1" name="goto_ham" <?= ($result['goto'] == "ham@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_ham'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editalias" data-item="<?=htmlspecialchars($alias);?>" data-api-url='edit/alias' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
elseif (isset($_GET['domainadmin']) &&
ctype_alnum(str_replace(array('_', '.', '-'), '', $_GET["domainadmin"])) &&
!empty($_GET["domainadmin"]) &&
$_GET["domainadmin"] != 'admin' &&
$_SESSION['mailcow_cc_role'] == "admin") {
$domain_admin = $_GET["domainadmin"];
$result = domain_admin('details', $domain_admin);
if (!empty($result)) {
?>
<h4><?=$lang['edit']['domain_admin'];?></h4>
<br />
<form class="form-horizontal" data-id="editdomainadmin" role="form" method="post">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="username_new"><?=$lang['edit']['username'];?></label>
<div class="col-sm-10">
<input class="form-control" type="text" name="username_new" value="<?=htmlspecialchars($domain_admin);?>" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="domains"><?=$lang['edit']['domains'];?></label>
<div class="col-sm-10">
<select data-live-search="true" id="domains" name="domains" multiple required>
<?php
foreach ($result['selected_domains'] as $domain):
?>
<option selected><?=htmlspecialchars($domain);?></option>
<?php
endforeach;
foreach ($result['unselected_domains'] as $domain):
?>
<option><?=htmlspecialchars($domain);?></option>
<?php
endforeach;
?>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['edit']['password'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password" id="password" placeholder="">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password2"><?=$lang['edit']['password_repeat'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password2" id="password2">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="disable_tfa"> <?=$lang['tfa']['disable_tfa'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editdomainadmin" data-item="<?=$domain_admin;?>" data-api-url='edit/domain-admin' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
elseif (isset($_GET['domain']) &&
is_valid_domain_name($_GET["domain"]) &&
!empty($_GET["domain"])) {
$domain = $_GET["domain"];
$result = mailbox('get', 'domain_details', $domain);
$rl = mailbox('get', 'ratelimit', $domain);
$rlyhosts = relayhost('get');
if (!empty($result)) {
?>
<h4><?=$lang['edit']['domain'];?></h4>
<form data-id="editdomain" class="form-horizontal" role="form" method="post">
<input type="hidden" value="0" name="active">
<input type="hidden" value="0" name="backupmx">
<input type="hidden" value="0" name="relay_all_recipients">
<div class="form-group">
<label class="control-label col-sm-2" for="description"><?=$lang['edit']['description'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="description" id="description" value="<?=htmlspecialchars($result['description']);?>">
</div>
</div>
<?php
if ($_SESSION['mailcow_cc_role'] == "admin") {
?>
<div class="form-group">
<label class="control-label col-sm-2" for="aliases"><?=$lang['edit']['max_aliases'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="aliases" id="aliases" value="<?=intval($result['max_num_aliases_for_domain']);?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="mailboxes"><?=$lang['edit']['max_mailboxes'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="mailboxes" id="mailboxes" value="<?=intval($result['max_num_mboxes_for_domain']);?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="maxquota"><?=$lang['edit']['max_quota'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="maxquota" id="maxquota" value="<?=intval($result['max_quota_for_mbox'] / 1048576);?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="quota"><?=$lang['edit']['domain_quota'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="quota" id="quota" value="<?=intval($result['max_quota_for_domain'] / 1048576);?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="quota">Relayhost</label>
<div class="col-sm-10">
<select data-live-search="true" name="relayhost" id="relayhost" class="form-control">
<?php
foreach ($rlyhosts as $rlyhost) {
?>
<option value="<?=$rlyhost['id'];?>" <?=($result['relayhost'] == $rlyhost['id']) ? 'selected' : null;?>>ID <?=$rlyhost['id'];?>: <?=$rlyhost['hostname'];?> (<?=$rlyhost['username'];?>)</option>
<?php
}
?>
<option value="" <?=($result['relayhost'] == "0") ? 'selected' : null;?>>None</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2"><?=$lang['edit']['backup_mx_options'];?></label>
<div class="col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="backupmx" <?=(isset($result['backupmx_int']) && $result['backupmx_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['relay_domain'];?></label>
<br />
<label><input type="checkbox" value="1" name="relay_all_recipients" <?=(isset($result['relay_all_recipients_int']) && $result['relay_all_recipients_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['relay_all'];?></label>
<p><?=$lang['edit']['relay_all_info'];?></p>
</div>
</div>
</div>
<?php
}
?>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?=(isset($result['active_int']) && $result['active_int']=="1") ? "checked" : null;?> <?=($_SESSION['mailcow_cc_role'] == "admin") ? null : "disabled";?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editdomain" data-item="<?=$domain;?>" data-api-url='edit/domain' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
</div>
</div>
</form>
<?php
if (!empty($dkim = dkim('details', $domain))) {
?>
<hr>
<div class="row">
<div class="col-xs-2">
<p>Domain: <strong><?=htmlspecialchars($result['domain_name']);?></strong> (<?=$dkim['dkim_selector'];?>._domainkey)</p>
</div>
<div class="col-xs-10">
<pre><?=$dkim['dkim_txt'];?></pre>
</div>
</div>
<?php
}
?>
<hr>
<form data-id="domratelimit" class="form-inline well" method="post">
<div class="form-group">
<label class="control-label">Ratelimit</label>
<input name="rl_value" id="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
</div>
<div class="form-group">
<select name="rl_frame" id="rl_frame" class="form-control">
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
</select>
</div>
<div class="form-group">
<button class="btn btn-default" id="edit_selected" data-id="domratelimit" data-item="<?=$domain;?>" data-api-url='edit/ratelimit' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
</div>
</form>
<hr>
<div class="row">
<div class="col-sm-6">
<h4><?=$lang['user']['spamfilter_wl'];?></h4>
<p><?=$lang['user']['spamfilter_wl_desc'];?></p>
<div class="table-responsive">
<table class="table table-striped table-condensed" id="wl_policy_domain_table"></table>
</div>
<div class="mass-actions-user">
<div class="btn-group">
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="policy_wl_domain" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
<a class="btn btn-sm btn-danger" id="delete_selected" data-id="policy_wl_domain" data-api-url='delete/domain-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
</ul>
</div>
</div>
<form class="form-inline" data-id="add_wl_policy_domain">
<div class="input-group">
<input type="text" class="form-control" name="object_from" id="object_from" placeholder="*@example.org" required>
<span class="input-group-btn">
<button class="btn btn-default" id="add_item" data-id="add_wl_policy_domain" data-api-url='add/domain-policy' data-api-attr='{"domain":"<?= $domain; ?>","object_list":"wl"}' href="#"><?=$lang['user']['spamfilter_table_add'];?></button>
</span>
</div>
</form>
</div>
<div class="col-sm-6">
<h4><?=$lang['user']['spamfilter_bl'];?></h4>
<p><?=$lang['user']['spamfilter_bl_desc'];?></p>
<div class="table-responsive">
<table class="table table-striped table-condensed" id="bl_policy_domain_table"></table>
</div>
<div class="mass-actions-user">
<div class="btn-group">
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="policy_bl_domain" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
<a class="btn btn-sm btn-danger" id="delete_selected" data-id="policy_bl_domain" data-api-url='delete/domain-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
</ul>
</div>
</div>
<form class="form-inline" data-id="add_bl_policy_domain">
<div class="input-group">
<input type="text" class="form-control" name="object_from" id="object_from" placeholder="*@example.org" required>
<span class="input-group-btn">
<button class="btn btn-default" id="add_item" data-id="add_bl_policy_domain" data-api-url='add/domain-policy' data-api-attr='{"domain":"<?= $domain; ?>","object_list":"bl"}' href="#"><?=$lang['user']['spamfilter_table_add'];?></button>
</span>
</div>
</form>
</div>
</div>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
elseif (isset($_GET['aliasdomain']) &&
is_valid_domain_name(html_entity_decode(rawurldecode($_GET["aliasdomain"]))) &&
!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);
if (!empty($result)) {
?>
<h4><?=$lang['edit']['edit_alias_domain'];?></h4>
<form class="form-horizontal" data-id="editaliasdomain" role="form" method="post">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="target_domain"><?=$lang['edit']['target_domain'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="target_domain" id="target_domain" value="<?=htmlspecialchars($result['target_domain']);?>">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?=(isset($result['active_int']) && $result['active_int']=="1") ? "checked" : null ?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editaliasdomain" data-item="<?=$alias_domain;?>" data-api-url='edit/alias-domain' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<hr>
<form data-id="domratelimit" class="form-inline well" method="post">
<div class="form-group">
<label class="control-label">Ratelimit</label>
<input name="rl_value" id="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
</div>
<div class="form-group">
<select name="rl_frame" id="rl_frame" class="form-control">
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
</select>
</div>
<div class="form-group">
<button class="btn btn-default" id="edit_selected" data-id="domratelimit" data-item="<?=$alias_domain;?>" data-api-url='edit/ratelimit' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
</div>
</form>
<?php
if (!empty($dkim = dkim('details', $alias_domain))) {
?>
<hr>
<div class="row">
<div class="col-xs-2">
<p>Domain: <strong><?=htmlspecialchars($result['alias_domain']);?></strong> (<?=$dkim['dkim_selector'];?>._domainkey)</p>
</div>
<div class="col-xs-10">
<pre><?=$dkim['dkim_txt'];?></pre>
</div>
</div>
<?php
}
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
elseif (isset($_GET['mailbox']) && filter_var(html_entity_decode(rawurldecode($_GET["mailbox"])), FILTER_VALIDATE_EMAIL) && !empty($_GET["mailbox"])) {
$mailbox = html_entity_decode(rawurldecode($_GET["mailbox"]));
$result = mailbox('get', 'mailbox_details', $mailbox);
$rl = mailbox('get', 'ratelimit', $mailbox);
if (!empty($result)) {
?>
<h4><?=$lang['edit']['mailbox'];?></h4>
<form class="form-horizontal" data-id="editmailbox" role="form" method="post">
<input type="hidden" value="default" name="sender_acl">
<input type="hidden" value="0" name="active">
<input type="hidden" value="0" name="force_pw_update">
<div class="form-group">
<label class="control-label col-sm-2" for="name"><?=$lang['edit']['full_name'];?>:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" id="name" value="<?=htmlspecialchars($result['name'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="quota"><?=$lang['edit']['quota_mb'];?>:
<br /><span id="quotaBadge" class="badge">max. <?=intval($result['max_new_quota'] / 1048576)?> MiB</span>
</label>
<div class="col-sm-10">
<input type="number" name="quota" id="quota" id="destroyable" style="width:100%" min="1" max="<?=intval($result['max_new_quota'] / 1048576);?>" value="<?=intval($result['quota']) / 1048576;?>" class="form-control">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="sender_acl"><?=$lang['edit']['sender_acl'];?>:</label>
<div class="col-sm-10">
<select data-live-search="true" data-width="100%" style="width:100%" id="sender_acl" name="sender_acl" size="10" multiple>
<?php
$sender_acl_handles = mailbox('get', 'sender_acl_handles', $mailbox);
foreach ($sender_acl_handles['sender_acl_domains']['ro'] as $domain):
?>
<option data-subtext="Admin" value="<?=htmlspecialchars($domain);?>" disabled selected><?=htmlspecialchars(sprintf($lang['edit']['dont_check_sender_acl'], $domain));?></option>
<?php
endforeach;
foreach ($sender_acl_handles['sender_acl_addresses']['ro'] as $domain):
?>
<option data-subtext="Admin" disabled selected><?=htmlspecialchars($alias);?></option>
<?php
endforeach;
foreach ($sender_acl_handles['fixed_sender_aliases'] as $alias):
?>
<option data-subtext="Alias" disabled selected><?=htmlspecialchars($alias);?></option>
<?php
endforeach;
foreach ($sender_acl_handles['sender_acl_domains']['rw'] as $domain):
?>
<option value="<?=htmlspecialchars($domain);?>" selected><?=htmlspecialchars(sprintf($lang['edit']['dont_check_sender_acl'], $domain));?></option>
<?php
endforeach;
foreach ($sender_acl_handles['sender_acl_domains']['selectable'] as $domain):
?>
<option value="<?=htmlspecialchars($domain);?>"><?=htmlspecialchars(sprintf($lang['edit']['dont_check_sender_acl'], $domain));?></option>
<?php
endforeach;
foreach ($sender_acl_handles['sender_acl_addresses']['rw'] as $address):
?>
<option selected><?=htmlspecialchars($address);?></option>
<?php
endforeach;
foreach ($sender_acl_handles['sender_acl_addresses']['selectable'] as $address):
?>
<option><?=htmlspecialchars($address);?></option>
<?php
endforeach;
?>
</select>
<div style="display:none" id="sender_acl_disabled"><?=$lang['edit']['sender_acl_disabled'];?></div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['edit']['password'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password" id="password" placeholder="<?=$lang['edit']['unchanged_if_empty'];?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password2"><?=$lang['edit']['password_repeat'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password2" id="password2">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?=($result['active_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="force_pw_update" <?=($result['attributes']['force_pw_update']=="1") ? "checked" : null;?>> <?=$lang['edit']['force_pw_update'];?></label>
<small class="help-block"><?=$lang['edit']['force_pw_update_info'];?></small>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editmailbox" data-item="<?=htmlspecialchars($result['username']);?>" data-api-url='edit/mailbox' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<hr>
<form data-id="mboxratelimit" class="form-inline well" method="post">
<div class="row">
<div class="col-sm-1">
<p class="help-block">Ratelimit</p>
</div>
<div class="col-sm-10">
<div class="form-group">
<input name="rl_value" id="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
</div>
<div class="form-group">
<select name="rl_frame" id="rl_frame" class="form-control">
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
</select>
</div>
<div class="form-group">
<button class="btn btn-default" id="edit_selected" data-id="mboxratelimit" data-item="<?=htmlspecialchars($mailbox);?>" data-api-url='edit/ratelimit' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
</div>
</div>
</div>
</form>
<?php
}
}
elseif (isset($_GET['relayhost']) && is_numeric($_GET["relayhost"]) && !empty($_GET["relayhost"])) {
$relayhost = intval($_GET["relayhost"]);
$result = relayhost('details', $relayhost);
if (!empty($result)) {
?>
<h4><?=$lang['edit']['resource'];?></h4>
<form class="form-horizontal" role="form" method="post" data-id="editrelayhost">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="hostname"><?=$lang['add']['hostname'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="hostname" id="hostname" value="<?=htmlspecialchars($result['hostname'], ENT_QUOTES, 'UTF-8');?>" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="username" id="username" value="<?=htmlspecialchars($result['username'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['add']['password'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password" id="password" value="<?=htmlspecialchars($result['password'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?=($result['active_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editrelayhost" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/relayhost' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
elseif (isset($_GET['resource']) && filter_var(html_entity_decode(rawurldecode($_GET["resource"])), FILTER_VALIDATE_EMAIL) && !empty($_GET["resource"])) {
$resource = html_entity_decode(rawurldecode($_GET["resource"]));
$result = mailbox('get', 'resource_details', $resource);
if (!empty($result)) {
?>
<h4><?=$lang['edit']['resource'];?></h4>
<form class="form-horizontal" role="form" method="post" data-id="editresource">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="description" id="description" value="<?=htmlspecialchars($result['description'], ENT_QUOTES, 'UTF-8');?>" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['edit']['kind'];?>:</label>
<div class="col-sm-10">
<select name="kind" id="kind" title="<?=$lang['edit']['select'];?>" required>
<option value="location" <?=($result['kind'] == "location") ? "selected" : null;?>>Location</option>
<option value="group" <?=($result['kind'] == "group") ? "selected" : null;?>>Group</option>
<option value="thing" <?=($result['kind'] == "thing") ? "selected" : null;?>>Thing</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="multiple_bookings_select"><?=$lang['add']['multiple_bookings'];?>:</label>
<div class="col-sm-10">
<select name="multiple_bookings_select" id="multiple_bookings_select" title="<?=$lang['add']['select'];?>" required>
<option value="0" <?=($result['multiple_bookings'] == 0) ? "selected" : null;?>><?=$lang['mailbox']['booking_0'];?></option>
<option value="-1" <?=($result['multiple_bookings'] == -1) ? "selected" : null;?>><?=$lang['mailbox']['booking_lt0'];?></option>
<option value="custom" <?=($result['multiple_bookings'] >= 1) ? "selected" : null;?>><?=$lang['mailbox']['booking_custom'];?></option>
</select>
<div style="display:none" id="multiple_bookings_custom_div">
<hr>
<input type="number" class="form-control" name="multiple_bookings_custom" id="multiple_bookings_custom" value="<?=($result['multiple_bookings'] >= 1) ? $result['multiple_bookings'] : null;?>">
</div>
<input type="hidden" name="multiple_bookings" id="multiple_bookings">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?=($result['active_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editresource" data-item="<?=htmlspecialchars($result['name']);?>" data-api-url='edit/resource' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
elseif (isset($_GET['bcc']) && !empty($_GET["bcc"])) {
$bcc = intval($_GET["bcc"]);
$result = bcc('details', $bcc);
if (!empty($result)) {
?>
- <h4>BCC map</h4>
+ <h4><?=$lang['mailbox']['bcc_map'];?></h4>
<br />
<form class="form-horizontal" data-id="editbcc" role="form" method="post">
<input type="hidden" value="0" name="active">
<div class="form-group">
- <label class="control-label col-sm-2" for="bcc_dest">BCC destination</label>
+ <label class="control-label col-sm-2" for="bcc_dest"><?=$lang['mailbox']['bcc_destination'];?></label>
<div class="col-sm-10">
- <textarea id="bcc_dest" class="form-control" autocapitalize="none" autocorrect="off" rows="10" id="bcc_dest" name="bcc_dest" required><?=$result['bcc_dest'];?></textarea>
- <small>BCC destination must be a single valid email address.</small>
+ <input value="<?=$result['bcc_dest'];?>" type="text" class="form-control" name="bcc_dest" id="bcc_dest">
+ <small><?=$lang['edit']['bcc_dest_format'];?></small>
</div>
</div>
<div class="form-group">
- <label class="control-label col-sm-2" for="type">Type:</label>
+ <label class="control-label col-sm-2" for="type"><?=$lang['mailbox']['bcc_map_type'];?></label>
<div class="col-sm-10">
<select id="addFilterType" name="type" id="type" required>
- <option value="sender" <?=($result['type'] == 'sender') ? 'selected' : null;?>>Sender map</option>
- <option value="rcpt" <?=($result['type'] == 'rcpt') ? 'selected' : null;?>>Recipient map</option>
+ <option value="sender" <?=($result['type'] == 'sender') ? 'selected' : null;?>><?=$lang['mailbox']['bcc_sender_map'];?></option>
+ <option value="rcpt" <?=($result['type'] == 'rcpt') ? 'selected' : null;?>><?=$lang['mailbox']['bcc_rcpt_map'];?></option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editbcc" data-item="<?=$bcc;?>" data-api-url='edit/bcc' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
elseif (isset($_GET['recipient_map']) && !empty($_GET["recipient_map"])) {
$map = intval($_GET["recipient_map"]);
$result = recipient_map('details', $map);
if (substr($result['recipient_map_old'], 0, 1) == '@') {
$result['recipient_map_old'] = substr($result['recipient_map_old'], 1);
}
if (!empty($result)) {
?>
<h4><?=$lang['mailbox']['recipient_map']?>: <?=$result['recipient_map_old'];?></h4>
<br />
<form class="form-horizontal" data-id="edit_recipient_map" role="form" method="post">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="recipient_map_new"><?=$lang['mailbox']['recipient_map_old'];?></label>
<div class="col-sm-10">
<input value="<?=$result['recipient_map_old'];?>" type="text" class="form-control" name="recipient_map_old" id="recipient_map_old">
<small><?=$lang['mailbox']['recipient_map_old_info'];?></small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="recipient_map_new"><?=$lang['mailbox']['recipient_map_new'];?></label>
<div class="col-sm-10">
<input value="<?=$result['recipient_map_new'];?>" type="text" class="form-control" name="recipient_map_new" id="recipient_map_new">
<small><?=$lang['mailbox']['recipient_map_new_info'];?></small>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="edit_recipient_map" data-item="<?=$map;?>" data-api-url='edit/recipient_map' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
}
if ($_SESSION['mailcow_cc_role'] == "admin" || $_SESSION['mailcow_cc_role'] == "domainadmin" || $_SESSION['mailcow_cc_role'] == "user") {
if (isset($_GET['syncjob']) &&
is_numeric($_GET['syncjob'])) {
$id = $_GET["syncjob"];
$result = mailbox('get', 'syncjob_details', $id);
if (!empty($result)) {
?>
<h4><?=$lang['edit']['syncjob'];?></h4>
<form class="form-horizontal" data-id="editsyncjob" role="form" method="post">
<input type="hidden" value="0" name="delete2duplicates">
<input type="hidden" value="0" name="delete1">
<input type="hidden" value="0" name="delete2">
<input type="hidden" value="0" name="automap">
<input type="hidden" value="0" name="skipcrossduplicates">
<input type="hidden" value="0" name="active">
<input type="hidden" value="0" name="subscribeall">
<div class="form-group">
<label class="control-label col-sm-2" for="host1"><?=$lang['edit']['hostname'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="host1" id="host1" value="<?=htmlspecialchars($result['host1'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="port1">Port</label>
<div class="col-sm-10">
<input type="number" class="form-control" name="port1" id="port1" min="1" max="65535" value="<?=htmlspecialchars($result['port1'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="user1"><?=$lang['edit']['username'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="user1" id="user1" value="<?=htmlspecialchars($result['user1'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password1"><?=$lang['edit']['password'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password1" id="password1" value="<?=htmlspecialchars($result['password1'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="enc1"><?=$lang['edit']['encryption'];?>:</label>
<div class="col-sm-10">
<select id="enc1" name="enc1">
<option <?=($result['enc1'] == "TLS") ? "selected" : null;?>>TLS</option>
<option <?=($result['enc1'] == "SSL") ? "selected" : null;?>>SSL</option>
<option <?=($result['enc1'] == "PLAIN") ? "selected" : null;?>>PLAIN</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="mins_interval"><?=$lang['edit']['mins_interval'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="mins_interval" min="1" max="3600" value="<?=htmlspecialchars($result['mins_interval'], ENT_QUOTES, 'UTF-8');?>" required>
<small class="help-block">1-3600</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="subfolder2" id="subfolder2" value="<?=htmlspecialchars($result['subfolder2'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="maxage" id="maxage" min="0" max="32000" value="<?=htmlspecialchars($result['maxage'], ENT_QUOTES, 'UTF-8');?>">
<small class="help-block">0-32000</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="<?=htmlspecialchars($result['maxbytespersecond'], ENT_QUOTES, 'UTF-8');?>">
<small class="help-block">0-125000000</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="timeout1"><?=$lang['add']['timeout1'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="timeout1" id="timeout1" min="1" max="32000" value="<?=htmlspecialchars($result['timeout1'], ENT_QUOTES, 'UTF-8');?>">
<small class="help-block">1-32000</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="timeout2"><?=$lang['add']['timeout2'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="timeout2" id="timeout2" min="1" max="32000" value="<?=htmlspecialchars($result['timeout2'], ENT_QUOTES, 'UTF-8');?>">
<small class="help-block">1-32000</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="exclude"><?=$lang['edit']['exclude'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="exclude" id="exclude" value="<?=htmlspecialchars($result['exclude'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="custom_params"><?=$lang['add']['custom_params'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="custom_params" id="custom_params" value="<?=htmlspecialchars($result['custom_params'], ENT_QUOTES, 'UTF-8');?>">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="delete2duplicates" <?=($result['delete2duplicates']=="1") ? "checked" : "";?>> <?=$lang['edit']['delete2duplicates'];?> (--delete2duplicates)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="delete1" <?=($result['delete1']=="1") ? "checked" : "";?>> <?=$lang['edit']['delete1'];?> (--delete1)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="delete2" <?=($result['delete2']=="1") ? "checked" : "";?>> <?=$lang['edit']['delete2'];?> (--delete2)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="automap" <?=($result['automap']=="1") ? "checked" : "";?>> <?=$lang['edit']['automap'];?> (--automap)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="skipcrossduplicates" <?=($result['skipcrossduplicates']=="1") ? "checked" : "";?>> <?=$lang['edit']['skipcrossduplicates'];?> (--skipcrossduplicates)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="subscribeall" <?=($result['subscribeall']=="1") ? "checked" : "";?>> <?=$lang['add']['subscribeall'];?> (--subscribeall)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?=($result['active_int']=="1") ? "checked" : "";?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editsyncjob" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/syncjob' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
elseif (isset($_GET['filter']) &&
is_numeric($_GET['filter'])) {
$id = $_GET["filter"];
$result = mailbox('get', 'filter_details', $id);
if (!empty($result)) {
?>
<h4>Filter</h4>
<form class="form-horizontal" data-id="editfilter" role="form" method="post">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="script_desc"><?=$lang['edit']['sieve_desc'];?>:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="script_desc" id="script_desc" value="<?=htmlspecialchars($result['script_desc'], ENT_QUOTES, 'UTF-8');?>" required maxlength="255">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="filter_type"><?=$lang['edit']['sieve_type'];?>:</label>
<div class="col-sm-10">
<select id="addFilterType" name="filter_type" id="filter_type" required>
<option value="prefilter" <?=($result['filter_type'] == 'prefilter') ? 'selected' : null;?>>Prefilter</option>
<option value="postfilter" <?=($result['filter_type'] == 'postfilter') ? 'selected' : null;?>>Postfilter</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="script_data">Script:</label>
<div class="col-sm-10">
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control" rows="20" id="script_data" name="script_data" required><?=$result['script_data'];?></textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?=($result['active_int']=="1") ? "checked" : "";?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="edit_selected" data-id="editfilter" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/filter' data-api-attr='{}' href="#"><?=$lang['edit']['validate_save'];?></button>
</div>
</div>
</form>
<?php
}
else {
?>
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
<?php
}
}
}
}
else {
?>
<div class="alert alert-danger" role="alert"><?=$lang['danger']['access_denied'];?></div>
<?php
}
?>
</div>
</div>
</div>
</div>
<a href="<?=$_SESSION['return_to'];?>">&#8592; <?=$lang['edit']['previous'];?></a>
</div> <!-- /container -->
<script type='text/javascript'>
<?php
$lang_user = json_encode($lang['user']);
echo "var lang = ". $lang_user . ";\n";
echo "var table_for_domain = '". ((isset($domain)) ? $domain : null) . "';\n";
echo "var csrf_token = '". $_SESSION['CSRF']['TOKEN'] . "';\n";
echo "var pagination_size = '". $PAGINATION_SIZE . "';\n";
?>
</script>
<script src="js/footable.min.js"></script>
<script src="js/edit.js"></script>
<?php
require_once("inc/footer.inc.php");
?>
diff --git a/data/web/inc/footer.inc.php b/data/web/inc/footer.inc.php
index d7b80723..cdef8e0b 100644
--- a/data/web/inc/footer.inc.php
+++ b/data/web/inc/footer.inc.php
@@ -1,245 +1,247 @@
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/footer.php';
logger();
?>
<div style="margin-bottom: 100px;"></div>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/bootstrap-switch.min.js"></script>
<script src="/js/bootstrap-slider.min.js"></script>
<script src="/js/bootstrap-select.min.js"></script>
<script src="/js/bootstrap-filestyle.min.js"></script>
<script src="/js/notifications.min.js"></script>
<script src="/js/formcache.min.js"></script>
<script src="/js/google.charts.loader.js"></script>
<script src="/js/numberedtextarea.min.js"></script>
<script src="/js/u2f-api.js"></script>
<script src="/js/api.js"></script>
<script>
var loading_text = '<?= $lang['footer']['loading']; ?>'
$(window).scroll(function() {
sessionStorage.scrollTop = $(this).scrollTop();
});
// Select language and reopen active URL without POST
function setLang(sel) {
$.post( "<?= $_SERVER['REQUEST_URI']; ?>", {lang: sel} );
window.location.href = window.location.pathname + window.location.search;
}
$(window).load(function() {
$(".overlay").hide();
});
$(document).ready(function() {
window.mailcow_alert_box = function(message, type) {
- msg = $('<span/>').html(message).text();
+ msg = $('<span/>').text(message).text();
if (type == 'danger') {
auto_hide = 0;
$('#' + localStorage.getItem("add_modal")).modal('show');
localStorage.removeItem("add_modal");
} else {
auto_hide = 5000;
}
$.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}});
}
<?php
$alertbox_log_parser = alertbox_log_parser($_SESSION);
if (is_array($alertbox_log_parser)) {
+ foreach($alertbox_log_parser as $log) {
?>
- mailcow_alert_box(<?=$alertbox_log_parser['msg'];?>, <?=$alertbox_log_parser['type'];?>);
+ mailcow_alert_box(<?=$log['msg'];?>, <?=$log['type'];?>);
<?php
+ }
unset($_SESSION['return']);
}
?>
$('[data-cached-form="true"]').formcache({key: $(this).data('id')});
// Confirm TFA modal
<?php if (isset($_SESSION['pending_tfa_method'])):?>
$('#ConfirmTFAModal').modal({
backdrop: 'static',
keyboard: false
});
$('#u2f_status_auth').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>');
$('#ConfirmTFAModal').on('shown.bs.modal', function(){
$(this).find('#token').focus();
// If U2F
if(document.getElementById("u2f_auth_data") !== null) {
$.ajax({
type: "GET",
cache: false,
dataType: 'script',
url: "/api/v1/get/u2f-authentication/<?= (isset($_SESSION['pending_mailcow_cc_username'])) ? rawurlencode($_SESSION['pending_mailcow_cc_username']) : null; ?>",
complete: function(data){
$('#u2f_status_auth').html('<?=$lang['tfa']['waiting_usb_auth'];?>');
data;
setTimeout(function() {
console.log("Ready to authenticate");
u2f.sign(appId, challenge, registeredKeys, function(data) {
var form = document.getElementById('u2f_auth_form');
var auth = document.getElementById('u2f_auth_data');
console.log("Authenticate callback", data);
auth.value = JSON.stringify(data);
form.submit();
});
}, 1000);
}
});
}
});
$('#ConfirmTFAModal').on('hidden.bs.modal', function(){
$.ajax({
type: "GET",
cache: false,
dataType: 'script',
url: '/inc/ajax/destroy_tfa_auth.php',
complete: function(data){
window.location = window.location.href.split("#")[0];
}
});
});
<?php endif; ?>
// Set TFA modals
$('#selectTFA').change(function () {
if ($(this).val() == "yubi_otp") {
$('#YubiOTPModal').modal('show');
$("option:selected").prop("selected", false);
}
if ($(this).val() == "totp") {
$('#TOTPModal').modal('show');
$("option:selected").prop("selected", false);
}
if ($(this).val() == "u2f") {
$('#U2FModal').modal('show');
$("option:selected").prop("selected", false);
$('#u2f_status_reg').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>');
$.ajax({
type: "GET",
cache: false,
dataType: 'script',
url: "/api/v1/get/u2f-registration/<?= (isset($_SESSION['mailcow_cc_username'])) ? rawurlencode($_SESSION['mailcow_cc_username']) : null; ?>",
complete: function(data){
data;
setTimeout(function() {
console.log("Ready to register");
$('#u2f_status_reg').html('<?=$lang['tfa']['waiting_usb_register'];?>');
u2f.register(appId, registerRequests, registeredKeys, function(deviceResponse) {
var form = document.getElementById('u2f_reg_form');
var reg = document.getElementById('u2f_register_data');
console.log("Register callback: ", data);
if (deviceResponse.errorCode && deviceResponse.errorCode != 0) {
var u2f_return_code = document.getElementById('u2f_return_code');
u2f_return_code.style.display = u2f_return_code.style.display === 'none' ? '' : null;
if (deviceResponse.errorCode == "4") { deviceResponse.errorCode = "4 - The presented device is not eligible for this request. For a registration request this may mean that the token is already registered, and for a sign request it may mean that the token does not know the presented key handle"; }
u2f_return_code.innerHTML = 'Error code: ' + deviceResponse.errorCode;
return;
}
reg.value = JSON.stringify(deviceResponse);
form.submit();
});
}, 1000);
}
});
}
if ($(this).val() == "none") {
$('#DisableTFAModal').modal('show');
$("option:selected").prop("selected", false);
}
});
$(function () {
$('[data-toggle="tooltip"]').tooltip()
});
// Remember last navigation pill
(function () {
'use strict';
if ($('a[data-toggle="tab"]').length) {
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
if ($(this).data('dont-remember') == 1) {
return true;
}
var id = $(this).parents('[role="tablist"]').attr('id');
var key = 'lastTag';
if (id) {
key += ':' + id;
}
localStorage.setItem(key, $(e.target).attr('href'));
});
$('[role="tablist"]').each(function (idx, elem) {
var id = $(elem).attr('id');
var key = 'lastTag';
if (id) {
key += ':' + id;
}
var lastTab = localStorage.getItem(key);
if (lastTab) {
$('[href="' + lastTab + '"]').tab('show');
}
});
}
})();
// Disable submit after submitting form (not API driven buttons)
$('form').submit(function() {
if ($('form button[type="submit"]').data('submitted') == '1') {
return false;
} else {
$(this).find('button[type="submit"]').first().text('<?= $lang['footer']['loading']; ?>');
$('form button[type="submit"]').attr('data-submitted', '1');
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };
$(document).on("keydown", disableF5);
}
});
// IE fix to hide scrollbars when table body is empty
$('tbody').filter(function (index) {
return $(this).children().length < 1;
}).remove();
// Init Bootstrap Selectpicker
$('select').selectpicker();
// Trigger container restart
$('#RestartContainer').on('show.bs.modal', function(e) {
var container = $(e.relatedTarget).data('container');
$('#containerName').text(container);
$('#triggerRestartContainer').click(function(){
$(this).prop("disabled",true);
$(this).html('<span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ');
$('#statusTriggerRestartContainer').html('<?= $lang['footer']['restarting_container']; ?>');
$.ajax({
method: 'get',
url: '/inc/ajax/container_ctrl.php',
timeout: <?= $DOCKER_TIMEOUT * 1000; ?>,
data: {
'service': container,
'action': 'restart'
}
})
.always( function (data, status) {
$('#statusTriggerRestartContainer').append(data);
var htmlResponse = $.parseHTML(data)
if ($(htmlResponse).find('span').hasClass('text-success')) {
$('#triggerRestartContainer').html('<span class="glyphicon glyphicon-ok"></span> ');
setTimeout(function(){
$('#RestartContainer').modal('toggle');
window.location = window.location.href.split("#")[0];
}, 1200);
} else {
$('#triggerRestartContainer').html('<span class="glyphicon glyphicon-remove"></span> ');
}
})
});
})
// CSRF
$('<input type="hidden" value="<?= $_SESSION['CSRF']['TOKEN']; ?>">').attr('id', 'csrf_token').attr('name', 'csrf_token').appendTo('form');
if (sessionStorage.scrollTop != "undefined") {
$(window).scrollTop(sessionStorage.scrollTop);
}
});
</script>
</body>
</html>
<?php
$stmt = null;
$pdo = null;
diff --git a/data/web/inc/functions.address_rewriting.inc.php b/data/web/inc/functions.address_rewriting.inc.php
index ce10d676..36fc4946 100644
--- a/data/web/inc/functions.address_rewriting.inc.php
+++ b/data/web/inc/functions.address_rewriting.inc.php
@@ -1,535 +1,486 @@
<?php
function bcc($_action, $_data = null, $attr = null) {
global $pdo;
global $lang;
if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
return false;
}
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'
);
return false;
}
$local_dest = strtolower(trim($_data['local_dest']));
$bcc_dest = $_data['bcc_dest'];
$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'
);
return false;
}
if (empty($bcc_dest)) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
'msg' => 'bcc_empty'
);
return false;
}
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'
);
return false;
}
$domain = idn_to_ascii($local_dest);
$local_dest_sane = '@' . idn_to_ascii($local_dest);
}
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'
);
return false;
}
$domain = mailbox('get', 'mailbox_details', $local_dest)['domain'];
if (empty($domain)) {
return false;
}
$local_dest_sane = $local_dest;
}
else {
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)
);
return false;
}
try {
$stmt = $pdo->prepare("INSERT INTO `bcc_maps` (`local_dest`, `bcc_dest`, `domain`, `active`, `type`) VALUES
(:local_dest, :bcc_dest, :domain, :active, :type)");
$stmt->execute(array(
':local_dest' => $local_dest_sane,
':bcc_dest' => $bcc_dest,
':domain' => $domain,
':active' => $active,
':type' => $type
));
}
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'
);
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'
);
return false;
}
$ids = (array)$_data['id'];
foreach ($ids as $id) {
$is_now = bcc('details', $id);
if (!empty($is_now)) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$bcc_dest = (!empty($_data['bcc_dest'])) ? $_data['bcc_dest'] : $is_now['bcc_dest'];
$local_dest = $is_now['local_dest'];
$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,
':active' => $active,
':type' => $type,
':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_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;
}
return $bccdata;
break;
case 'get':
$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'];
}
}
$all_items = null;
return $bccdata;
break;
case 'delete':
$ids = (array)$_data['id'];
foreach ($ids as $id) {
if (!is_numeric($id)) {
return false;
}
try {
$stmt = $pdo->prepare("SELECT `domain` FROM `bcc_maps` WHERE id = :id");
$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;
}
}
function recipient_map($_action, $_data = null, $attr = null) {
global $pdo;
global $lang;
if ($_SESSION['mailcow_cc_role'] != "admin") {
return false;
}
switch ($_action) {
case 'add':
$old_dest = strtolower(trim($_data['recipient_map_old']));
if (substr($old_dest, 0, 1) == '@') {
$old_dest = substr($old_dest, 1);
}
$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);
}
elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
$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;
}
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;
}
$rmaps = recipient_map('get');
foreach ($rmaps as $rmap) {
$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))
);
return false;
}
try {
$stmt = $pdo->prepare("INSERT INTO `recipient_maps` (`old_dest`, `new_dest`, `active`) VALUES
(:old_dest, :new_dest, :active)");
$stmt->execute(array(
':old_dest' => $old_dest_sane,
':new_dest' => $new_dest,
':active' => $active
));
}
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))
);
break;
case 'edit':
$ids = (array)$_data['id'];
foreach ($ids as $id) {
$is_now = recipient_map('details', $id);
if (!empty($is_now)) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$new_dest = (!empty($_data['recipient_map_new'])) ? $_data['recipient_map_new'] : $is_now['recipient_map_new'];
$old_dest = (!empty($_data['recipient_map_old'])) ? $_data['recipient_map_old'] : $is_now['recipient_map_old'];
if (substr($old_dest, 0, 1) == '@') {
$old_dest = substr($old_dest, 1);
}
}
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);
}
elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
$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) {
$old_dests_existing[] = recipient_map('details', $rmap)['recipient_map_old'];
}
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
`old_dest` = :old_dest,
`new_dest` = :new_dest,
`active` = :active
WHERE `id`= :id");
$stmt->execute(array(
':old_dest' => $old_dest_sane,
':new_dest' => $new_dest,
':active' => $active,
':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;
}
+ $_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'];
}
$all_items = null;
return $mapdata;
break;
case 'delete':
$ids = (array)$_data['id'];
foreach ($ids as $id) {
if (!is_numeric($id)) {
return false;
}
try {
$stmt = $pdo->prepare("DELETE FROM `recipient_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;
}
}
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'success',
'msg' => array('recipient_map_entry_deleted', htmlspecialchars($old_dest))
);
return true;
break;
}
}
diff --git a/data/web/inc/functions.autoconfiguration.inc.php b/data/web/inc/functions.autoconfiguration.inc.php
deleted file mode 100644
index bd3dd10b..00000000
--- a/data/web/inc/functions.autoconfiguration.inc.php
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php
-function autoconfiguration($_action, $_type, $_data = null) {
- global $pdo;
- global $lang;
- switch ($_action) {
- case 'edit':
- if (!isset($_SESSION['acl']['eas_autoconfig']) || $_SESSION['acl']['eas_autoconfig'] != "1" ) {
- $_SESSION['return'] = array(
- 'type' => '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 8fb928fa..a737bdbc 100644
--- a/data/web/inc/functions.customize.inc.php
+++ b/data/web/inc/functions.customize.inc.php
@@ -1,236 +1,236 @@
<?php
function customize($_action, $_item, $_data = null) {
global $redis;
global $lang;
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'
);
return false;
}
switch ($_item) {
case 'main_logo':
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'
);
return false;
}
$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'
);
return false;
}
$image->destroy();
}
catch (ImagickException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_item, $_data),
'msg' => 'img_invalid'
);
return false;
}
}
else {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_item, $_data),
'msg' => 'invalid_mime_type'
);
return false;
}
try {
$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'
);
break;
}
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'
);
return false;
}
switch ($_item) {
case 'app_links':
$apps = (array)$_data['app'];
$links = (array)$_data['href'];
$out = array();
if (count($apps) == count($links)) {
for ($i = 0; $i < count($apps); $i++) {
$out[] = array($apps[$i] => $links[$i]);
}
try {
$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)
);
return false;
}
}
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_item, $_data),
'msg' => 'app_links'
);
break;
case 'ui_texts':
$title_name = $_data['title_name'];
$main_name = $_data['main_name'];
$apps_name = $_data['apps_name'];
$help_text = $_data['help_text'];
try {
$redis->set('TITLE_NAME', htmlspecialchars($title_name));
$redis->set('MAIN_NAME', htmlspecialchars($main_name));
$redis->set('APPS_NAME', htmlspecialchars($apps_name));
$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'
);
break;
}
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'
);
return false;
}
switch ($_item) {
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'
);
return true;
}
}
catch (RedisException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_item, $_data),
'msg' => array('redis_error', $e)
);
return false;
}
break;
}
break;
case 'get':
switch ($_item) {
case 'app_links':
try {
$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)
);
return false;
}
return ($app_links) ? $app_links : false;
break;
case 'main_logo':
try {
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)
);
return false;
}
break;
case 'ui_texts':
try {
$data['title_name'] = ($title_name = $redis->get('TITLE_NAME')) ? $title_name : 'mailcow UI';
$data['main_name'] = ($main_name = $redis->get('MAIN_NAME')) ? $main_name : 'mailcow UI';
$data['apps_name'] = ($apps_name = $redis->get('APPS_NAME')) ? $apps_name : 'mailcow Apps';
$data['help_text'] = ($help_text = $redis->get('HELP_TEXT')) ? $help_text : false;
return $data;
}
catch (RedisException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_item, $_data),
'msg' => array('redis_error', $e)
);
return false;
}
break;
case 'main_logo_specs':
try {
$image = new Imagick();
$img_data = explode('base64,', customize('get', 'main_logo'));
if ($img_data[1]) {
$image->readImageBlob(base64_decode($img_data[1]));
}
return $image->identifyImage();
}
catch (ImagickException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_item, $_data),
'msg' => 'imagick_exception'
);
return false;
}
break;
}
break;
}
}
\ No newline at end of file
diff --git a/data/web/inc/functions.dkim.inc.php b/data/web/inc/functions.dkim.inc.php
index 8099d2f8..17bac738 100644
--- a/data/web/inc/functions.dkim.inc.php
+++ b/data/web/inc/functions.dkim.inc.php
@@ -1,272 +1,272 @@
<?php
function dkim($_action, $_data = null) {
global $redis;
global $lang;
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'
);
return false;
}
$key_length = intval($_data['key_size']);
$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'
);
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'
);
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'
);
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)
);
// Save public key and selector to redis
try {
$redis->hSet('DKIM_PUB_KEYS', $domain, $pubKey);
$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)
);
return false;
}
// 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(
+ $_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'
);
return true;
}
else {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data),
'msg' => 'dkim_domain_or_sel_invalid'
);
return false;
}
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'
);
return false;
}
$private_key_input = trim($_data['private_key_file']);
$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)
);
return false;
}
// Explode by nl
$pem_public_key_array = explode(PHP_EOL, trim(openssl_pkey_get_details($private_key)['key']));
// Remove first and last line/item
array_shift($pem_public_key_array);
array_pop($pem_public_key_array);
// Implode as single string
$pem_public_key = implode('', $pem_public_key_array);
$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'
);
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'
);
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'
);
return false;
}
try {
$redis->hSet('DKIM_PUB_KEYS', $domain, $pem_public_key);
$redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector);
$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)
);
return false;
}
unset($private_key_normalized);
unset($private_key);
unset($private_key_input);
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'
);
return true;
break;
case 'details':
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
$dkimdata = array();
if ($redis_dkim_key_data = $redis->hGet('DKIM_PUB_KEYS', $_data)) {
$dkimdata['pubkey'] = $redis_dkim_key_data;
if (strlen($dkimdata['pubkey']) < 391) {
$dkimdata['length'] = "1024";
}
elseif (strlen($dkimdata['pubkey']) < 736) {
$dkimdata['length'] = "2048";
}
elseif (strlen($dkimdata['pubkey']) < 1416) {
$dkimdata['length'] = "4096";
}
else {
$dkimdata['length'] = ">= 8192";
}
$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.');
}
}
return $dkimdata;
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'
);
return false;
}
$blinddkim = array();
foreach ($redis->hKeys('DKIM_PUB_KEYS') as $redis_dkim_domain) {
$blinddkim[] = $redis_dkim_domain;
}
return array_diff($blinddkim, array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')));
break;
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'
);
return false;
}
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);
$redis->hDel('DKIM_PUB_KEYS', $domain);
$redis->hDel('DKIM_PRIV_KEYS', $selector . '.' . $domain);
$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 cac2db78..dbd26375 100644
--- a/data/web/inc/functions.docker.inc.php
+++ b/data/web/inc/functions.docker.inc.php
@@ -1,185 +1,185 @@
<?php
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' ));
switch($action) {
case 'get_id':
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
$response = curl_exec($curl);
if ($response === false) {
$err = curl_error($curl);
curl_close($curl);
// logger(array('return' => 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(
// 'type' => 'success',
// 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
// )));
$containers = json_decode($response, true);
if (!empty($containers)) {
foreach ($containers as $container) {
if ($container['Config']['Labels']['com.docker.compose.service'] == $service_name
&& $container['Config']['Labels']['com.docker.compose.project'] == getenv('COMPOSE_PROJECT_NAME')) {
return trim($container['Id']);
}
}
}
}
return false;
case 'containers':
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
$response = curl_exec($curl);
if ($response === false) {
$err = curl_error($curl);
curl_close($curl);
// logger(array('return' => 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(
// 'type' => 'success',
// 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
// )));
$containers = json_decode($response, true);
if (!empty($containers)) {
foreach ($containers as $container) {
if ($container['Config']['Labels']['com.docker.compose.project'] == getenv('COMPOSE_PROJECT_NAME')) {
$out[$container['Config']['Labels']['com.docker.compose.service']]['State'] = $container['State'];
$out[$container['Config']['Labels']['com.docker.compose.service']]['Config'] = $container['Config'];
}
}
}
return (!empty($out)) ? $out : false;
}
return false;
break;
case 'info':
if (empty($service_name)) {
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
}
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');
}
else {
// logger(array('return' => array(
// 'type' => 'danger',
// 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
// 'msg' => 'invalid_container_id'
// )));
return false;
}
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
$response = curl_exec($curl);
if ($response === false) {
$err = curl_error($curl);
curl_close($curl);
// logger(array('return' => 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(
// 'type' => 'success',
// 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
// )));
$decoded_response = json_decode($response, true);
if (!empty($decoded_response)) {
if (empty($service_name)) {
foreach ($decoded_response as $container) {
if ($container['Config']['Labels']['com.docker.compose.project'] == 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'];
}
}
}
else {
if ($decoded_response['Config']['Labels']['com.docker.compose.project'] == 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'];
}
}
}
if (empty($response)) {
return true;
}
else {
return (!empty($out)) ? $out : false;
}
}
break;
case 'post':
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_POST, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
if (!empty($attr2)) {
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($attr2));
}
if (!empty($extra_headers) && is_array($extra_headers)) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $extra_headers);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
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;
}
else {
return $response;
}
}
}
}
break;
}
}
diff --git a/data/web/inc/functions.domain_admin.inc.php b/data/web/inc/functions.domain_admin.inc.php
index 3c631d08..86cec621 100644
--- a/data/web/inc/functions.domain_admin.inc.php
+++ b/data/web/inc/functions.domain_admin.inc.php
@@ -1,545 +1,524 @@
<?php
function domain_admin($_action, $_data = null) {
global $pdo;
global $lang;
$_data_log = $_data;
!isset($_data_log['password']) ?: $_data_log['password'] = '*';
!isset($_data_log['password2']) ?: $_data_log['password2'] = '*';
switch ($_action) {
case 'add':
$username = strtolower(trim($_data['username']));
$password = $_data['password'];
$password2 = $_data['password2'];
$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'
);
return false;
}
if (empty($domains)) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'domain_invalid'
);
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))
);
return false;
}
}
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;
}
if ($password != $password2) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'password_mismatch'
);
return false;
}
$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'
);
return false;
}
try {
$stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
VALUES (:username, :domain, :created, :active)");
$stmt->execute(array(
':username' => $username,
':domain' => $domain,
':created' => date('Y-m-d H:i:s'),
':active' => $active
));
}
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)
);
return false;
}
}
try {
$stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `active`)
VALUES (:username, :password_hashed, '0', :active)");
$stmt->execute(array(
':username' => $username,
':password_hashed' => $password_hashed,
':active' => $active
));
}
catch (PDOException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('mysql_error', $e)
);
return false;
}
}
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))
);
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'
);
return false;
}
// Administrator
if ($_SESSION['mailcow_cc_role'] == "admin") {
if (!is_array($_data['username'])) {
$usernames = array();
$usernames[] = $_data['username'];
}
else {
$usernames = $_data['username'];
}
foreach ($usernames as $username) {
$is_now = domain_admin('details', $username);
$domains = (isset($_data['domains'])) ? (array)$_data['domains'] : null;
if (!empty($is_now)) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$domains = (!empty($domains)) ? $domains : $is_now['selected_domains'];
$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 {
$stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
$stmt->execute(array(
':username' => $username,
));
}
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)) {
foreach ($domains as $domain) {
try {
$stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
VALUES (:username_new, :domain, :created, :active)");
$stmt->execute(array(
':username_new' => $username_new,
':domain' => $domain,
':created' => date('Y-m-d H:i:s'),
':active' => $active
));
}
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 {
$stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
$stmt->execute(array(
':password_hashed' => $password_hashed,
':username_new' => $username_new,
':username' => $username,
':active' => $active
));
if (isset($_data['disable_tfa'])) {
$stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
}
else {
$stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
$stmt->execute(array(':username_new' => $username_new, ':username' => $username));
}
}
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 {
try {
$stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active WHERE `username` = :username");
$stmt->execute(array(
':username_new' => $username_new,
':username' => $username,
':active' => $active
));
if (isset($_data['disable_tfa'])) {
$stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
}
else {
$stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
$stmt->execute(array(':username_new' => $username_new, ':username' => $username));
}
}
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
elseif ($_SESSION['mailcow_cc_role'] == "domainadmin") {
$username = $_SESSION['mailcow_cc_username'];
$password_old = $_data['user_old_pass'];
$password_new = $_data['user_new_pass'];
$password_new2 = $_data['user_new_pass2'];
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
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'
);
return false;
}
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'
);
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'
);
return false;
}
$password_hashed = hash_password($password_new);
try {
$stmt = $pdo->prepare("UPDATE `admin` SET `password` = :password_hashed WHERE `username` = :username");
$stmt->execute(array(
':password_hashed' => $password_hashed,
':username' => $username
));
}
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('domain_admin_modified', htmlspecialchars($username))
);
}
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'
);
return false;
}
$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");
$stmt->execute(array(
':username' => $username,
));
$stmt = $pdo->prepare("DELETE FROM `admin` WHERE `username` = :username");
$stmt->execute(array(
':username' => $username,
));
}
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':
$domainadmindata = array();
if ($_SESSION['mailcow_cc_role'] == "domainadmin" && $_data != $_SESSION['mailcow_cc_username']) {
return false;
}
elseif ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) {
return false;
}
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 668e41cb..166606ef 100644
--- a/data/web/inc/functions.fail2ban.inc.php
+++ b/data/web/inc/functions.fail2ban.inc.php
@@ -1,195 +1,205 @@
<?php
function valid_network($network) {
$cidr = explode('/', $network);
if (filter_var($cidr[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && (!isset($cidr[1]) || ($cidr[1] >= 0 && $cidr[1] <= 32))) {
return true;
}
elseif (filter_var($cidr[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && (!isset($cidr[1]) || ($cidr[1] >= 0 && $cidr[1] <= 128))) {
return true;
}
return false;
}
function fail2ban($_action, $_data = null) {
global $redis;
global $lang;
$_data_log = $_data;
switch ($_action) {
case 'get':
$f2b_options = array();
if ($_SESSION['mailcow_cc_role'] != "admin") {
return false;
}
try {
$f2b_options = json_decode($redis->Get('F2B_OPTIONS'), true);
$wl = $redis->hGetAll('F2B_WHITELIST');
if (is_array($wl)) {
foreach ($wl as $key => $value) {
$tmp_wl_data[] = $key;
}
if (isset($tmp_wl_data)) {
sort($tmp_wl_data);
$f2b_options['whitelist'] = implode(PHP_EOL, $tmp_wl_data);
}
else {
$f2b_options['whitelist'] = "";
}
}
else {
$f2b_options['whitelist'] = "";
}
$bl = $redis->hGetAll('F2B_BLACKLIST');
if (is_array($bl)) {
foreach ($bl as $key => $value) {
$tmp_bl_data[] = $key;
}
if (isset($tmp_bl_data)) {
sort($tmp_bl_data);
$f2b_options['blacklist'] = implode(PHP_EOL, $tmp_bl_data);
}
else {
$f2b_options['blacklist'] = "";
}
}
else {
$f2b_options['blacklist'] = "";
}
$pb = $redis->hGetAll('F2B_PERM_BANS');
if (is_array($pb)) {
foreach ($pb as $key => $value) {
$f2b_options['perm_bans'][] = $key;
}
}
else {
$f2b_options['perm_bans'] = "";
}
$active_bans = $redis->hGetAll('F2B_ACTIVE_BANS');
$queue_unban = $redis->hGetAll('F2B_QUEUE_UNBAN');
if (is_array($active_bans)) {
foreach ($active_bans as $network => $banned_until) {
$queued_for_unban = (isset($queue_unban[$network]) && $queue_unban[$network] == 1) ? 1 : 0;
$difference = $banned_until - time();
$f2b_options['active_bans'][] = array(
'queued_for_unban' => $queued_for_unban,
'network' => $network,
'banned_until' => sprintf('%02dh %02dm %02ds', ($difference/3600), ($difference/60%60), $difference%60)
);
}
}
else {
$f2b_options['active_bans'] = "";
}
}
catch (RedisException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('redis_error', $e)
);
return false;
}
return $f2b_options;
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'
);
return false;
}
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');
if (!empty($is_now)) {
$ban_time = intval((isset($_data['ban_time'])) ? $_data['ban_time'] : $is_now['ban_time']);
$max_attempts = intval((isset($_data['max_attempts'])) ? $_data['max_attempts'] : $is_now['active_int']);
$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']);
$wl = (isset($_data['whitelist'])) ? $_data['whitelist'] : $is_now['whitelist'];
$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'
);
return false;
}
$f2b_options = array();
$f2b_options['ban_time'] = ($ban_time < 60) ? 60 : $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;
$f2b_options['netban_ipv6'] = ($netban_ipv6 > 128) ? 128 : $netban_ipv6;
$f2b_options['max_attempts'] = ($max_attempts < 1) ? 1 : $max_attempts;
$f2b_options['retry_window'] = ($retry_window < 1) ? 1 : $retry_window;
try {
$redis->Set('F2B_OPTIONS', json_encode($f2b_options));
$redis->Del('F2B_WHITELIST');
$redis->Del('F2B_BLACKLIST');
if(!empty($wl)) {
$wl_array = array_map('trim', preg_split( "/( |,|;|\n)/", $wl));
if (is_array($wl_array)) {
foreach ($wl_array as $wl_item) {
if (valid_network($wl_item)) {
$redis->hSet('F2B_WHITELIST', $wl_item, 1);
}
}
}
}
if(!empty($bl)) {
$bl_array = array_map('trim', preg_split( "/( |,|;|\n)/", $bl));
if (is_array($bl_array)) {
foreach ($bl_array as $bl_item) {
if (valid_network($bl_item)) {
$redis->hSet('F2B_BLACKLIST', $bl_item, 1);
}
}
}
}
}
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'
);
break;
}
}
diff --git a/data/web/inc/functions.fwdhost.inc.php b/data/web/inc/functions.fwdhost.inc.php
index f16834ea..5c511f4f 100644
--- a/data/web/inc/functions.fwdhost.inc.php
+++ b/data/web/inc/functions.fwdhost.inc.php
@@ -1,183 +1,183 @@
<?php
function fwdhost($_action, $_data = null) {
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/spf.inc.php';
global $redis;
global $lang;
$_data_log = $_data;
switch ($_action) {
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'
);
return false;
}
$source = $_data['hostname'];
$host = trim($_data['hostname']);
$filter_spam = (isset($_data['filter_spam']) && $_data['filter_spam'] == 1) ? 1 : 0;
if (preg_match('/^[0-9a-fA-F:\/]+$/', $host)) { // IPv6 address
$hosts = array($host);
}
elseif (preg_match('/^[0-9\.\/]+$/', $host)) { // IPv4 address
$hosts = array($host);
}
else {
$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))
);
return false;
}
foreach ($hosts as $host) {
try {
$redis->hSet('WHITELISTED_FWD_HOST', $host, $source);
if ($filter_spam == 0) {
$redis->hSet('KEEP_SPAM', $host, 1);
}
elseif ($redis->hGet('KEEP_SPAM', $host)) {
$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;
}
}
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('forwarding_host_added', htmlspecialchars(implode(', ', $hosts)))
);
break;
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'
);
return false;
}
$fwdhosts = (array)$_data['fwdhost'];
foreach ($fwdhosts as $fwdhost) {
$is_now = fwdhost('details', $fwdhost);
if (!empty($is_now)) {
$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) {
$redis->hSet('KEEP_SPAM', $fwdhost, 1);
}
else {
$redis->hDel('KEEP_SPAM', $fwdhost);
}
}
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'];
foreach ($hosts as $host) {
try {
$redis->hDel('WHITELISTED_FWD_HOST', $host);
$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") {
return false;
}
$fwdhostsdata = array();
try {
$fwd_hosts = $redis->hGetAll('WHITELISTED_FWD_HOST');
if (!empty($fwd_hosts)) {
foreach ($fwd_hosts as $fwd_host => $source) {
$keep_spam = ($redis->hGet('KEEP_SPAM', $fwd_host)) ? "yes" : "no";
$fwdhostsdata[] = array(
'host' => $fwd_host,
'source' => $source,
'keep_spam' => $keep_spam
);
}
}
}
catch (RedisException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('redis_error', $e)
);
return false;
}
return $fwdhostsdata;
break;
case 'details':
$fwdhostdetails = array();
if (!isset($_data) || empty($_data)) {
return false;
}
try {
if ($source = $redis->hGet('WHITELISTED_FWD_HOST', $_data)) {
$fwdhostdetails['host'] = $_data;
$fwdhostdetails['source'] = $source;
$fwdhostdetails['keep_spam'] = ($redis->hGet('KEEP_SPAM', $_data)) ? "yes" : "no";
}
}
catch (RedisException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('redis_error', $e)
);
return false;
}
return $fwdhostdetails;
break;
}
}
\ No newline at end of file
diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index d99661cb..a44cf7eb 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -1,1487 +1,1456 @@
<?php
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 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;
if (!filter_var($username, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
return false;
}
if (empty($domain) || !is_valid_domain_name($domain)) {
return false;
}
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;
}
return false;
}
function hasMailboxObjectAccess($username, $role, $object) {
global $pdo;
if (!filter_var(html_entity_decode(rawurldecode($username)), FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
return false;
}
if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') {
return false;
}
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) {
// Need to remove BEGIN/END PUBLIC KEY
$lines = explode("\n", trim($pem_key));
unset($lines[count($lines)-1]);
unset($lines[0]);
return base64_decode(implode('', $lines));
}
function generate_tlsa_digest($hostname, $port, $starttls = null) {
if (!is_valid_domain_name($hostname)) {
return "Not a valid hostname";
}
if (empty($starttls)) {
$context = stream_context_create(array("ssl" => array("capture_peer_cert" => true, 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)));
$stream = stream_socket_client('ssl://' . $hostname . ':' . $port, $error_nr, $error_msg, 5, STREAM_CLIENT_CONNECT, $context);
if (!$stream) {
$error_msg = isset($error_msg) ? $error_msg : '-';
return $error_nr . ': ' . $error_msg;
}
}
else {
$stream = stream_socket_client('tcp://' . $hostname . ':' . $port, $error_nr, $error_msg, 5);
if (!$stream) {
return $error_nr . ': ' . $error_msg;
}
$banner = fread($stream, 512 );
if (preg_match("/^220/i", $banner)) { // SMTP
fwrite($stream,"HELO tlsa.generator.local\r\n");
fread($stream, 512);
fwrite($stream,"STARTTLS\r\n");
fread($stream, 512);
}
elseif (preg_match("/imap.+starttls/i", $banner)) { // IMAP
fwrite($stream,"A1 STARTTLS\r\n");
fread($stream, 512);
}
elseif (preg_match("/^\+OK/", $banner)) { // POP3
fwrite($stream,"STLS\r\n");
fread($stream, 512);
}
elseif (preg_match("/^OK/m", $banner)) { // Sieve
fwrite($stream,"STARTTLS\r\n");
fread($stream, 512);
}
else {
return 'Unknown banner: "' . htmlspecialchars(trim($banner)) . '"';
}
// Upgrade connection
stream_set_blocking($stream, true);
stream_context_set_option($stream, 'ssl', 'capture_peer_cert', true);
stream_context_set_option($stream, 'ssl', 'verify_peer', false);
stream_context_set_option($stream, 'ssl', 'verify_peer_name', false);
stream_context_set_option($stream, 'ssl', 'allow_self_signed', true);
stream_socket_enable_crypto($stream, true, STREAM_CRYPTO_METHOD_ANY_CLIENT);
stream_set_blocking($stream, false);
}
$params = stream_context_get_params($stream);
if (!empty($params['options']['ssl']['peer_certificate'])) {
$key_resource = openssl_pkey_get_public($params['options']['ssl']['peer_certificate']);
// We cannot get ['rsa']['n'], the binary data would contain BEGIN/END PUBLIC KEY
$key_data = openssl_pkey_get_details($key_resource)['key'];
return '3 1 1 ' . openssl_digest(pem_to_der($key_data), 'sha256');
}
else {
return 'Error: Cannot read peer certificate';
}
}
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;
}
function verify_hash($hash, $password) {
if (preg_match('/^{SSHA256}/i', $hash)) {
// Remove tag if any
$hash = preg_replace('/^{SSHA256}/i', '', $hash);
// Decode hash
$dhash = base64_decode($hash);
// Get first 32 bytes of binary which equals a SHA256 hash
$ohash = substr($dhash, 0, 32);
// Remove SHA256 hash from decoded hash to get original salt string
$osalt = str_replace($ohash, '', $dhash);
// Check single salted SHA256 hash against extracted hash
if (hash_equals(hash('sha256', $password . $osalt, true), $ohash)) {
return true;
}
}
elseif (preg_match('/^{SHA512-CRYPT}/i', $hash)) {
// Remove tag if any
$hash = preg_replace('/^{SHA512-CRYPT}/i', '', $hash);
// Decode hash
preg_match('/\\$6\\$(.*)\\$(.*)/i', $hash, $hash_array);
$osalt = $hash_array[1];
$ohash = $hash_array[2];
if (hash_equals(crypt($password, '$6$' . $osalt . '$'), $hash)) {
return true;
}
}
elseif (preg_match('/^{SSHA512}/i', $hash)) {
$hash = preg_replace('/^{SSHA512}/i', '', $hash);
// Decode hash
$dhash = base64_decode($hash);
// Get first 64 bytes of binary which equals a SHA512 hash
$ohash = substr($dhash, 0, 64);
// Remove SHA512 hash from decoded hash to get original salt string
$osalt = str_replace($ohash, '', $dhash);
// Check single salted SHA512 hash against extracted hash
if (hash_equals(hash('sha512', $password . $osalt, true), $ohash)) {
return true;
}
}
return false;
}
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'
);
return false;
}
$user = strtolower(trim($user));
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
WHERE `superadmin` = '1'
AND `username` = :user");
$stmt->execute(array(':user' => $user));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
if (verify_hash($row['password'], $pass)) {
if (get_tfa($user)['name'] != "none") {
$_SESSION['pending_mailcow_cc_username'] = $user;
$_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'
);
return "pending";
}
else {
unset($_SESSION['ldelay']);
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $user, '*'),
'msg' => array('logged_in_as', $user)
);
return "admin";
}
}
}
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
WHERE `superadmin` = '0'
AND `active`='1'
AND `username` = :user");
$stmt->execute(array(':user' => $user));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
if (verify_hash($row['password'], $pass) !== false) {
if (get_tfa($user)['name'] != "none") {
$_SESSION['pending_mailcow_cc_username'] = $user;
$_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'
);
return "pending";
}
else {
unset($_SESSION['ldelay']);
// 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)
);
return "domainadmin";
}
}
}
$stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
WHERE `kind` NOT REGEXP 'location|thing|group'
AND `active`='1'
AND `username` = :user");
$stmt->execute(array(':user' => $user));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
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)
);
return "user";
}
}
if (!isset($_SESSION['ldelay'])) {
$_SESSION['ldelay'] = "0";
$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']);
}
elseif (!isset($_SESSION['mailcow_cc_username'])) {
$_SESSION['ldelay'] = $_SESSION['ldelay']+0.5;
$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'
);
sleep($_SESSION['ldelay']);
return false;
}
function set_acl() {
global $pdo;
if (!isset($_SESSION['mailcow_cc_username'])) {
return false;
}
if ($_SESSION['mailcow_cc_role'] == 'admin' || $_SESSION['mailcow_cc_role'] == 'domainadmin') {
$stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';");
$acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($acl_all)) {
$acl['acl'][$row['Field']] = 1;
}
}
else {
$username = strtolower(trim($_SESSION['mailcow_cc_username']));
$stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
$acl['acl'] = $stmt->fetch(PDO::FETCH_ASSOC);
unset($acl['acl']['username']);
}
if (!empty($acl)) {
$_SESSION = array_merge($_SESSION, $acl);
}
else {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'info',
'log' => array(__FUNCTION__),
'msg' => 'set_acl_failed'
);
return false;
}
}
function get_acl($username) {
global $pdo;
if ($_SESSION['mailcow_cc_role'] != "admin") {
return false;
}
$username = strtolower(trim($username));
$stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
$acl = $stmt->fetch(PDO::FETCH_ASSOC);
unset($acl['username']);
if (!empty($acl)) {
return $acl;
}
else {
return false;
}
}
function formatBytes($size, $precision = 2) {
if(!is_numeric($size)) {
return "0";
}
$base = log($size, 1024);
$suffixes = array(' Byte', ' KiB', ' MiB', ' GiB', ' TiB');
if ($size == "0") {
return "0";
}
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
}
function edit_admin_account($_data) {
global $lang;
global $pdo;
$_data_log = $_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'
);
return false;
}
$username_now = $_SESSION['mailcow_cc_username'];
$username = $_data['admin_user'];
$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'
);
return false;
}
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'
);
return false;
}
if ($password != $password2) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'password_mismatch'
);
return false;
}
$password_hashed = hash_password($password);
try {
$stmt = $pdo->prepare("UPDATE `admin` SET
`password` = :password_hashed,
`username` = :username1
WHERE `username` = :username2");
$stmt->execute(array(
':password_hashed' => $password_hashed,
':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)
);
return false;
}
}
else {
try {
$stmt = $pdo->prepare("UPDATE `admin` SET
`username` = :username1
WHERE `username` = :username2");
$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)
);
return false;
}
}
try {
$stmt = $pdo->prepare("UPDATE `domain_admins` SET `domain` = 'ALL', `username` = :username1 WHERE `username` = :username2");
$stmt->execute(array(':username1' => $username, ':username2' => $username_now));
$stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username1 WHERE `username` = :username2");
$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)
);
return false;
}
$_SESSION['mailcow_cc_username'] = $username;
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'admin_modified'
);
}
function update_sogo_static_view() {
global $pdo;
global $lang;
$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 SELECT * from sogo_view");
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
}
}
function edit_user_account($_data) {
global $lang;
global $pdo;
$_data_log = $_data;
!isset($_data_log['user_new_pass']) ?: $_data_log['user_new_pass'] = '*';
!isset($_data_log['user_new_pass2']) ?: $_data_log['user_new_pass2'] = '*';
!isset($_data_log['user_old_pass']) ?: $_data_log['user_old_pass'] = '*';
$username = $_SESSION['mailcow_cc_username'];
$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'
);
return false;
}
if (isset($_data['user_new_pass']) && isset($_data['user_new_pass2'])) {
$password_new = $_data['user_new_pass'];
$password_new2 = $_data['user_new_pass2'];
}
$stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
WHERE `kind` NOT REGEXP 'location|thing|group'
AND `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__, $_data_log),
'msg' => 'access_denied'
);
return false;
}
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'
);
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'
);
return false;
}
$password_hashed = hash_password($password_new);
try {
$stmt = $pdo->prepare("UPDATE `mailbox` SET `password` = :password_hashed, `attributes` = JSON_SET(`attributes`, '$.force_pw_update', '0') WHERE `username` = :username");
$stmt->execute(array(
':password_hashed' => $password_hashed,
':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;
}
}
}
update_sogo_static_view();
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_data_log),
'msg' => array('mailbox_modified', htmlspecialchars($username))
);
}
function user_get_alias_details($username) {
global $lang;
global $pdo;
if ($_SESSION['mailcow_cc_role'] == "user") {
$username = $_SESSION['mailcow_cc_username'];
}
if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
return false;
}
- try {
- $data['address'] = $username;
- $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '&#10008;') 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']) ? '&#10008;' : $data['direct_aliases'];
- $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '&#10008;') 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 ', ')), '&#10008;') 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 ', '), '&#10008;') 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 ', '), '&#10008;') 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']) ? '&#10008;' : $data['direct_aliases'];
+ $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '&#10008;') 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 ', ')), '&#10008;') 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 ', '), '&#10008;') 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)) {
return false;
}
$domain_name = idn_to_ascii($domain_name);
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));
}
function set_tfa($_data) {
global $lang;
global $pdo;
global $yubi;
global $u2f;
global $tfa;
$_data_log = $_data;
!isset($_data_log['confirm_password']) ?: $_data_log['confirm_password'] = '*';
$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'
);
return false;
}
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
WHERE `username` = :user");
$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'
);
return false;
}
switch ($_data["tfa_method"]) {
case "yubi_otp":
$key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"];
$yubico_id = $_data['yubico_id'];
$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'
);
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'
);
return false;
}
$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())
);
return false;
}
try {
// We could also do a modhex translation here
$yubico_modhex_id = substr($_data["otp_token"], 0, 12);
$stmt = $pdo->prepare("DELETE FROM `tfa`
WHERE `username` = :username
AND (`authmech` != 'yubi_otp')
OR (`authmech` = 'yubi_otp' AND `secret` LIKE :modhex)");
$stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id));
$stmt = $pdo->prepare("INSERT INTO `tfa` (`key_id`, `username`, `authmech`, `active`, `secret`) VALUES
(:key_id, :username, 'yubi_otp', '1', :secret)");
$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))
);
break;
case "u2f":
$key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"];
try {
$reg = $u2f->doRegister(json_decode($_SESSION['regReq']), json_decode($_data['token']));
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username AND `authmech` != 'u2f'");
$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)
);
$_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())
);
$_SESSION['regReq'] = null;
return false;
}
break;
case "totp":
$key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"];
if ($tfa->verifyCode($_POST['totp_secret'], $_POST['totp_confirm_token']) === true) {
try {
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
$stmt = $pdo->prepare("INSERT INTO `tfa` (`username`, `key_id`, `authmech`, `secret`, `active`) VALUES (?, ?, 'totp', ?, '1')");
$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'
);
}
break;
case "none":
try {
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
$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))
);
break;
}
}
function unset_tfa_key($_data) {
// Can only unset own keys
// Needs at least one key left
global $pdo;
global $lang;
$_data_log = $_data;
$id = intval($_data['unset_tfa_key']);
$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'
);
return false;
}
try {
if (!is_numeric($id)) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'access_denied'
);
return false;
}
$stmt = $pdo->prepare("SELECT COUNT(*) AS `keys` FROM `tfa`
WHERE `username` = :username AND `active` = '1'");
$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'
);
return false;
}
$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)
);
return false;
}
}
function get_tfa($username = null) {
global $pdo;
if (isset($_SESSION['mailcow_cc_username'])) {
$username = $_SESSION['mailcow_cc_username'];
}
elseif (empty($username)) {
return false;
}
$stmt = $pdo->prepare("SELECT * FROM `tfa`
WHERE `username` = :username AND `active` = '1'");
$stmt->execute(array(':username' => $username));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
switch ($row["authmech"]) {
case "yubi_otp":
$data['name'] = "yubi_otp";
$data['pretty'] = "Yubico OTP";
$stmt = $pdo->prepare("SELECT `id`, `key_id`, RIGHT(`secret`, 12) AS 'modhex' FROM `tfa` WHERE `authmech` = 'yubi_otp' AND `username` = :username");
$stmt->execute(array(
':username' => $username,
));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while($row = array_shift($rows)) {
$data['additional'][] = $row;
}
return $data;
break;
case "u2f":
$data['name'] = "u2f";
$data['pretty'] = "Fido U2F";
$stmt = $pdo->prepare("SELECT `id`, `key_id` FROM `tfa` WHERE `authmech` = 'u2f' AND `username` = :username");
$stmt->execute(array(
':username' => $username,
));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while($row = array_shift($rows)) {
$data['additional'][] = $row;
}
return $data;
break;
case "hotp":
$data['name'] = "hotp";
$data['pretty'] = "HMAC-based OTP";
return $data;
break;
case "totp":
$data['name'] = "totp";
$data['pretty'] = "Time-based OTP";
$stmt = $pdo->prepare("SELECT `id`, `key_id`, `secret` FROM `tfa` WHERE `authmech` = 'totp' AND `username` = :username");
$stmt->execute(array(
':username' => $username,
));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while($row = array_shift($rows)) {
$data['additional'][] = $row;
}
return $data;
break;
default:
$data['name'] = 'none';
$data['pretty'] = "-";
return $data;
break;
}
}
function verify_tfa_login($username, $token) {
global $pdo;
global $lang;
global $yubi;
global $u2f;
global $tfa;
$stmt = $pdo->prepare("SELECT `authmech` FROM `tfa`
WHERE `username` = :username AND `active` = '1'");
$stmt->execute(array(':username' => $username));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
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')
);
return false;
}
$yubico_modhex_id = substr($token, 0, 12);
$stmt = $pdo->prepare("SELECT `id`, `secret` FROM `tfa`
WHERE `username` = :username
AND `authmech` = 'yubi_otp'
AND `active`='1'
AND `secret` LIKE :modhex");
$stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$yubico_auth = explode(':', $row['secret']);
$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())
);
return false;
}
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')
);
return false;
break;
case "u2f":
try {
$reg = $u2f->doAuthenticate(json_decode($_SESSION['authReq']), get_u2f_registrations($username), json_decode($token));
$stmt = $pdo->prepare("UPDATE `tfa` SET `counter` = ? WHERE `id` = ?");
$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'
);
return true;
}
catch (Exception $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $username, '*'),
'msg' => array('u2f_verification_failed', $e->getMessage())
);
$_SESSION['regReq'] = null;
return false;
}
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $username, '*'),
'msg' => array('u2f_verification_failed', 'unknown')
);
return false;
break;
case "hotp":
return false;
break;
case "totp":
try {
$stmt = $pdo->prepare("SELECT `id`, `secret` FROM `tfa`
WHERE `username` = :username
AND `authmech` = 'totp'
AND `active`='1'");
$stmt->execute(array(':username' => $username));
$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'
);
return false;
}
catch (PDOException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $username, '*'),
'msg' => array('mysql_error', $e)
);
return false;
}
break;
default:
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $username, '*'),
'msg' => 'unknown_tfa_method'
);
return false;
break;
}
return false;
}
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'
);
return false;
}
switch ($action) {
case "edit":
$regen_key = $data['admin_api_regen_key'];
$active = (isset($data['active'])) ? 1 : 0;
$allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $data['allow_from']));
foreach ($allow_from as $key => $val) {
if (!filter_var($val, FILTER_VALIDATE_IP)) {
unset($allow_from[$key]);
continue;
}
}
$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'
);
return false;
}
$api_key = implode('-', array(
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3)))
));
$stmt = $pdo->prepare("INSERT INTO `api` (`username`, `api_key`, `active`, `allow_from`)
SELECT `username`, :api_key, :active, :allow_from FROM `admin` WHERE `superadmin`='1' AND `active`='1'
ON DUPLICATE KEY UPDATE `active` = :active_u, `allow_from` = :allow_from_u ;");
$stmt->execute(array(
':api_key' => $api_key,
':active' => $active,
':active_u' => $active,
':allow_from' => $allow_from,
':allow_from_u' => $allow_from
));
break;
case "regen_key":
$api_key = implode('-', array(
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3)))
));
$stmt = $pdo->prepare("UPDATE `api` SET `api_key` = :api_key WHERE `username` IN
(SELECT `username` FROM `admin` WHERE `superadmin`='1' AND `active`='1')");
$stmt->execute(array(
':api_key' => $api_key
));
break;
}
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $data),
'msg' => 'admin_modified'
);
}
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'
);
return false;
}
switch ($action) {
case "edit":
$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'
);
return false;
}
if ($rspamd_ui_pass != $rspamd_ui_pass2) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, '*', '*'),
'msg' => 'password_mismatch'
);
return false;
}
if (strlen($rspamd_ui_pass) < 6) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, '*', '*'),
'msg' => 'rspamd_ui_pw_length'
);
return false;
}
$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'
);
return true;
}
else {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => $docker_return_array['type'],
'log' => array(__FUNCTION__, '*', '*'),
'msg' => $docker_return_array['msg']
);
return false;
}
}
else {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, '*', '*'),
'msg' => 'unknown'
);
return false;
}
break;
}
}
function get_admin_details() {
// No parameter to be given, only one admin should exist
global $pdo;
global $lang;
$data = array();
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) {
global $pdo;
$sel = $pdo->prepare("SELECT * FROM `tfa` WHERE `authmech` = 'u2f' AND `username` = ? AND `active` = '1'");
$sel->execute(array($username));
return $sel->fetchAll(PDO::FETCH_OBJ);
}
function get_logs($container, $lines = false) {
if ($lines === false) {
$lines = $GLOBALS['LOG_LINES'] - 1;
}
elseif(is_numeric($lines) && $lines >= 1) {
$lines = abs(intval($lines) - 1);
}
else {
list ($from, $to) = explode('-', $lines);
$from = intval($from);
$to = intval($to);
if ($from < 1 || $to < $from) { return false; }
}
global $lang;
global $redis;
global $pdo;
if ($_SESSION['mailcow_cc_role'] != "admin") {
return 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;
}
}
// Redis
if ($container == "dovecot-mailcow") {
if (isset($from) && isset($to)) {
$data = $redis->lRange('DOVECOT_MAILLOG', $from - 1, $to - 1);
}
else {
$data = $redis->lRange('DOVECOT_MAILLOG', 0, $lines);
}
if ($data) {
foreach ($data as $json_line) {
$data_array[] = json_decode($json_line, true);
}
return $data_array;
}
}
if ($container == "postfix-mailcow") {
if (isset($from) && isset($to)) {
$data = $redis->lRange('POSTFIX_MAILLOG', $from - 1, $to - 1);
}
else {
$data = $redis->lRange('POSTFIX_MAILLOG', 0, $lines);
}
if ($data) {
foreach ($data as $json_line) {
$data_array[] = json_decode($json_line, true);
}
return $data_array;
}
}
if ($container == "sogo-mailcow") {
if (isset($from) && isset($to)) {
$data = $redis->lRange('SOGO_LOG', $from - 1, $to - 1);
}
else {
$data = $redis->lRange('SOGO_LOG', 0, $lines);
}
if ($data) {
foreach ($data as $json_line) {
$data_array[] = json_decode($json_line, true);
}
return $data_array;
}
}
if ($container == "watchdog-mailcow") {
if (isset($from) && isset($to)) {
$data = $redis->lRange('WATCHDOG_LOG', $from - 1, $to - 1);
}
else {
$data = $redis->lRange('WATCHDOG_LOG', 0, $lines);
}
if ($data) {
foreach ($data as $json_line) {
$data_array[] = json_decode($json_line, true);
}
return $data_array;
}
}
if ($container == "acme-mailcow") {
if (isset($from) && isset($to)) {
$data = $redis->lRange('ACME_LOG', $from - 1, $to - 1);
}
else {
$data = $redis->lRange('ACME_LOG', 0, $lines);
}
if ($data) {
foreach ($data as $json_line) {
$data_array[] = json_decode($json_line, true);
}
return $data_array;
}
}
if ($container == "api-mailcow") {
if (isset($from) && isset($to)) {
$data = $redis->lRange('API_LOG', $from - 1, $to - 1);
}
else {
$data = $redis->lRange('API_LOG', 0, $lines);
}
if ($data) {
foreach ($data as $json_line) {
$data_array[] = json_decode($json_line, true);
}
return $data_array;
}
}
if ($container == "netfilter-mailcow") {
if (isset($from) && isset($to)) {
$data = $redis->lRange('NETFILTER_LOG', $from - 1, $to - 1);
}
else {
$data = $redis->lRange('NETFILTER_LOG', 0, $lines);
}
if ($data) {
foreach ($data as $json_line) {
$data_array[] = json_decode($json_line, true);
}
return $data_array;
}
}
if ($container == "autodiscover-mailcow") {
if (isset($from) && isset($to)) {
$data = $redis->lRange('AUTODISCOVER_LOG', $from - 1, $to - 1);
}
else {
$data = $redis->lRange('AUTODISCOVER_LOG', 0, $lines);
}
if ($data) {
foreach ($data as $json_line) {
$data_array[] = json_decode($json_line, true);
}
return $data_array;
}
}
if ($container == "rspamd-history") {
$curl = curl_init();
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/rspamd-sock/rspamd.sock');
if (!is_numeric($lines)) {
list ($from, $to) = explode('-', $lines);
curl_setopt($curl, CURLOPT_URL,"http://rspamd/history?from=" . intval($from) . "&to=" . intval($to));
}
else {
curl_setopt($curl, CURLOPT_URL,"http://rspamd/history?to=" . intval($lines));
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$history = curl_exec($curl);
if (!curl_errno($curl)) {
$data_array = json_decode($history, true);
curl_close($curl);
return $data_array['rows'];
}
curl_close($curl);
return false;
}
return false;
}
?>
diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php
index d0d1cd1a..82481cc3 100644
--- a/data/web/inc/functions.mailbox.inc.php
+++ b/data/web/inc/functions.mailbox.inc.php
@@ -1,4149 +1,3500 @@
<?php
function mailbox($_action, $_type, $_data = null, $_extra = null) {
global $pdo;
global $redis;
global $lang;
$_data_log = $_data;
!isset($_data_log['password']) ?: $_data_log['password'] = '*';
!isset($_data_log['password2']) ?: $_data_log['password2'] = '*';
switch ($_action) {
case 'add':
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'
);
return false;
}
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'
);
return false;
}
else {
$username = $_data['username'];
}
}
else {
$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']))
);
break;
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'
);
return false;
}
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'
);
return false;
}
else {
$username = $_data['username'];
}
}
elseif ($_SESSION['mailcow_cc_role'] == "user") {
$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'
);
return false;
}
$active = intval($_data['active']);
$script_data = $_data['script_data'];
$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'
);
return false;
}
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;
}
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'
);
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'
);
return false;
}
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)
);
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'
);
return false;
}
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'
);
return false;
}
else {
$username = $_data['username'];
}
}
elseif ($_SESSION['mailcow_cc_role'] == "user") {
$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'
);
return false;
}
$active = intval($_data['active']);
$subscribeall = intval($_data['subscribeall']);
$delete2duplicates = intval($_data['delete2duplicates']);
$delete1 = intval($_data['delete1']);
$delete2 = intval($_data['delete2']);
$timeout1 = intval($_data['timeout1']);
$timeout2 = intval($_data['timeout2']);
$skipcrossduplicates = intval($_data['skipcrossduplicates']);
$automap = intval($_data['automap']);
$port1 = $_data['port1'];
$host1 = strtolower($_data['host1']);
$password1 = $_data['password1'];
$exclude = $_data['exclude'];
$maxage = $_data['maxage'];
$maxbytespersecond = $_data['maxbytespersecond'];
$subfolder2 = $_data['subfolder2'];
$user1 = $_data['user1'];
$mins_interval = $_data['mins_interval'];
$enc1 = $_data['enc1'];
$custom_params = (empty(trim($_data['custom_params']))) ? '' : trim($_data['custom_params']);
if (empty($subfolder2)) {
$subfolder2 = "";
}
if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
$maxage = "0";
}
if (!isset($timeout1) || !filter_var($timeout1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
$timeout1 = "600";
}
if (!isset($timeout2) || !filter_var($timeout2, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
$timeout2 = "600";
}
if (!isset($maxbytespersecond) || !filter_var($maxbytespersecond, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 125000000)))) {
$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;
}
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;
}
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;
}
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;
}
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)
);
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'
);
return false;
}
$domain = idn_to_ascii(strtolower(trim($_data['domain'])));
$description = $_data['description'];
$aliases = $_data['aliases'];
$mailboxes = $_data['mailboxes'];
$maxquota = $_data['maxquota'];
$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'
);
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'
);
return false;
}
$active = intval($_data['active']);
$relay_all_recipients = intval($_data['relay_all_recipients']);
$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'
);
return false;
}
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))
);
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))
);
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']));
$gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto']));
$active = intval($_data['active']);
$goto_null = intval($_data['goto_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'
);
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'
);
return false;
}
if ($goto_null == "1") {
$goto = "null@localhost";
}
elseif ($goto_spam == "1") {
$goto = "spam@localhost";
}
elseif ($goto_ham == "1") {
$goto = "ham@localhost";
}
else {
- foreach ($gotos as &$goto) {
+ foreach ($gotos as $i => &$goto) {
if (empty($goto)) {
continue;
}
$goto_domain = idn_to_ascii(substr(strstr($goto, '@'), 1));
$goto_local_part = strstr($goto, '@', true);
$goto = $goto_local_part.'@'.$goto_domain;
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
WHERE `kind` REGEXP 'location|thing|group'
AND `username`= :goto");
$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) {
if (empty($address)) {
continue;
}
if (in_array($address, $gotos)) {
continue;
}
$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`
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(
+ $_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'
);
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'
);
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':
$local_part = strtolower(trim($_data['local_part']));
$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'
);
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'
);
return false;
}
$password = $_data['password'];
$password2 = $_data['password2'];
$name = $_data['name'];
$quota_m = filter_var($_data['quota'], FILTER_SANITIZE_NUMBER_FLOAT);
if (empty($name)) {
$name = $local_part;
}
$active = intval($_data['active']);
$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'
);
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'
);
return false;
}
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;
}
if ($password != $password2) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'password_mismatch'
);
return false;
}
$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'
);
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'])
);
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'])
);
return false;
}
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'])));
$description = $_data['description'];
$local_part = preg_replace('/[^\da-z]/i', '', preg_quote($description, '/'));
$name = $local_part . '@' . $domain;
$kind = $_data['kind'];
$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'
);
return false;
}
if (empty($description)) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'description_invalid'
);
return false;
}
if (!isset($multiple_bookings) || $multiple_bookings < -1) {
$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'
);
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'
);
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;
case 'edit':
switch ($_type) {
case 'alias_domain':
$alias_domains = (array)$_data['alias_domain'];
foreach ($alias_domains as $alias_domain) {
$alias_domain = idn_to_ascii(strtolower(trim($alias_domain)));
$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'];
}
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'])) {
$usernames = array();
$usernames[] = $_data['username'];
}
else {
$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'
);
return false;
}
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)) {
$tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in'];
$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'])) {
$usernames = array();
$usernames[] = $_data['username'];
}
else {
$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'
);
return false;
}
foreach ($usernames as $username) {
$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'
);
return false;
}
if (!is_array($_data['address'])) {
$addresses = array();
$addresses[] = $_data['address'];
}
else {
$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'])) {
$usernames = array();
$usernames[] = $_data['username'];
}
else {
$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'
);
return false;
}
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 {
$redis->hSet('RCPT_WANTS_SUBJECT_TAG', $username, 1);
$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") {
try {
$redis->hSet('RCPT_WANTS_SUBFOLDER_TAG', $username, 1);
$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 {
try {
$redis->hDel('RCPT_WANTS_SUBJECT_TAG', $username);
$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'];
}
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(
+ $_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 {
try {
$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'])) {
$ids = array();
$ids[] = $_data['id'];
}
else {
$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'
);
return false;
}
foreach ($ids as $id) {
$is_now = mailbox('get', 'syncjob_details', $id, array('with_password'));
if (!empty($is_now)) {
$username = $is_now['user2'];
$user1 = (!empty($_data['user1'])) ? $_data['user1'] : $is_now['user1'];
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$last_run = (isset($_data['last_run'])) ? NULL : $is_now['last_run'];
$delete2duplicates = (isset($_data['delete2duplicates'])) ? intval($_data['delete2duplicates']) : $is_now['delete2duplicates'];
$subscribeall = (isset($_data['subscribeall'])) ? intval($_data['subscribeall']) : $is_now['subscribeall'];
$delete1 = (isset($_data['delete1'])) ? intval($_data['delete1']) : $is_now['delete1'];
$delete2 = (isset($_data['delete2'])) ? intval($_data['delete2']) : $is_now['delete2'];
$automap = (isset($_data['automap'])) ? intval($_data['automap']) : $is_now['automap'];
$skipcrossduplicates = (isset($_data['skipcrossduplicates'])) ? intval($_data['skipcrossduplicates']) : $is_now['skipcrossduplicates'];
$port1 = (!empty($_data['port1'])) ? $_data['port1'] : $is_now['port1'];
$password1 = (!empty($_data['password1'])) ? $_data['password1'] : $is_now['password1'];
$host1 = (!empty($_data['host1'])) ? $_data['host1'] : $is_now['host1'];
$subfolder2 = (isset($_data['subfolder2'])) ? $_data['subfolder2'] : $is_now['subfolder2'];
$enc1 = (!empty($_data['enc1'])) ? $_data['enc1'] : $is_now['enc1'];
$mins_interval = (!empty($_data['mins_interval'])) ? $_data['mins_interval'] : $is_now['mins_interval'];
$exclude = (isset($_data['exclude'])) ? $_data['exclude'] : $is_now['exclude'];
$custom_params = (isset($_data['custom_params'])) ? $_data['custom_params'] : $is_now['custom_params'];
$maxage = (isset($_data['maxage']) && $_data['maxage'] != "") ? intval($_data['maxage']) : $is_now['maxage'];
$maxbytespersecond = (isset($_data['maxbytespersecond']) && $_data['maxbytespersecond'] != "") ? intval($_data['maxbytespersecond']) : $is_now['maxbytespersecond'];
$timeout1 = (isset($_data['timeout1']) && $_data['timeout1'] != "") ? intval($_data['timeout1']) : $is_now['timeout1'];
$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 = "";
}
if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
$maxage = "0";
}
if (!isset($timeout1) || !filter_var($timeout1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
$timeout1 = "600";
}
if (!isset($timeout2) || !filter_var($timeout2, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
$timeout2 = "600";
}
if (!isset($maxbytespersecond) || !filter_var($maxbytespersecond, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 125000000)))) {
$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();
if (!is_array($_data['id'])) {
$ids = array();
$ids[] = $_data['id'];
}
else {
$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'
);
return false;
}
foreach ($ids as $id) {
$is_now = mailbox('get', 'filter_details', $id);
if (!empty($is_now)) {
$username = $is_now['username'];
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$script_desc = (!empty($_data['script_desc'])) ? $_data['script_desc'] : $is_now['script_desc'];
$script_data = (!empty($_data['script_data'])) ? $_data['script_data'] : $is_now['script_data'];
$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";
}
elseif ($goto_spam == "1") {
$goto = "spam@localhost";
}
elseif ($goto_ham == "1") {
$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'])) {
$domains = array();
$domains[] = $_data['domain'];
}
else {
$domains = $_data['domain'];
}
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);
if (!empty($is_now)) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$backupmx = (isset($_data['backupmx'])) ? intval($_data['backupmx']) : $is_now['backupmx_int'];
$relay_all_recipients = (isset($_data['relay_all_recipients'])) ? intval($_data['relay_all_recipients']) : $is_now['relay_all_recipients_int'];
$relayhost = (isset($_data['relayhost'])) ? intval($_data['relayhost']) : $is_now['relayhost'];
$aliases = (!empty($_data['aliases'])) ? $_data['aliases'] : $is_now['max_num_aliases_for_domain'];
$mailboxes = (!empty($_data['mailboxes'])) ? $_data['mailboxes'] : $is_now['max_num_mboxes_for_domain'];
$maxquota = (!empty($_data['maxquota'])) ? $_data['maxquota'] : ($is_now['max_quota_for_mbox'] / 1048576);
$quota = (!empty($_data['quota'])) ? $_data['quota'] : ($is_now['max_quota_for_domain'] / 1048576);
$description = (!empty($_data['description'])) ? $_data['description'] : $is_now['description'];
($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'])) {
$usernames = array();
$usernames[] = $_data['username'];
}
else {
$usernames = $_data['username'];
}
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)) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
(int)$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($is_now['attributes']['force_pw_update']);
$name = (!empty($_data['name'])) ? $_data['name'] : $is_now['name'];
$domain = $is_now['domain'];
$quota_m = (!empty($_data['quota'])) ? $_data['quota'] : ($is_now['quota'] / 1048576);
$quota_b = $quota_m * 1048576;
$password = (!empty($_data['password'])) ? $_data['password'] : 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
$sender_acl_admin = array_merge(
mailbox('get', 'sender_acl_handles', $username)['sender_acl_domains']['ro'],
mailbox('get', 'sender_acl_handles', $username)['sender_acl_addresses']['ro']
);
// Get sender_acl items from POST array
// Set sender_acl_domain_admin to empty array if sender_acl contains "default" to trigger a reset
// Delete records from sender_acl if sender_acl contains "*" and set to array("*")
$_data['sender_acl'] = (array)$_data['sender_acl'];
if (in_array("*", $_data['sender_acl'])) {
$sender_acl_domain_admin = array('*');
}
elseif (array("default") === $_data['sender_acl']) {
$sender_acl_domain_admin = array();
}
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'];
}
if (!empty($sender_acl_domain_admin) || !empty($sender_acl_admin)) {
// Check items in POST array and skip invalid
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;
}
}
}
// Merge both arrays
$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'])) {
$names = array();
$names[] = $_data['name'];
}
else {
$names = $_data['name'];
}
foreach ($names as $name) {
$is_now = mailbox('get', 'resource_details', $name);
if (!empty($is_now)) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$multiple_bookings = (isset($_data['multiple_bookings'])) ? intval($_data['multiple_bookings']) : $is_now['multiple_bookings'];
$description = (!empty($_data['description'])) ? $_data['description'] : $is_now['description'];
$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;
case 'get':
switch ($_type) {
case 'sender_acl_handles':
if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
return false;
}
$data['sender_acl_domains']['ro'] = array();
$data['sender_acl_domains']['rw'] = array();
$data['sender_acl_domains']['selectable'] = array();
$data['sender_acl_addresses']['ro'] = array();
$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;
case 'mailboxes':
$mailboxes = array();
if (isset($_data) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
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;
break;
case 'tls_policy':
$attrs = array();
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
}
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'],
'tls_enforce_out' => $attrs['tls_enforce_out']
);
break;
case 'filters':
$filters = array();
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
}
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;
case 'filter_details':
$filter_details = array();
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;
}
return $filter_details;
break;
case 'active_user_sieve':
$filter_details = array();
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
}
else {
$_data = $_SESSION['mailcow_cc_username'];
}
$exec_fields = array(
'cmd' => 'sieve_list',
'username' => $_data
);
$filters = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);
$filters = array_filter(explode(PHP_EOL, $filters));
foreach ($filters as $filter) {
if (preg_match('/.+ ACTIVE/i', $filter)) {
$exec_fields = array(
'cmd' => 'sieve_print',
'script_name' => substr($filter, 0, -7),
'username' => $_data
);
$filters = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);
return preg_replace('/^.+\n/', '', $filters);
}
}
return false;
break;
case 'syncjob_details':
$syncjobdetails = array();
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;
}
return $syncjobdetails;
break;
case 'syncjobs':
$syncjobdata = array();
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
}
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;
case 'spam_score':
$default = "5, 15";
$policydata = array();
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
}
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':
$tladata = array();
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
}
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':
$policydata = array();
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
}
else {
$_data = $_SESSION['mailcow_cc_username'];
}
try {
if ($redis->hGet('RCPT_WANTS_SUBJECT_TAG', $_data)) {
return "subject";
}
elseif ($redis->hGet('RCPT_WANTS_SUBFOLDER_TAG', $_data)) {
return "subfolder";
}
else {
return "none";
}
}
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;
}
break;
case 'resources':
$resources = array();
if (isset($_data) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
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;
break;
case 'alias_domains':
$aliasdomains = array();
if (isset($_data) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
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;
break;
case 'aliases':
$aliases = array();
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'
);
return false;
}
}
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'
);
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(
+ $_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();
- 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;
}
return $aliasdomaindata;
break;
case 'domains':
$domains = array();
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;
case 'domain_details':
$domaindata = array();
$_data = idn_to_ascii(strtolower(trim($_data)));
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':
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
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;
case 'resource_details':
$resourcedata = array();
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;
}
return $resourcedata;
break;
}
break;
case 'delete':
switch ($_type) {
case 'syncjob':
if (!is_array($_data['id'])) {
$ids = array();
$ids[] = $_data['id'];
}
else {
$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'
);
return false;
}
foreach ($ids as $id) {
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'])) {
$ids = array();
$ids[] = $_data['id'];
}
else {
$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'
);
return false;
}
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'])) {
$addresses = array();
$addresses[] = $_data['address'];
}
else {
$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'
);
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'])) {
$usernames = array();
$usernames[] = $_data['username'];
}
else {
$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'
);
return false;
}
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'])) {
$domains = array();
$domains[] = $_data['domain'];
}
else {
$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'
);
return false;
}
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'])) {
$alias_domains = array();
$alias_domains[] = $_data['alias_domain'];
}
else {
$alias_domains = $_data['alias_domain'];
}
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'])) {
$usernames = array();
$usernames[] = $_data['username'];
}
else {
$usernames = $_data['username'];
}
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'])) {
$names = array();
$names[] = $_data['name'];
}
else {
$names = $_data['name'];
}
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;
}
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 6bc2f780..c8526169 100644
--- a/data/web/inc/functions.policy.inc.php
+++ b/data/web/inc/functions.policy.inc.php
@@ -1,392 +1,320 @@
<?php
function policy($_action, $_scope, $_data = null) {
global $pdo;
global $redis;
global $lang;
$_data_log = $_data;
switch ($_action) {
case 'add':
switch ($_scope) {
case 'domain':
$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'
);
return false;
}
$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;
}
if ($_data['object_list'] == "bl") {
$object_list = "blacklist_from";
}
elseif ($_data['object_list'] == "wl") {
$object_list = "whitelist_from";
}
$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'
);
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)
);
break;
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'
);
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'
);
return false;
}
if ($_data['object_list'] == "bl") {
$object_list = "blacklist_from";
}
elseif ($_data['object_list'] == "wl") {
$object_list = "whitelist_from";
}
$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'
);
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)
);
break;
}
break;
case 'delete':
switch ($_scope) {
case 'domain':
(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");
$stmt->execute(array(
':object' => $object,
':prefid' => $prefid
));
}
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'])) {
$prefids = array();
$prefids[] = $_data['prefid'];
}
else {
$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'
);
return false;
}
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");
$stmt->execute(array(
':object' => $object,
':prefid' => $prefid
));
}
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;
case 'get':
switch ($_scope) {
case 'domain':
if (!is_valid_domain_name($_data)) {
return false;
}
else {
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
$_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':
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
}
}
else {
$_data = $_SESSION['mailcow_cc_username'];
}
$domain = mailbox('get', 'mailbox_details', $_data)['domain'];
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;
}
break;
}
}
\ No newline at end of file
diff --git a/data/web/inc/functions.quarantine.inc.php b/data/web/inc/functions.quarantine.inc.php
index 865a0f08..c92a2cdd 100644
--- a/data/web/inc/functions.quarantine.inc.php
+++ b/data/web/inc/functions.quarantine.inc.php
@@ -1,311 +1,389 @@
<?php
function quarantine($_action, $_data = null) {
global $pdo;
global $redis;
global $lang;
$_data_log = $_data;
switch ($_action) {
case 'delete':
if (!is_array($_data['id'])) {
$ids = array();
$ids[] = $_data['id'];
}
else {
$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'
);
return false;
}
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'
);
return false;
}
// 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'
);
return false;
}
$retention_size = $_data['retention_size'];
$max_size = $_data['max_size'];
$exclude_domains = (array)$_data['exclude_domains'];
try {
$redis->Set('Q_RETENTION_SIZE', intval($retention_size));
$redis->Set('Q_MAX_SIZE', intval($max_size));
$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'
);
}
// Release item
elseif ($_data['action'] == 'release') {
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(
+ $_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 {
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->SMTPDebug = 0;
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
if (!empty(gethostbynamel('postfix-mailcow'))) {
$postfix = 'postfix-mailcow';
}
if (!empty(gethostbynamel('postfix'))) {
$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;
$mail->setFrom($sender);
$mail->CharSet = 'UTF-8';
$mail->Subject = sprintf($lang['quarantine']['release_subject'], $row['qid']);
$mail->addAddress($row['rcpt']);
$mail->IsHTML(false);
$msg_tmpf = tempnam("/tmp", $row['qid']);
file_put_contents($msg_tmpf, $row['msg']);
$mail->addAttachment($msg_tmpf, $row['qid'] . '.eml');
$mail->Body = sprintf($lang['quarantine']['release_body']);
$mail->send();
unlink($msg_tmpf);
}
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");
$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('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'
);
return false;
}
try {
$settings['exclude_domains'] = json_decode($redis->Get('Q_EXCLUDE_DOMAINS'), true);
$settings['max_size'] = $redis->Get('Q_MAX_SIZE');
$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)
);
return false;
}
return $settings;
break;
case 'details':
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 8faad80a..a3e1ffda 100644
--- a/data/web/inc/functions.relayhost.inc.php
+++ b/data/web/inc/functions.relayhost.inc.php
@@ -1,193 +1,174 @@
<?php
function relayhost($_action, $_data = null) {
global $pdo;
global $lang;
$_data_log = $_data;
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'
);
return false;
}
$hostname = trim($_data['hostname']);
$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))
);
return false;
}
try {
$stmt = $pdo->prepare("INSERT INTO `relayhosts` (`hostname`, `username` ,`password`, `active`)
VALUES (:hostname, :username, :password, :active)");
$stmt->execute(array(
':hostname' => $hostname,
':username' => $username,
':password' => str_replace(':', '\:', $password),
':active' => '1'
));
}
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)))
);
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'
);
return false;
}
$ids = (array)$_data['id'];
foreach ($ids as $id) {
$is_now = relayhost('details', $id);
if (!empty($is_now)) {
$hostname = (!empty($_data['hostname'])) ? trim($_data['hostname']) : $is_now['hostname'];
$username = (isset($_data['username'])) ? trim($_data['username']) : $is_now['username'];
$password = (isset($_data['password'])) ? trim($_data['password']) : $is_now['password'];
$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
`hostname` = :hostname,
`username` = :username,
`password` = :password,
`active` = :active
WHERE `id` = :id");
$stmt->execute(array(
':id' => $id,
':hostname' => $hostname,
':username' => $username,
':password' => $password,
':active' => $active
));
}
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'
);
return false;
}
$ids = (array)$_data['id'];
foreach ($ids as $id) {
try {
$stmt = $pdo->prepare("DELETE FROM `relayhosts` WHERE `id`= :id");
$stmt->execute(array(':id' => $id));
$stmt = $pdo->prepare("UPDATE `domain` SET `relayhost` = '0' WHERE `relayhost`= :id");
$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':
if ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) {
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;
}
}
\ No newline at end of file
diff --git a/data/web/inc/functions.rsettings.inc.php b/data/web/inc/functions.rsettings.inc.php
index 9f13a4c3..fbf8922b 100644
--- a/data/web/inc/functions.rsettings.inc.php
+++ b/data/web/inc/functions.rsettings.inc.php
@@ -1,178 +1,160 @@
<?php
function rsettings($_action, $_data = null) {
global $pdo;
global $lang;
$_data_log = $_data;
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'
);
return false;
}
$content = $_data['content'];
$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'
);
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(
+ $_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'
);
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'
);
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(
+ $_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 {
$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(
+ $_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'
);
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(
+ $_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':
if ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) {
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;
}
}
\ No newline at end of file
diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php
index b938a56b..c99484d5 100644
--- a/data/web/inc/init_db.inc.php
+++ b/data/web/inc/init_db.inc.php
@@ -1,953 +1,960 @@
<?php
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));
if ($num_results != 0) {
$stmt = $pdo->query("SELECT `version` FROM `versions`");
if ($stmt->fetch(PDO::FETCH_ASSOC)['version'] == $db_version) {
return true;
}
}
$views = array(
"grouped_mail_aliases" => "CREATE VIEW grouped_mail_aliases (username, aliases) AS
SELECT goto, IFNULL(GROUP_CONCAT(address SEPARATOR ' '), '') AS address FROM alias
WHERE address!=goto
AND active = '1'
AND address NOT LIKE '@%'
GROUP BY goto;",
"grouped_sender_acl" => "CREATE VIEW grouped_sender_acl (username, send_as_acl) AS
SELECT logged_in_as, IFNULL(GROUP_CONCAT(send_as SEPARATOR ' '), '') AS send_as_acl FROM sender_acl
WHERE send_as NOT LIKE '@%'
GROUP BY logged_in_as;",
"grouped_domain_alias_address" => "CREATE VIEW grouped_domain_alias_address (username, ad_alias) AS
SELECT username, IFNULL(GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ' '), '') AS ad_alias FROM mailbox
LEFT OUTER JOIN alias_domain ON target_domain=domain
GROUP BY username;",
"sieve_before" => "CREATE VIEW sieve_before (id, username, script_name, script_data) AS
SELECT md5(script_data), username, script_name, script_data FROM sieve_filters
WHERE filter_type = 'prefilter';",
"sieve_after" => "CREATE VIEW sieve_after (id, username, script_name, script_data) AS
SELECT md5(script_data), username, script_name, script_data FROM sieve_filters
WHERE filter_type = 'postfilter';"
);
$tables = array(
"versions" => array(
"cols" => array(
"application" => "VARCHAR(255) NOT NULL",
"version" => "VARCHAR(100) NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
),
"keys" => array(
"primary" => array(
"" => array("application")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"admin" => array(
"cols" => array(
"username" => "VARCHAR(255) NOT NULL",
"password" => "VARCHAR(255) NOT NULL",
"superadmin" => "TINYINT(1) NOT NULL DEFAULT '0'",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE NOW(0)",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
"primary" => array(
"" => array("username")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"_sogo_static_view" => array(
"cols" => array(
"c_uid" => "VARCHAR(255) NOT NULL",
"domain" => "VARCHAR(255) NOT NULL",
"c_name" => "VARCHAR(255) NOT NULL",
"c_password" => "VARCHAR(255) NOT NULL DEFAULT ''",
"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 ''",
"ad_aliases" => "VARCHAR(6144) NOT NULL DEFAULT ''",
"home" => "VARCHAR(255)",
"kind" => "VARCHAR(100) NOT NULL DEFAULT ''",
"multiple_bookings" => "INT NOT NULL DEFAULT -1"
),
"keys" => array(
"primary" => array(
"" => array("c_uid")
),
"key" => array(
"domain" => array("domain")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"relayhosts" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"hostname" => "VARCHAR(255) NOT NULL",
"username" => "VARCHAR(255) NOT NULL",
"password" => "VARCHAR(255) NOT NULL",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
"primary" => array(
"" => array("id")
),
"key" => array(
"hostname" => array("hostname")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"alias" => array(
"cols" => array(
+ "id" => "INT NOT NULL AUTO_INCREMENT",
"address" => "VARCHAR(255) NOT NULL",
"goto" => "TEXT NOT NULL",
"domain" => "VARCHAR(255) NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
"primary" => array(
- "" => array("address")
+ "" => array("id")
+ ),
+ "unique" => array(
+ "address" => array("address")
),
"key" => array(
"domain" => array("domain")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"api" => array(
"cols" => array(
"username" => "VARCHAR(255) NOT NULL",
"api_key" => "VARCHAR(255) NOT NULL",
"allow_from" => "VARCHAR(512) NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE NOW(0)",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
"primary" => array(
"" => array("username")
),
"fkey" => array(
"fk_username_api" => array(
"col" => "username",
"ref" => "admin.username",
"delete" => "CASCADE",
"update" => "CASCADE"
)
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sender_acl" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"logged_in_as" => "VARCHAR(255) NOT NULL",
"send_as" => "VARCHAR(255) NOT NULL"
),
"keys" => array(
"primary" => array(
"" => array("id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"domain" => array(
"cols" => array(
"domain" => "VARCHAR(255) NOT NULL",
"description" => "VARCHAR(255)",
"aliases" => "INT(10) NOT NULL DEFAULT '0'",
"mailboxes" => "INT(10) NOT NULL DEFAULT '0'",
"maxquota" => "BIGINT(20) NOT NULL DEFAULT '0'",
"quota" => "BIGINT(20) NOT NULL DEFAULT '102400'",
"relayhost" => "VARCHAR(255) NOT NULL DEFAULT '0'",
"backupmx" => "TINYINT(1) NOT NULL DEFAULT '0'",
"relay_all_recipients" => "TINYINT(1) NOT NULL DEFAULT '0'",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
"primary" => array(
"" => array("domain")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"quarantine" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"qid" => "VARCHAR(30) NOT NULL",
"score" => "FLOAT(8,2)",
"ip" => "VARBINARY(16)",
"action" => "CHAR(20) NOT NULL DEFAULT 'unknown'",
"symbols" => "JSON",
"sender" => "VARCHAR(255) NOT NULL DEFAULT 'unknown'",
"rcpt" => "VARCHAR(255)",
"msg" => "LONGTEXT",
"domain" => "VARCHAR(255)",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"user" => "VARCHAR(255) NOT NULL DEFAULT 'unknown'",
),
"keys" => array(
"primary" => array(
"" => array("id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"mailbox" => array(
"cols" => array(
"username" => "VARCHAR(255) NOT NULL",
"password" => "VARCHAR(255) NOT NULL",
"name" => "VARCHAR(255)",
"maildir" => "VARCHAR(255) NOT NULL",
"quota" => "BIGINT(20) NOT NULL DEFAULT '102400'",
"local_part" => "VARCHAR(255) NOT NULL",
"domain" => "VARCHAR(255) NOT NULL",
"attributes" => "JSON",
"kind" => "VARCHAR(100) NOT NULL DEFAULT ''",
"multiple_bookings" => "INT NOT NULL DEFAULT -1",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
"primary" => array(
"" => array("username")
),
"key" => array(
"domain" => array("domain")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sieve_filters" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"username" => "VARCHAR(255) NOT NULL",
"script_desc" => "VARCHAR(255) NOT NULL",
"script_name" => "ENUM('active','inactive')",
"script_data" => "TEXT NOT NULL",
"filter_type" => "ENUM('postfilter','prefilter')",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP"
),
"keys" => array(
"primary" => array(
"" => array("id")
),
"key" => array(
"username" => array("username"),
"script_desc" => array("script_desc")
),
"fkey" => array(
"fk_username_sieve_global_before" => array(
"col" => "username",
"ref" => "mailbox.username",
"delete" => "CASCADE",
"update" => "NO ACTION"
)
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"user_acl" => array(
"cols" => array(
"username" => "VARCHAR(255) NOT NULL",
"spam_alias" => "TINYINT(1) NOT NULL DEFAULT '1'",
"tls_policy" => "TINYINT(1) NOT NULL DEFAULT '1'",
"spam_score" => "TINYINT(1) NOT NULL DEFAULT '1'",
"spam_policy" => "TINYINT(1) NOT NULL DEFAULT '1'",
"delimiter_action" => "TINYINT(1) NOT NULL DEFAULT '1'",
"syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'",
"eas_reset" => "TINYINT(1) NOT NULL DEFAULT '1'",
"filters" => "TINYINT(1) NOT NULL DEFAULT '1'",
"quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'",
"bcc_maps" => "TINYINT(1) NOT NULL DEFAULT '1'",
"recipient_maps" => "TINYINT(1) NOT NULL DEFAULT '0'",
),
"keys" => array(
"primary" => array(
"" => array("username")
),
"fkey" => array(
"fk_username" => array(
"col" => "username",
"ref" => "mailbox.username",
"delete" => "CASCADE",
"update" => "NO ACTION"
)
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"alias_domain" => array(
"cols" => array(
"alias_domain" => "VARCHAR(255) NOT NULL",
"target_domain" => "VARCHAR(255) NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
"primary" => array(
"" => array("alias_domain")
),
"key" => array(
"active" => array("active"),
"target_domain" => array("target_domain")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"spamalias" => array(
"cols" => array(
"address" => "VARCHAR(255) NOT NULL",
"goto" => "TEXT NOT NULL",
"validity" => "INT(11) NOT NULL"
),
"keys" => array(
"primary" => array(
"" => array("address")
),
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"filterconf" => array(
"cols" => array(
"object" => "VARCHAR(255) NOT NULL DEFAULT ''",
"option" => "VARCHAR(50) NOT NULL DEFAULT ''",
"value" => "VARCHAR(100) NOT NULL DEFAULT ''",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"prefid" => "INT(11) NOT NULL AUTO_INCREMENT"
),
"keys" => array(
"primary" => array(
"" => array("prefid")
),
"key" => array(
"object" => array("object")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"settingsmap" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"desc" => "VARCHAR(255) NOT NULL",
"content" => "LONGTEXT NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"active" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(
"" => array("id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"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",
"user" => "VARCHAR(64) NOT NULL",
"role" => "VARCHAR(32) NOT NULL",
"remote" => "VARCHAR(32) NOT NULL",
"time" => "INT(11) NOT NULL"
),
"keys" => array(
"primary" => array(
"" => array("id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"quota2" => array(
"cols" => array(
"username" => "VARCHAR(255) NOT NULL",
"bytes" => "BIGINT(20) NOT NULL DEFAULT '0'",
"messages" => "BIGINT(20) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(
"" => array("username")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"domain_admins" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"username" => "VARCHAR(255) NOT NULL",
"domain" => "VARCHAR(255) NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
"primary" => array(
"" => array("id")
),
"key" => array(
"username" => array("username")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"imapsync" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"user2" => "VARCHAR(255) NOT NULL",
"host1" => "VARCHAR(255) NOT NULL",
"authmech1" => "ENUM('PLAIN','LOGIN','CRAM-MD5') DEFAULT 'PLAIN'",
"regextrans2" => "VARCHAR(255) DEFAULT ''",
"authmd51" => "TINYINT(1) NOT NULL DEFAULT 0",
"domain2" => "VARCHAR(255) NOT NULL DEFAULT ''",
"subfolder2" => "VARCHAR(255) NOT NULL DEFAULT ''",
"user1" => "VARCHAR(255) NOT NULL",
"password1" => "VARCHAR(255) NOT NULL",
"exclude" => "VARCHAR(500) NOT NULL DEFAULT ''",
"maxage" => "SMALLINT NOT NULL DEFAULT '0'",
"mins_interval" => "VARCHAR(50) NOT NULL DEFAULT '0'",
"maxbytespersecond" => "VARCHAR(50) NOT NULL DEFAULT '0'",
"port1" => "SMALLINT NOT NULL",
"enc1" => "ENUM('TLS','SSL','PLAIN') DEFAULT 'TLS'",
"delete2duplicates" => "TINYINT(1) NOT NULL DEFAULT '1'",
"delete1" => "TINYINT(1) NOT NULL DEFAULT '0'",
"delete2" => "TINYINT(1) NOT NULL DEFAULT '0'",
"automap" => "TINYINT(1) NOT NULL DEFAULT '0'",
"skipcrossduplicates" => "TINYINT(1) NOT NULL DEFAULT '0'",
"custom_params" => "VARCHAR(512) NOT NULL DEFAULT ''",
"timeout1" => "SMALLINT NOT NULL DEFAULT '600'",
"timeout2" => "SMALLINT NOT NULL DEFAULT '600'",
"subscribeall" => "TINYINT(1) NOT NULL DEFAULT '1'",
"is_running" => "TINYINT(1) NOT NULL DEFAULT '0'",
"returned_text" => "MEDIUMTEXT",
"last_run" => "TIMESTAMP NULL DEFAULT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"active" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(
"" => array("id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"bcc_maps" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"local_dest" => "VARCHAR(255) NOT NULL",
"bcc_dest" => "VARCHAR(255) NOT NULL",
"domain" => "VARCHAR(255) NOT NULL",
"type" => "ENUM('sender','rcpt')",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"active" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(
"" => array("id")
),
"key" => array(
"local_dest" => array("local_dest"),
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"recipient_maps" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"old_dest" => "VARCHAR(255) NOT NULL",
"new_dest" => "VARCHAR(255) NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"active" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(
"" => array("id")
),
"key" => array(
"local_dest" => array("old_dest"),
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"tfa" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"key_id" => "VARCHAR(255) NOT NULL",
"username" => "VARCHAR(255) NOT NULL",
"authmech" => "ENUM('yubi_otp', 'u2f', 'hotp', 'totp')",
"secret" => "VARCHAR(255) DEFAULT NULL",
"keyHandle" => "VARCHAR(255) DEFAULT NULL",
"publicKey" => "VARCHAR(255) DEFAULT NULL",
"counter" => "INT NOT NULL DEFAULT '0'",
"certificate" => "TEXT",
"active" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(
"" => array("id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"forwarding_hosts" => array(
"cols" => array(
"host" => "VARCHAR(255) NOT NULL",
"source" => "VARCHAR(255) NOT NULL",
"filter_spam" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(
"" => array("host")
),
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_acl" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"c_folder_id" => "INT NOT NULL",
"c_object" => "VARCHAR(255) NOT NULL",
"c_uid" => "VARCHAR(255) NOT NULL",
"c_role" => "VARCHAR(80) NOT NULL"
),
"keys" => array(
"primary" => array(
"" => array("id")
),
"key" => array(
"sogo_acl_c_folder_id_idx" => array("c_folder_id"),
"sogo_acl_c_uid_idx" => array("c_uid")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_alarms_folder" => array(
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"c_path" => "VARCHAR(255) NOT NULL",
"c_name" => "VARCHAR(255) NOT NULL",
"c_uid" => "VARCHAR(255) NOT NULL",
"c_recurrence_id" => "INT(11) DEFAULT NULL",
"c_alarm_number" => "INT(11) NOT NULL",
"c_alarm_date" => "INT(11) NOT NULL"
),
"keys" => array(
"primary" => array(
"" => array("id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_cache_folder" => array(
"cols" => array(
"c_uid" => "VARCHAR(255) NOT NULL",
"c_path" => "VARCHAR(255) NOT NULL",
"c_parent_path" => "VARCHAR(255) DEFAULT NULL",
"c_type" => "TINYINT(3) unsigned NOT NULL",
"c_creationdate" => "INT(11) NOT NULL",
"c_lastmodified" => "INT(11) NOT NULL",
"c_version" => "INT(11) NOT NULL DEFAULT '0'",
"c_deleted" => "TINYINT(4) NOT NULL DEFAULT '0'",
"c_content" => "LONGTEXT"
),
"keys" => array(
"primary" => array(
"" => array("c_uid", "c_path")
),
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_folder_info" => array(
"cols" => array(
"c_folder_id" => "BIGINT(20) unsigned NOT NULL AUTO_INCREMENT",
"c_path" => "VARCHAR(255) NOT NULL",
"c_path1" => "VARCHAR(255) NOT NULL",
"c_path2" => "VARCHAR(255) DEFAULT NULL",
"c_path3" => "VARCHAR(255) DEFAULT NULL",
"c_path4" => "VARCHAR(255) DEFAULT NULL",
"c_foldername" => "VARCHAR(255) NOT NULL",
"c_location" => "VARCHAR(2048) DEFAULT NULL",
"c_quick_location" => "VARCHAR(2048) DEFAULT NULL",
"c_acl_location" => "VARCHAR(2048) DEFAULT NULL",
"c_folder_type" => "VARCHAR(255) NOT NULL"
),
"keys" => array(
"primary" => array(
"" => array("c_path")
),
"unique" => array(
"c_folder_id" => array("c_folder_id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_quick_appointment" => array(
"cols" => array(
"c_folder_id" => "INT NOT NULL",
"c_name" => "VARCHAR(255) NOT NULL",
"c_uid" => "VARCHAR(255) NOT NULL",
"c_startdate" => "INT",
"c_enddate" => "INT",
"c_cycleenddate" => "INT",
"c_title" => "VARCHAR(1000) NOT NULL",
"c_participants" => "TEXT",
"c_isallday" => "INT",
"c_iscycle" => "INT",
"c_cycleinfo" => "TEXT",
"c_classification" => "INT NOT NULL",
"c_isopaque" => "INT NOT NULL",
"c_status" => "INT NOT NULL",
"c_priority" => "INT",
"c_location" => "VARCHAR(255)",
"c_orgmail" => "VARCHAR(255)",
"c_partmails" => "TEXT",
"c_partstates" => "TEXT",
"c_category" => "VARCHAR(255)",
"c_sequence" => "INT",
"c_component" => "VARCHAR(10) NOT NULL",
"c_nextalarm" => "INT",
"c_description" => "TEXT"
),
"keys" => array(
"primary" => array(
"" => array("c_folder_id", "c_name")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_quick_contact" => array(
"cols" => array(
"c_folder_id" => "INT NOT NULL",
"c_name" => "VARCHAR(255) NOT NULL",
"c_givenname" => "VARCHAR(255)",
"c_cn" => "VARCHAR(255)",
"c_sn" => "VARCHAR(255)",
"c_screenname" => "VARCHAR(255)",
"c_l" => "VARCHAR(255)",
"c_mail" => "TEXT",
"c_o" => "VARCHAR(255)",
"c_ou" => "VARCHAR(255)",
"c_telephonenumber" => "VARCHAR(255)",
"c_categories" => "VARCHAR(255)",
"c_component" => "VARCHAR(10) NOT NULL",
"c_hascertificate" => "INT4 DEFAULT 0"
),
"keys" => array(
"primary" => array(
"" => array("c_folder_id", "c_name")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_sessions_folder" => array(
"cols" => array(
"c_id" => "VARCHAR(255) NOT NULL",
"c_value" => "VARCHAR(255) NOT NULL",
"c_creationdate" => "INT(11) NOT NULL",
"c_lastseen" => "INT(11) NOT NULL"
),
"keys" => array(
"primary" => array(
"" => array("c_id")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_store" => array(
"cols" => array(
"c_folder_id" => "INT NOT NULL",
"c_name" => "VARCHAR(255) NOT NULL",
"c_content" => "MEDIUMTEXT NOT NULL",
"c_creationdate" => "INT NOT NULL",
"c_lastmodified" => "INT NOT NULL",
"c_version" => "INT NOT NULL",
"c_deleted" => "INT"
),
"keys" => array(
"primary" => array(
"" => array("c_folder_id", "c_name")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"sogo_user_profile" => array(
"cols" => array(
"c_uid" => "VARCHAR(255) NOT NULL",
"c_defaults" => "LONGTEXT",
"c_settings" => "LONGTEXT"
),
"keys" => array(
"primary" => array(
"" => array("c_uid")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
)
);
foreach ($tables as $table => $properties) {
// Migrate to quarantine
if ($table == 'quarantine') {
$stmt = $pdo->query("SHOW TABLES LIKE 'quarantaine'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results != 0) {
$stmt = $pdo->query("SHOW TABLES LIKE 'quarantine'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results == 0) {
$pdo->query("RENAME TABLE `quarantaine` TO `quarantine`");
}
}
}
// Migrate tls_enforce_* options
if ($table == 'mailbox') {
$stmt = $pdo->query("SHOW TABLES LIKE 'mailbox'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results != 0) {
$stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE '%tls_enforce%'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results != 0) {
$stmt = $pdo->query("SELECT `username`, `tls_enforce_in`, `tls_enforce_out` FROM `mailbox`");
$tls_options_rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($tls_options_rows)) {
$tls_options[$row['username']] = array('tls_enforce_in' => $row['tls_enforce_in'], 'tls_enforce_out' => $row['tls_enforce_out']);
}
}
}
}
$stmt = $pdo->query("SHOW TABLES LIKE '" . $table . "'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results != 0) {
$stmt = $pdo->prepare("SELECT CONCAT('ALTER TABLE ', `table_schema`, '.', `table_name`, ' DROP FOREIGN KEY ', `constraint_name`, ';') AS `FKEY_DROP` FROM `information_schema`.`table_constraints`
WHERE `constraint_type` = 'FOREIGN KEY' AND `table_name` = :table;");
$stmt->execute(array(':table' => $table));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($rows)) {
$pdo->query($row['FKEY_DROP']);
}
foreach($properties['cols'] as $column => $type) {
$stmt = $pdo->query("SHOW COLUMNS FROM `" . $table . "` LIKE '" . $column . "'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
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);
}
else {
$pdo->query("ALTER TABLE `" . $table . "` MODIFY COLUMN `" . $column . "` " . $type);
}
}
foreach($properties['keys'] as $key_type => $key_content) {
if (strtolower($key_type) == 'primary') {
foreach ($key_content as $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`";
$stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = 'PRIMARY'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
$is_drop = ($num_results != 0) ? "DROP PRIMARY KEY, " : "";
$pdo->query("ALTER TABLE `" . $table . "` " . $is_drop . "ADD PRIMARY KEY (" . $fields . ")");
}
}
if (strtolower($key_type) == 'key') {
foreach ($key_content as $key_name => $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`";
$stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = '" . $key_name . "'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
$is_drop = ($num_results != 0) ? "DROP INDEX `" . $key_name . "`, " : "";
$pdo->query("ALTER TABLE `" . $table . "` " . $is_drop . "ADD KEY `" . $key_name . "` (" . $fields . ")");
}
}
if (strtolower($key_type) == 'unique') {
foreach ($key_content as $key_name => $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`";
$stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = '" . $key_name . "'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
$is_drop = ($num_results != 0) ? "DROP INDEX `" . $key_name . "`, " : "";
$pdo->query("ALTER TABLE `" . $table . "` " . $is_drop . "ADD UNIQUE KEY `" . $key_name . "` (" . $fields . ")");
}
}
if (strtolower($key_type) == 'fkey') {
foreach ($key_content as $key_name => $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`";
$stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = '" . $key_name . "'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results != 0) {
$pdo->query("ALTER TABLE `" . $table . "` DROP INDEX `" . $key_name . "`");
}
@list($table_ref, $field_ref) = explode('.', $key_values['ref']);
$pdo->query("ALTER TABLE `" . $table . "` ADD FOREIGN KEY `" . $key_name . "` (" . $key_values['col'] . ") REFERENCES `" . $table_ref . "` (`" . $field_ref . "`)
ON DELETE " . $key_values['delete'] . " ON UPDATE " . $key_values['update']);
}
}
}
// Drop all vanished columns
$stmt = $pdo->query("SHOW COLUMNS FROM `" . $table . "`");
$cols_in_table = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($cols_in_table)) {
if (!array_key_exists($row['Field'], $properties['cols'])) {
$pdo->query("ALTER TABLE `" . $table . "` DROP COLUMN `" . $row['Field'] . "`;");
}
}
// Step 1: Get all non-primary keys, that currently exist and those that should exist
$stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE `Key_name` != 'PRIMARY'");
$keys_in_table = $stmt->fetchAll(PDO::FETCH_ASSOC);
$keys_to_exist = array();
if (isset($properties['keys']['unique']) && is_array($properties['keys']['unique'])) {
foreach ($properties['keys']['unique'] as $key_name => $key_values) {
$keys_to_exist[] = $key_name;
}
}
if (isset($properties['keys']['key']) && is_array($properties['keys']['key'])) {
foreach ($properties['keys']['key'] as $key_name => $key_values) {
$keys_to_exist[] = $key_name;
}
}
// Index for foreign key must exist
if (isset($properties['keys']['fkey']) && is_array($properties['keys']['fkey'])) {
foreach ($properties['keys']['fkey'] as $key_name => $key_values) {
$keys_to_exist[] = $key_name;
}
}
// Step 2: Drop all vanished indexes
while ($row = array_shift($keys_in_table)) {
if (!in_array($row['Key_name'], $keys_to_exist)) {
$pdo->query("ALTER TABLE `" . $table . "` DROP INDEX `" . $row['Key_name'] . "`");
}
}
// Step 3: Drop all vanished primary keys
if (!isset($properties['keys']['primary'])) {
$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");
}
}
}
else {
// Create table if it is missing
$sql = "CREATE TABLE IF NOT EXISTS `" . $table . "` (";
foreach($properties['cols'] as $column => $type) {
$sql .= "`" . $column . "` " . $type . ",";
}
foreach($properties['keys'] as $key_type => $key_content) {
if (strtolower($key_type) == 'primary') {
foreach ($key_content as $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`";
$sql .= "PRIMARY KEY (" . $fields . ")" . ",";
}
}
elseif (strtolower($key_type) == 'key') {
foreach ($key_content as $key_name => $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`";
$sql .= "KEY `" . $key_name . "` (" . $fields . ")" . ",";
}
}
elseif (strtolower($key_type) == 'unique') {
foreach ($key_content as $key_name => $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`";
$sql .= "UNIQUE KEY `" . $key_name . "` (" . $fields . ")" . ",";
}
}
elseif (strtolower($key_type) == 'fkey') {
foreach ($key_content as $key_name => $key_values) {
@list($table_ref, $field_ref) = explode('.', $key_values['ref']);
$fields = "`" . implode("`, `", $key_values) . "`";
$sql .= "FOREIGN KEY `" . $key_name . "` (" . $key_values['col'] . ") REFERENCES `" . $table_ref . "` (`" . $field_ref . "`)
ON DELETE " . $key_values['delete'] . " ON UPDATE " . $key_values['update'] . ",";
}
}
}
$sql = rtrim($sql, ",");
$sql .= ") " . $properties['attr'];
$pdo->query($sql);
}
// Reset table attributes
$pdo->query("ALTER TABLE `" . $table . "` " . $properties['attr'] . ";");
}
// Recreate SQL views
foreach ($views as $view => $create) {
$pdo->query("DROP VIEW IF EXISTS `" . $view . "`;");
$pdo->query($create);
}
// Create events to clean database
$events[] = 'DROP EVENT IF EXISTS clean_spamalias;
DELIMITER //
CREATE EVENT clean_spamalias
ON SCHEDULE EVERY 1 DAY DO
BEGIN
DELETE FROM spamalias WHERE validity < UNIX_TIMESTAMP();
END;
//
DELIMITER ;';
foreach ($events as $event) {
$pdo->exec($event);
}
// Inject admin if not exists
$stmt = $pdo->query("SELECT NULL FROM `admin`");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results == 0) {
$stmt = $pdo->query("INSERT INTO `admin` (`username`, `password`, `superadmin`, `created`, `modified`, `active`)
VALUES ('admin', '{SSHA256}K8eVJ6YsZbQCfuJvSUbaQRLr0HPLz5rC9IAp0PAFl0tmNDBkMDc0NDAyOTAxN2Rk', 1, NOW(), NOW(), 1)");
$stmt = $pdo->query("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
SELECT `username`, 'ALL', NOW(), 1 FROM `admin`
WHERE superadmin='1' AND `username` NOT IN (SELECT `username` FROM `domain_admins`);");
$stmt = $pdo->query("DELETE FROM `admin` WHERE `username` NOT IN (SELECT `username` FROM `domain_admins`);");
}
// Insert new DB schema version
$stmt = $pdo->query("REPLACE INTO `versions` (`application`, `version`) VALUES ('db_schema', '" . $db_version . "');");
// Migrate tls_enforce_* options and add force_pw_update attribute
$stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = '{}' WHERE `attributes` IS NULL;");
$stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.force_pw_update', 0) WHERE JSON_EXTRACT(`attributes`, '$.force_pw_update') IS NULL;");
foreach($tls_options as $tls_user => $tls_options) {
$stmt = $pdo->prepare("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', :tls_enforce_in),
`attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', :tls_enforce_out)
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'
);
// Fix user_acl
$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 1370155e..0ec41fab 100644
--- a/data/web/inc/prerequisites.inc.php
+++ b/data/web/inc/prerequisites.inc.php
@@ -1,144 +1,163 @@
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.inc.php';
$default_autodiscover_config = $autodiscover_config;
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/inc/vars.local.inc.php')) {
include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.local.inc.php';
}
$autodiscover_config = array_merge($default_autodiscover_config, $autodiscover_config);
header_remove("X-Powered-By");
// Yubi OTP API
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/Yubico.php';
// Autoload composer
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/vendor/autoload.php';
// Load Sieve
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/sieve/SieveParser.php';
// U2F API + T/HOTP API
$u2f = new u2flib_server\U2F('https://' . $_SERVER['HTTP_HOST']);
$tfa = new RobThree\Auth\TwoFactorAuth($OTP_LABEL);
// Redis
$redis = new Redis();
$redis->connect('redis-mailcow', 6379);
// PDO
// Calculate offset
$now = new DateTime();
$mins = $now->getOffset() / 60;
$sgn = ($mins < 0 ? -1 : 1);
$mins = abs($mins);
$hrs = floor($mins / 60);
$mins -= $hrs * 60;
$offset = sprintf('%+d:%02d', $hrs*$sgn, $mins);
$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '" . $offset . "', group_concat_max_len = 3423543543;",
];
try {
$pdo = new PDO($dsn, $database_user, $database_pass, $opt);
}
catch (PDOException $e) {
?>
<center style='font-family: "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;'>Connection to database failed.<br /><br />The following error was reported:<br/> <?=$e->getMessage();?></center>
<?php
exit;
}
+function pdo_exception_handler($e) {
+ if ($e instanceof PDOException) {
+ $_SESSION['return'][] = array(
+ 'type' => '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) {
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
if (!isset($_SESSION['mailcow_locale']) && !isset($_COOKIE['mailcow_locale'])) {
if ($DETECT_LANGUAGE && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$header_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
foreach ($AVAILABLE_LANGUAGES as $available_lang) {
if ($header_lang == $available_lang) {
$_SESSION['mailcow_locale'] = strtolower(trim($header_lang));
}
}
}
else {
$_SESSION['mailcow_locale'] = strtolower(trim($DEFAULT_LANG));
}
}
if (isset($_COOKIE['mailcow_locale'])) {
$_SESSION['mailcow_locale'] = $_COOKIE['mailcow_locale'];
}
if (isset($_GET['lang']) && in_array($_GET['lang'], $AVAILABLE_LANGUAGES)) {
$_SESSION['mailcow_locale'] = $_GET['lang'];
setcookie("mailcow_locale", $_GET['lang'], time()+30758400); // one year
}
require_once $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.en.php';
include $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.'.$_SESSION['mailcow_locale'].'.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailbox.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.customize.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.domain_admin.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quarantine.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';
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';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.docker.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/init_db.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.inc.php';
init_db_schema();
if (isset($_SESSION['mailcow_cc_role'])) {
set_acl();
}
$UI_TEXTS = customize('get', 'ui_texts');
diff --git a/data/web/inc/sessions.inc.php b/data/web/inc/sessions.inc.php
index fe1cdfa2..a3b81407 100644
--- a/data/web/inc/sessions.inc.php
+++ b/data/web/inc/sessions.inc.php
@@ -1,97 +1,97 @@
<?php
// Start session
ini_set("session.cookie_httponly", 1);
ini_set('session.gc_maxlifetime', $SESSION_LIFETIME);
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == "https") {
ini_set("session.cookie_secure", 1);
$IS_HTTPS = true;
}
elseif (isset($_SERVER['HTTPS'])) {
ini_set("session.cookie_secure", 1);
$IS_HTTPS = true;
}
else {
$IS_HTTPS = false;
}
// session_set_cookie_params($SESSION_LIFETIME, '/', '', $IS_HTTPS, true);
session_start();
if (!isset($_SESSION['CSRF']['TOKEN'])) {
$_SESSION['CSRF']['TOKEN'] = bin2hex(random_bytes(32));
}
// Set session UA
if (!isset($_SESSION['SESS_REMOTE_UA'])) {
$_SESSION['SESS_REMOTE_UA'] = $_SERVER['HTTP_USER_AGENT'];
}
// API
if (!empty($_SERVER['HTTP_X_API_KEY'])) {
$stmt = $pdo->prepare("SELECT `username`, `allow_from` FROM `api` WHERE `api_key` = :api_key AND `active` = '1';");
$stmt->execute(array(
':api_key' => preg_replace('/[^A-Z0-9-]/i', '', $_SERVER['HTTP_X_API_KEY'])
));
$api_return = $stmt->fetch(PDO::FETCH_ASSOC);
if (!empty($api_return['username'])) {
$remote = get_remote_ip(false);
$allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $api_return['allow_from']));
if (in_array($remote, $allow_from)) {
$_SESSION['mailcow_cc_username'] = $api_return['username'];
$_SESSION['mailcow_cc_role'] = 'admin';
$_SESSION['mailcow_cc_api'] = true;
}
}
}
// Update session cookie
// setcookie(session_name() ,session_id(), time() + $SESSION_LIFETIME);
// Check session
function session_check() {
if ($_SESSION['mailcow_cc_api'] === true) {
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'
);
return false;
}
if (!empty($_POST)) {
if ($_SESSION['CSRF']['TOKEN'] != $_POST['csrf_token']) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'warning',
'msg' => 'session_token'
);
return false;
}
unset($_POST['csrf_token']);
$_SESSION['CSRF']['TOKEN'] = bin2hex(random_bytes(32));
$_SESSION['CSRF']['TIME'] = time();
}
return true;
}
if (isset($_SESSION['mailcow_cc_role']) && session_check() === false) {
$_POST = array();
$_FILES = array();
}
// Handle logouts
if (isset($_POST["logout"])) {
if (isset($_SESSION["dual-login"])) {
$_SESSION["mailcow_cc_username"] = $_SESSION["dual-login"]["username"];
$_SESSION["mailcow_cc_role"] = $_SESSION["dual-login"]["role"];
unset($_SESSION["dual-login"]);
header("Location: /mailbox.php");
exit();
}
else {
session_regenerate_id(true);
session_unset();
session_destroy();
session_write_close();
header("Location: /");
}
}
diff --git a/data/web/js/api.js b/data/web/js/api.js
index 3f9bc4b7..2e770f7b 100644
--- a/data/web/js/api.js
+++ b/data/web/js/api.js
@@ -1,288 +1,307 @@
$(document).ready(function() {
function is_active(elem) {
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('<button class="btn btn-default btn-sm" disabled>' + loading_text + '</a>');
+ }
$(elem).text(loading_text);
$(elem).attr('data-submitted', '1');
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };
$(document).on("keydown", disableF5);
return false;
}
}
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
// Collect values of input fields with name "multi_select" and same data-id to js array multi_data[data-id]
var multi_data = [];
$(document).on('change', 'input[name=multi_select]:checkbox', function() {
if ($(this).is(':checked') && $(this).data('id')) {
var id = $(this).data('id');
if (typeof multi_data[id] == "undefined") {
multi_data[id] = [];
}
multi_data[id].push($(this).val());
}
else {
var id = $(this).data('id');
multi_data[id].splice($.inArray($(this).val(), multi_data[id]),1);
}
});
// Select checkbox by click on parent tr
$(document).on('click', 'tbody>tr', function(e) {
if(e.target.tagName.toLowerCase() === 'button') {
e.stopPropagation();
}
else if(e.target.tagName.toLowerCase() === 'a') {
e.stopPropagation();
}
else if (e.target.type == "checkbox") {
e.stopPropagation();
}
else {
var checkbox = $(this).find(':checkbox');
checkbox.trigger('click');
}
});
// Select or deselect all checkboxes with same data-id
$(document).on('click', '#toggle_multi_select_all', function(e) {
e.preventDefault();
id = $(this).data("id");
var all_checkboxes = $("input[data-id=" + id + "]:enabled");
all_checkboxes.prop("checked", !all_checkboxes.prop("checked")).change();
});
// General API edit actions
$(document).on('click', '#edit_selected', function(e) {
e.preventDefault();
var id = $(this).data('id');
var api_url = $(this).data('api-url');
var api_attr = $(this).data('api-attr');
if (typeof $(this).data('api-reload-window') !== 'undefined') {
api_reload_window = $(this).data('api-reload-window');
} else {
api_reload_window = true;
}
// If clicked element #edit_selected is in a form with the same data-id as the button,
// we merge all input fields by {"name":"value"} into api-attr
if ($(this).closest("form").data('id') == id) {
var invalid = false;
$(this).closest("form").find('select, textarea, input').each(function() {
if ($(this).prop('required')) {
if (!$(this).val() && $(this).prop('disabled') === false) {
invalid = true;
$(this).addClass('inputMissingAttr');
} else {
$(this).removeClass('inputMissingAttr');
}
}
if ($(this).attr("max")) {
if (Number($(this).val()) > Number($(this).attr("max"))) {
invalid = true;
$(this).addClass('inputMissingAttr');
} else {
if ($(this).attr("min")) {
if (Number($(this).val()) < Number($(this).attr("min"))) {
invalid = true;
$(this).addClass('inputMissingAttr');
} else {
$(this).removeClass('inputMissingAttr');
}
}
}
}
});
if (!invalid) {
var attr_to_merge = $(this).closest("form").serializeObject();
var api_attr = $.extend(api_attr, attr_to_merge)
} else {
return false;
}
}
// alert(JSON.stringify(api_attr));
// If clicked element #edit_selected has data-item attribute, it is added to "items"
if (typeof $(this).data('item') !== 'undefined') {
var id = $(this).data('id');
if (typeof multi_data[id] == "undefined") {
multi_data[id] = [];
}
multi_data[id].splice($.inArray($(this).data('item'), multi_data[id]), 1);
multi_data[id].push($(this).data('item'));
}
if (typeof multi_data[id] == "undefined") return;
api_items = multi_data[id];
for (var i in api_items) {
api_items[i] = decodeURIComponent(api_items[i]);
}
// alert(JSON.stringify(api_attr));
if (Object.keys(api_items).length !== 0) {
if (is_active($(this))) { return false; }
$.ajax({
type: "POST",
dataType: "json",
data: {
"items": JSON.stringify(api_items),
"attr": JSON.stringify(api_attr),
"csrf_token": csrf_token
},
url: '/api/v1/' + api_url,
jsonp: false,
complete: function(data) {
var response = (data.responseText);
if (typeof response !== 'undefined' && response.length !== 0) {
response_obj = JSON.parse(response);
}
if (api_reload_window === true) {
window.location = window.location.href.split("#")[0];
}
}
});
}
});
// General API add actions
$(document).on('click', '#add_item', function(e) {
e.preventDefault();
var id = $(this).data('id');
var api_url = $(this).data('api-url');
var api_attr = $(this).data('api-attr');
if (typeof $(this).data('api-reload-window') !== 'undefined') {
api_reload_window = $(this).data('api-reload-window');
} else {
api_reload_window = true;
}
// If clicked button is in a form with the same data-id as the button,
// we merge all input fields by {"name":"value"} into api-attr
if ($(this).closest("form").data('id') == id) {
var invalid = false;
$(this).closest("form").find('select, textarea, input').each(function() {
if ($(this).prop('required')) {
if (!$(this).val() && $(this).prop('disabled') === false) {
invalid = true;
$(this).addClass('inputMissingAttr');
} else {
$(this).removeClass('inputMissingAttr');
}
}
if ($(this).attr("max")) {
if (Number($(this).val()) > Number($(this).attr("max"))) {
alert($(this).attr("max"))
invalid = true;
$(this).addClass('inputMissingAttr');
} else {
if ($(this).attr("min")) {
if (Number($(this).val()) < Number($(this).attr("min"))) {
invalid = true;
$(this).addClass('inputMissingAttr');
} else {
$(this).removeClass('inputMissingAttr');
}
}
}
}
});
if (!invalid) {
var attr_to_merge = $(this).closest("form").serializeObject();
var api_attr = $.extend(api_attr, attr_to_merge)
} else {
return false;
}
}
if (is_active($(this))) { return false; }
// alert(JSON.stringify(api_attr));
$.ajax({
type: "POST",
dataType: "json",
data: {
"attr": JSON.stringify(api_attr),
"csrf_token": csrf_token
},
url: '/api/v1/' + api_url,
jsonp: false,
complete: function(data) {
var response = (data.responseText);
if (typeof response !== 'undefined' && response.length !== 0) {
response_obj = JSON.parse(response);
- if (response_obj.type == 'success') {
+ unset = true;
+ $.each(response_obj, function(i, v) {
+ if (v.type == "danger") {
+ unset = false;
+ }
+ });
+ if (unset === true) {
+ unset = null;
$('form').formcache('clear');
+ $('form').formcache('destroy');
+ var i = localStorage.length;
+ while(i--) {
+ var key = localStorage.key(i);
+ if(/formcache/.test(key)) {
+ localStorage.removeItem(key);
+ }
+ }
}
else {
var add_modal = $('.modal.in').attr('id');
localStorage.setItem("add_modal", add_modal);
}
}
if (api_reload_window === true) {
window.location = window.location.href.split("#")[0];
}
}
});
});
// General API delete actions
$(document).on('click', '#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"
if (typeof $(this).data('item') !== 'undefined') {
var id = $(this).data('id');
if (typeof multi_data[id] == "undefined") {
multi_data[id] = [];
}
multi_data[id].splice($.inArray($(this).data('item'), multi_data[id]), 1);
multi_data[id].push($(this).data('item'));
}
if (typeof $(this).data('text') !== 'undefined') {
$("#DeleteText").empty();
$("#DeleteText").text($(this).data('text'));
}
if (typeof multi_data[id] == "undefined" || multi_data[id] == "") return;
data_array = multi_data[id];
api_url = $(this).data('api-url');
$(document).on('show.bs.modal', '#ConfirmDeleteModal', function() {
$("#ItemsToDelete").empty();
for (var i in data_array) {
data_array[i] = decodeURIComponent(data_array[i]);
$("#ItemsToDelete").append("<li>" + data_array[i] + "</li>");
}
})
$('#ConfirmDeleteModal').modal({
backdrop: 'static',
keyboard: false
})
.one('click', '#IsConfirmed', function(e) {
$.ajax({
type: "POST",
dataType: "json",
cache: false,
data: {
"items": JSON.stringify(data_array),
"csrf_token": csrf_token
},
url: '/api/v1/' + api_url,
jsonp: false,
complete: function(data) {
window.location = window.location.href.split("#")[0];
}
});
})
.one('click', '#isCanceled', function(e) {
// Remove event handler to allow to close modal and restart dialog without multiple submits
$('#ConfirmDeleteModal').off();
$('#ConfirmDeleteModal').modal('hide');
});
});
});
\ No newline at end of file
diff --git a/data/web/js/debug.js b/data/web/js/debug.js
index 1a208628..37f45746 100644
--- a/data/web/js/debug.js
+++ b/data/web/js/debug.js
@@ -1,586 +1,588 @@
jQuery(function($){
if (localStorage.getItem("current_page") === null) {
var current_page = {};
} else {
var current_page = JSON.parse(localStorage.getItem('current_page'));
}
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
var entityMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};
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<B.length-1);return i.toFixed(1)+" "+B[e]}
$(".refresh_table").on('click', function(e) {
e.preventDefault();
var table_name = $(this).data('table');
$('#' + table_name).find("tr.footable-empty").remove();
draw_table = $(this).data('draw');
eval(draw_table + '()');
});
function table_log_ready(ft, name) {
heading = ft.$el.parents('.tab-pane').find('.panel-heading')
var ft_paging = ft.use(FooTable.Paging)
$(heading).children('.table-lines').text(function(){
return ft_paging.totalRows;
})
if (current_page[name]) {
ft_paging.goto(parseInt(current_page[name]))
}
}
function table_log_paging(ft, name) {
var ft_paging = ft.use(FooTable.Paging)
current_page[name] = ft_paging.current;
localStorage.setItem('current_page', JSON.stringify(current_page));
}
function draw_autodiscover_logs() {
ft_autodiscover_logs = FooTable.init('#autodiscover_log', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"ua","title":"User-Agent","style":{"min-width":"200px"}},
{"name":"user","title":"Username","style":{"min-width":"200px"}},
{"name":"service","title":"Service"},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/autodiscover/100',
jsonp: false,
error: function () {
console.log('Cannot draw autodiscover log table');
},
success: function (data) {
return process_table_data(data, 'autodiscover_log');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'autodiscover_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'autodiscover_logs');
}
}
});
}
function draw_postfix_logs() {
ft_postfix_logs = FooTable.init('#postfix_log', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"priority","title":lang.priority,"style":{"width":"80px"}},
{"name":"message","title":lang.message},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/postfix',
jsonp: false,
error: function () {
console.log('Cannot draw postfix log table');
},
success: function (data) {
return process_table_data(data, 'general_syslog');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'postfix_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'postfix_logs');
}
}
});
}
function draw_watchdog_logs() {
ft_watchdog_logs = FooTable.init('#watchdog_log', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"service","title":"Service"},
{"name":"trend","title":"Trend"},
{"name":"message","title":lang.message},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/watchdog',
jsonp: false,
error: function () {
console.log('Cannot draw watchdog log table');
},
success: function (data) {
return process_table_data(data, 'watchdog');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","connectors": false,"placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'postfix_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'postfix_logs');
}
}
});
}
function draw_api_logs() {
ft_api_logs = FooTable.init('#api_log', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"uri","title":"URI","style":{"width":"310px"}},
{"name":"method","title":"Method","style":{"width":"80px"}},
{"name":"remote","title":"IP","style":{"width":"80px"}},
{"name":"data","title":"Data","breakpoints": "all","style":{"word-break":"break-all"}},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/api',
jsonp: false,
error: function () {
console.log('Cannot draw api log table');
},
success: function (data) {
return process_table_data(data, 'apilog');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","connectors": false,"placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'api_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'api_logs');
}
}
});
}
function draw_ui_logs() {
ft_api_logs = FooTable.init('#ui_logs', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"type","title":"Type"},
+ {"name":"task","title":"Task"},
{"name":"user","title":"User"},
{"name":"role","title":"Role"},
{"name":"remote","title":"IP"},
{"name":"msg","title":lang.message},
{"name":"call","title":"Call","breakpoints": "all"},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/ui',
jsonp: false,
error: function () {
console.log('Cannot draw ui log table');
},
success: function (data) {
return process_table_data(data, 'mailcow_ui');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","connectors": false,"placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'ui_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'ui_logs');
}
}
});
}
function draw_acme_logs() {
ft_acme_logs = FooTable.init('#acme_log', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"message","title":lang.message},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/acme',
jsonp: false,
error: function () {
console.log('Cannot draw acme log table');
},
success: function (data) {
return process_table_data(data, 'general_syslog');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","connectors": false,"placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'acme_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'acme_logs');
}
}
});
}
function draw_netfilter_logs() {
ft_netfilter_logs = FooTable.init('#netfilter_log', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"priority","title":lang.priority,"style":{"width":"80px"}},
{"name":"message","title":lang.message},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/netfilter',
jsonp: false,
error: function () {
console.log('Cannot draw netfilter log table');
},
success: function (data) {
return process_table_data(data, 'general_syslog');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","connectors": false,"placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'netfilter_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'netfilter_logs');
}
}
});
}
function draw_sogo_logs() {
ft_sogo_logs = FooTable.init('#sogo_log', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"priority","title":lang.priority,"style":{"width":"80px"}},
{"name":"message","title":lang.message},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/sogo',
jsonp: false,
error: function () {
console.log('Cannot draw sogo log table');
},
success: function (data) {
return process_table_data(data, 'general_syslog');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","connectors": false,"placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'sogo_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'sogo_logs');
}
}
});
}
function draw_dovecot_logs() {
ft_dovecot_logs = FooTable.init('#dovecot_log', {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"priority","title":lang.priority,"style":{"width":"80px"}},
{"name":"message","title":lang.message},
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/dovecot',
jsonp: false,
error: function () {
console.log('Cannot draw dovecot log table');
},
success: function (data) {
return process_table_data(data, 'general_syslog');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","connectors": false,"placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'dovecot_logs');
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'dovecot_logs');
}
}
});
}
function rspamd_pie_graph() {
$.ajax({
url: '/api/v1/get/rspamd/actions',
success: function(graphdata){
graphdata.unshift(['Type', 'Count']);
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable(graphdata);
var options = {
is3D: true,
sliceVisibilityThreshold: 0,
pieSliceText: 'percentage',
chartArea: {
left: 0,
right: 0,
top: 20,
width: '100%',
height: '100%'
},
slices: {
0: { color: '#DC3023' },
1: { color: '#59ABE3' },
2: { color: '#FFA400' },
3: { color: '#FFA400' },
4: { color: '#26A65B' }
}
};
var chart = new google.visualization.PieChart(document.getElementById('rspamd_donut'));
chart.draw(data, options);
}
}
});
}
function draw_rspamd_history() {
ft_rspamd_history = FooTable.init('#rspamd_history', {
"columns": [
{"name":"unix_time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name": "ip","title": "IP address","breakpoints": "all","style": {"minWidth": 88}},
{"name": "sender_mime","title": "From","breakpoints": "xs sm md","style": {"minWidth": 100}},
{"name": "rcpt_mime","title": "To","breakpoints": "xs sm md","style": {"minWidth": 100}},
{"name": "subject","title": "Subject","breakpoints": "all","style": {"word-break": "break-all","minWidth": 150}},
{"name": "action","title": "Action","style": {"minwidth": 82}},
{"name": "score","title": "Score","style": {"maxWidth": 110},},
{"name": "symbols","title": "Symbols","breakpoints": "all",},
{"name": "size","title": "Msg size","breakpoints": "all","style": {"minwidth": 50},"formatter": function(value){return humanFileSize(value);}},
{"name": "scan_time","title": "Scan time","breakpoints": "all","style": {"maxWidth": 72},},
{"name": "message-id","title": "ID","breakpoints": "all","style": {"minWidth": 130,"overflow": "hidden","textOverflow": "ellipsis","wordBreak": "break-all","whiteSpace": "normal"}},
{"name": "user","title": "Authenticated user","breakpoints": "xs sm md","style": {"minWidth": 100}}
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/logs/rspamd-history',
jsonp: false,
error: function () {
console.log('Cannot draw rspamd history table');
},
success: function (data) {
return process_table_data(data, 'rspamd_history');
}
}),
"empty": lang.empty,
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
"filtering": {"enabled": true,"delay": 1,"position": "left","connectors": false,"placeholder": lang.filter_table},
"sorting": {"enabled": true},
"on": {
"ready.ft.table": function(e, ft){
table_log_ready(ft, 'rspamd_history');
heading = ft.$el.parents('.tab-pane').find('.panel-heading')
$(heading).children('.table-lines').text(function(){
var ft_paging = ft.use(FooTable.Paging)
return ft_paging.totalRows;
})
rspamd_pie_graph();
},
"after.ft.paging": function(e, ft){
table_log_paging(ft, 'rspamd_history');
}
}
});
}
function process_table_data(data, table) {
if (table == 'rspamd_history') {
$.each(data, function (i, item) {
item.rcpt_mime = item.rcpt_mime.join(",&#8203;");
Object.keys(item.symbols).map(function(key) {
var sym = item.symbols[key];
if (sym.score <= 0) {
sym.score_formatted = '(<span class="text-success"><b>' + sym.score + '</b></span>)'
}
else {
sym.score_formatted = '(<span class="text-danger"><b>' + sym.score + '</b></span>)'
}
var str = '<strong>' + key + '</strong> ' + sym.score_formatted;
if (sym.options) {
str += ' [' + sym.options.join(",") + "]";
}
item.symbols[key].str = str;
});
item.symbols = Object.keys(item.symbols).
map(function(key) {
return item.symbols[key];
}).sort(function(e1, e2) {
return Math.abs(e1.score) < Math.abs(e2.score);
}).map(function(e) {
return e.str;
}).join("<br>\n");
var scan_time = item.time_real.toFixed(3) + ' / ' + item.time_virtual.toFixed(3);
item.scan_time = {
"options": {
"sortValue": item.time_real
},
"value": scan_time
};
if (item.action === 'clean' || item.action === 'no action') {
item.action = "<div class='label label-success'>" + item.action + "</div>";
} else if (item.action === 'rewrite subject' || item.action === 'add header' || item.action === 'probable spam') {
item.action = "<div class='label label-warning'>" + item.action + "</div>";
} else if (item.action === 'spam' || item.action === 'reject') {
item.action = "<div class='label label-danger'>" + item.action + "</div>";
} else {
item.action = "<div class='label label-info'>" + item.action + "</div>";
}
var score_content;
if (item.score < item.required_score) {
score_content = "[ <span class='text-success'>" + item.score.toFixed(2) + " / " + item.required_score + "</span> ]";
} else {
score_content = "[ <span class='text-danger'>" + item.score.toFixed(2) + " / " + item.required_score + "</span> ]";
}
item.score = {
"options": {
"sortValue": item.score
},
"value": score_content
};
if (item.user == null) {
item.user = "none";
}
});
} else if (table == 'autodiscover_log') {
$.each(data, function (i, item) {
item.ua = '<span style="font-size:small">' + item.ua + '</span>';
if (item.service == "activesync") {
item.service = '<span class="label label-info">ActiveSync</span>';
}
else if (item.service == "imap") {
item.service = '<span class="label label-success">IMAP, SMTP, Cal-/CardDAV</span>';
}
else {
item.service = '<span class="label label-danger">' + item.service + '</span>';
}
});
} else if (table == 'watchdog') {
$.each(data, function (i, item) {
if (item.message == null) {
item.message = 'Health level: ' + item.lvl + '% (' + item.hpnow + '/' + item.hptotal + ')';
if (item.hpdiff < 0) {
item.trend = '<span class="label label-danger"><span class="glyphicon glyphicon-arrow-down"></span> ' + item.hpdiff + '</span>';
}
else if (item.hpdiff == 0) {
item.trend = '<span class="label label-info"><span class="glyphicon glyphicon-arrow-right"></span> ' + item.hpdiff + '</span>';
}
else {
item.trend = '<span class="label label-success"><span class="glyphicon glyphicon-arrow-up"></span> ' + item.hpdiff + '</span>';
}
}
else {
item.trend = '';
item.service = '';
}
});
} else if (table == 'mailcow_ui') {
$.each(data, function (i, item) {
if (item === null) { return true; }
item.user = escapeHtml(item.user);
+ item.task = '<code>' + item.task + '</code>';
item.type = '<span class="label label-' + item.type + '">' + item.type + '</span>';
});
} else if (table == 'general_syslog') {
$.each(data, function (i, item) {
if (item === null) { return true; }
item.message = escapeHtml(item.message);
var danger_class = ["emerg", "alert", "crit", "err"];
var warning_class = ["warning", "warn"];
var info_class = ["notice", "info", "debug"];
if (jQuery.inArray(item.priority, danger_class) !== -1) {
item.priority = '<span class="label label-danger">' + item.priority + '</span>';
} else if (jQuery.inArray(item.priority, warning_class) !== -1) {
item.priority = '<span class="label label-warning">' + item.priority + '</span>';
} else if (jQuery.inArray(item.priority, info_class) !== -1) {
item.priority = '<span class="label label-info">' + item.priority + '</span>';
}
});
} else if (table == 'apilog') {
$.each(data, function (i, item) {
if (item === null) { return true; }
if (item.method == 'GET') {
item.method = '<span class="label label-success">' + item.method + '</span>';
} else if (item.method == 'POST') {
item.method = '<span class="label label-warning">' + item.method + '</span>';
}
});
}
return data
};
$('.add_log_lines').on('click', function (e) {
e.preventDefault();
var log_table= $(this).data("table")
var new_nrows = $(this).data("nrows")
var post_process = $(this).data("post-process")
var log_url = $(this).data("log-url")
if (log_table === undefined || new_nrows === undefined || post_process === undefined || log_url === undefined) {
console.log("no data-table or data-nrows or log_url or data-post-process attr found");
return;
}
if (ft = FooTable.get($('#' + log_table))) {
var heading = ft.$el.parents('.tab-pane').find('.panel-heading')
var ft_paging = ft.use(FooTable.Paging)
var load_rows = (ft_paging.totalRows + 1) + '-' + (ft_paging.totalRows + new_nrows)
$.get('/api/v1/get/logs/' + log_url + '/' + load_rows).then(function(data){
if (data.length === undefined) { mailcow_alert_box(lang.no_new_rows, "info"); return; }
var rows = process_table_data(data, post_process);
var rows_now = (ft_paging.totalRows + data.length);
$(heading).children('.table-lines').text(rows_now)
mailcow_alert_box(data.length + lang.additional_rows, "success");
ft.rows.load(rows, true);
});
}
})
// Initial table drawings
draw_postfix_logs();
draw_autodiscover_logs();
draw_dovecot_logs();
draw_sogo_logs();
draw_watchdog_logs();
draw_acme_logs();
draw_api_logs();
draw_ui_logs();
draw_netfilter_logs();
draw_rspamd_history();
$(window).resize(function () {
var timer;
clearTimeout(timer);
timer = setTimeout(function () {
rspamd_pie_graph();
}, 500);
});
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var target = $(e.target).attr("href");
if ((target == '#tab-rspamd-history')) {
rspamd_pie_graph();
}
});
});
diff --git a/data/web/js/mailbox.js b/data/web/js/mailbox.js
index 7d25c3f1..072eea63 100644
--- a/data/web/js/mailbox.js
+++ b/data/web/js/mailbox.js
@@ -1,871 +1,872 @@
$(document).ready(function() {
FooTable.domainFilter = FooTable.Filtering.extend({
construct: function(instance){
this._super(instance);
var domain_list = [];
$.ajax({
dataType: 'json',
'async': false,
url: '/api/v1/get/domain/all',
jsonp: false,
error: function () {
domain_list.push('Cannot read domain list');
},
success: function (data) {
$.each(data, function (i, item) {
domain_list.push(item.domain_name);
});
}
});
this.domains = domain_list;
this.def = 'All Domains';
this.$domain = null;
},
$create: function(){
this._super();
var self = this,
$form_grp = $('<div/>', {'class': 'form-group'})
.append($('<label/>', {'class': 'sr-only', text: 'Domain'}))
.prependTo(self.$form);
self.$domain = $('<select/>', { 'class': 'form-control' })
.on('change', {self: self}, self._onDomainDropdownChanged)
.append($('<option/>', {text: self.def}))
.appendTo($form_grp);
$.each(self.domains, function(i, domain){
self.$domain.append($('<option/>').text(domain));
});
},
_onDomainDropdownChanged: function(e){
var self = e.data.self,
selected = $(this).val();
if (selected !== self.def){
self.addFilter('domain', selected, ['domain']);
} else {
self.removeFilter('domain');
}
self.filter();
},
draw: function(){
this._super();
var domain = this.find('domain');
if (domain instanceof FooTable.Filter){
this.$domain.val(domain.query.val());
} else {
this.$domain.val(this.def);
}
$(this.$domain).closest("select").selectpicker();
}
});
// Auto-fill domain quota when adding new domain
auto_fill_quota = function(domain) {
$.get("/api/v1/get/domain/" + domain, function(data){
var result = $.parseJSON(JSON.stringify(data));
max_new_mailbox_quota = ( result.max_new_mailbox_quota / 1048576);
if (max_new_mailbox_quota != '0') {
$("#quotaBadge").html('max. ' + max_new_mailbox_quota + ' MiB');
$('#addInputQuota').attr({"disabled": false, "value": "", "type": "number", "max": max_new_mailbox_quota});
$('#addInputQuota').val(max_new_mailbox_quota);
}
else {
$("#quotaBadge").html('max. ' + max_new_mailbox_quota + ' MiB');
$('#addInputQuota').attr({"disabled": true, "value": "", "type": "text", "value": "n/a"});
$('#addInputQuota').val(max_new_mailbox_quota);
}
});
}
$('#addSelectDomain').on('change', function() {
auto_fill_quota($('#addSelectDomain').val());
});
auto_fill_quota($('#addSelectDomain').val());
$(".generate_password").click(function( event ) {
event.preventDefault();
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);
});
$(".goto_checkbox").click(function( event ) {
$("form[data-id='add_alias'] .goto_checkbox").not(this).prop('checked', false);
if ($("form[data-id='add_alias'] .goto_checkbox:checked").length > 0) {
$('#textarea_alias_goto').prop('disabled', true);
}
else {
$("#textarea_alias_goto").removeAttr('disabled');
}
});
$('#addAliasModal').on('show.bs.modal', function(e) {
if ($("form[data-id='add_alias'] .goto_checkbox:checked").length > 0) {
$('#textarea_alias_goto').prop('disabled', true);
}
else {
$("#textarea_alias_goto").removeAttr('disabled');
}
});
// Log modal
$('#syncjobLogModal').on('show.bs.modal', function(e) {
var syncjob_id = $(e.relatedTarget).data('syncjob-id');
$.ajax({
url: '/inc/ajax/syncjob_logs.php',
data: { id: syncjob_id },
dataType: 'text',
success: function(data){
$(e.currentTarget).find('#logText').text(data);
},
error: function(xhr, status, error) {
$(e.currentTarget).find('#logText').text(xhr.responseText);
}
});
});
// Log modal
$('#dnsInfoModal').on('show.bs.modal', function(e) {
var domain = $(e.relatedTarget).data('domain');
$('.dns-modal-body').html('<center><span style="font-size:18pt;margin:50px" class="glyphicon glyphicon-refresh glyphicon-spin"></span></center>');
$.ajax({
url: '/inc/ajax/dns_diagnostics.php',
data: { domain: domain },
dataType: 'text',
success: function(data){
$('.dns-modal-body').html(data);
},
error: function(xhr, status, error) {
$('.dns-modal-body').html(xhr.responseText);
}
});
});
// Sieve data modal
$('#sieveDataModal').on('show.bs.modal', function(e) {
var sieveScript = $(e.relatedTarget).data('sieve-script');
$(e.currentTarget).find('#sieveDataText').html('<pre style="font-size:14px;line-height:1.1">' + sieveScript + '</pre>');
});
// Set line numbers for textarea
$("#script_data").numberedtextarea({allowTabChar: true});
// Disable submit button on script change
$('#script_data').on('keyup', function() {
$('#add_filter_btns > #add_item').attr({"disabled": true});
$('#validation_msg').html('-');
});
// Validate script data
$("#validate_sieve").click(function( event ) {
event.preventDefault();
var script = $('#script_data').val();
$.ajax({
dataType: 'jsonp',
url: "/inc/ajax/sieve_validation.php",
type: "get",
data: { script: script },
complete: function(data) {
var response = (data.responseText);
response_obj = JSON.parse(response);
if (response_obj.type == "success") {
$('#add_filter_btns > #add_item').attr({"disabled": false});
}
mailcow_alert_box(response_obj.msg, response_obj.type);
},
});
});
// $(document).on('DOMNodeInserted', '#prefilter_table', function () {
// $("#active-script").closest('td').css('background-color','#b0f0a0');
// $("#inactive-script").closest('td').css('background-color','#b0f0a0');
// });
});
jQuery(function($){
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
var entityMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
};
function escapeHtml(string) {
return String(string).replace(/[&<>"'`=\/]/g, function (s) {
return entityMap[s];
});
}
if (localStorage.getItem("current_page") === null) {
var current_page = {};
} else {
var current_page = JSON.parse(localStorage.getItem('current_page'));
}
// http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
function validateEmail(email) {
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
// Calculation human readable file sizes
function humanFileSize(bytes) {
if(Math.abs(bytes) < 1024) {
return bytes + ' B';
}
var units = ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
var u = -1;
do {
bytes /= 1024;
++u;
} while(Math.abs(bytes) >= 1024 && u < units.length - 1);
return bytes.toFixed(1)+' '+units[u];
}
function unix_time_format(tm) {
var date = new Date(tm ? tm * 1000 : 0);
return date.toLocaleString();
}
$(".refresh_table").on('click', function(e) {
e.preventDefault();
var table_name = $(this).data('table');
$('#' + table_name).find("tr.footable-empty").remove();
draw_table = $(this).data('draw');
eval(draw_table + '()');
});
function table_mailbox_ready(ft, name) {
heading = ft.$el.parents('.tab-pane').find('.panel-heading')
var ft_paging = ft.use(FooTable.Paging)
$(heading).children('.table-lines').text(function(){
return ft_paging.totalRows;
})
if (current_page[name]) {
ft_paging.goto(parseInt(current_page[name]))
}
}
function paging_mailbox_after(ft, name) {
var ft_paging = ft.use(FooTable.Paging)
current_page[name] = ft_paging.current;
localStorage.setItem('current_page', JSON.stringify(current_page));
}
function draw_domain_table() {
ft_domain_table = FooTable.init('#domain_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"domain_name","title":lang.domain,"style":{"width":"250px"}},
{"name":"aliases","title":lang.aliases,"breakpoints":"xs sm"},
{"name":"mailboxes","title":lang.mailboxes},
{"name":"quota","style":{"whiteSpace":"nowrap"},"title":lang.domain_quota,"formatter": function(value){
res = value.split("/");
return humanFileSize(res[0]) + " / " + humanFileSize(res[1]);
},
"sortValue": function(value){
res = value.split("/");
return Number(res[0]);
},
},
{"name":"max_quota_for_mbox","title":lang.mailbox_quota,"breakpoints":"xs sm","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"}
],
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/domain/all',
jsonp: false,
error: function (data) {
console.log('Cannot draw domain table');
},
success: function (data) {
$.each(data, function (i, item) {
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;
item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
item.chkbox = '<input type="checkbox" data-id="domain" name="multi_select" value="' + encodeURIComponent(item.domain_name) + '" />';
item.action = '<div class="btn-group">';
if (role == "admin") {
item.action += '<a href="/edit.php?domain=' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-domain" data-api-url="delete/domain" data-item="' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>';
}
else {
item.action += '<a href="/edit.php?domain=' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>';
}
item.action += '<a href="#dnsInfoModal" class="btn btn-xs btn-info" data-toggle="modal" data-domain="' + encodeURIComponent(item.domain_name) + '"><span class="glyphicon glyphicon-question-sign"></span> DNS</a></div>';
});
}
}),
"empty": lang.empty,
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'domain_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'domain_table');
}
}
});
}
function draw_mailbox_table() {
ft_mailbox_table = FooTable.init('#mailbox_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"username","style":{"word-break":"break-all","min-width":"120px"},"title":lang.username},
{"name":"name","title":lang.fname,"style":{"word-break":"break-all","min-width":"120px"},"breakpoints":"xs sm"},
{"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
{"name":"quota","style":{"whiteSpace":"nowrap"},"title":lang.domain_quota,"formatter": function(value){
res = value.split("/");
return humanFileSize(res[0]) + " / " + humanFileSize(res[1]);
},
"sortValue": function(value){
res = value.split("/");
return Number(res[0]);
},
},
{"name":"spam_aliases","filterable": false,"title":lang.spam_aliases,"breakpoints":"xs sm md"},
{"name":"in_use","filterable": false,"type":"html","title":lang.in_use,"sortValue": function(value){
return Number($(value).find(".progress-bar").attr('aria-valuenow'));
},
},
{"name":"messages","filterable": false,"title":lang.msg_num,"breakpoints":"xs sm md"},
{"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"}
],
"empty": lang.empty,
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/mailbox/all',
jsonp: false,
error: function () {
console.log('Cannot draw mailbox table');
},
success: function (data) {
$.each(data, function (i, item) {
item.quota = item.quota_used + "/" + item.quota;
item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
item.chkbox = '<input type="checkbox" data-id="mailbox" name="multi_select" value="' + encodeURIComponent(item.username) + '" />';
if (role == "admin") {
item.action = '<div class="btn-group">' +
'<a href="/edit.php?mailbox=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-mailbox" data-api-url="delete/mailbox" data-item="' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>' +
'</div>';
}
else {
item.action = '<div class="btn-group">' +
'<a href="/edit.php?mailbox=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-mailbox" data-api-url="delete/mailbox" data-item="' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'</div>';
}
item.in_use = '<div class="progress">' +
'<div class="progress-bar progress-bar-' + item.percent_class + ' role="progressbar" aria-valuenow="' + item.percent_in_use + '" aria-valuemin="0" aria-valuemax="100" ' +
'style="min-width:2em;width:' + item.percent_in_use + '%">' + item.percent_in_use + '%' + '</div></div>';
item.username = escapeHtml(item.username);
});
}
}),
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"components": {
"filtering": FooTable.domainFilter
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'mailbox_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'mailbox_table');
}
}
});
}
function draw_resource_table() {
ft_resource_table = FooTable.init('#resource_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"description","title":lang.description,"style":{"width":"250px"}},
{"name":"kind","title":lang.kind},
{"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
{"name":"multiple_bookings","filterable": false,"style":{"maxWidth":"150px","width":"140px"},"title":lang.multiple_bookings,"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":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
],
"empty": lang.empty,
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/resource/all',
jsonp: false,
error: function () {
console.log('Cannot draw resource table');
},
success: function (data) {
$.each(data, function (i, item) {
if (item.multiple_bookings == '0') {
item.multiple_bookings = '<span id="active-script" class="label label-success">' + lang.booking_0_short + '</span>';
} else if (item.multiple_bookings == '-1') {
item.multiple_bookings = '<span id="active-script" class="label label-warning">' + lang.booking_lt0_short + '</span>';
} else {
item.multiple_bookings = '<span id="active-script" class="label label-danger">' + lang.booking_custom_short + ' (' + item.multiple_bookings + ')</span>';
}
item.action = '<div class="btn-group">' +
'<a href="/edit.php?resource=' + encodeURIComponent(item.name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-resource" data-api-url="delete/resource" data-item="' + item.name + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'</div>';
item.chkbox = '<input type="checkbox" data-id="resource" name="multi_select" value="' + encodeURIComponent(item.name) + '" />';
item.name = escapeHtml(item.name);
});
}
}),
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"components": {
"filtering": FooTable.domainFilter
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'resource_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'resource_table');
}
}
});
}
function draw_bcc_table() {
ft_bcc_table = FooTable.init('#bcc_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
{"name":"type","title":lang.bcc_type},
{"name":"local_dest","title":lang.bcc_local_dest},
{"name":"bcc_dest","title":lang.bcc_destinations},
{"name":"domain","title":lang.domain,"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":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
],
"empty": lang.empty,
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/bcc/all',
jsonp: false,
error: function () {
console.log('Cannot draw bcc table');
},
success: function (data) {
$.each(data, function (i, item) {
item.action = '<div class="btn-group">' +
'<a href="/edit.php?bcc=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-bcc" data-api-url="delete/bcc" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'</div>';
item.chkbox = '<input type="checkbox" data-id="bcc" name="multi_select" value="' + item.id + '" />';
item.local_dest = escapeHtml(item.local_dest);
item.bcc_dest = escapeHtml(item.bcc_dest);
if (item.type == 'sender') {
item.type = '<span id="active-script" class="label label-success">Sender</span>';
} else {
item.type = '<span id="inactive-script" class="label label-warning">Recipient</span>';
}
});
}
}),
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'bcc_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'bcc_table');
}
}
});
}
function draw_recipient_map_table() {
ft_recipient_map_table = FooTable.init('#recipient_map_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
{"name":"recipient_map_old","title":lang.recipient_map_old},
{"name":"recipient_map_new","title":lang.recipient_map_new},
{"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":(role == "admin" ? lang.action : ""),"breakpoints":"xs sm"}
],
"empty": lang.empty,
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/recipient_map/all',
jsonp: false,
error: function () {
console.log('Cannot draw recipient map table');
},
success: function (data) {
if (role == "admin") {
$.each(data, function (i, item) {
item.recipient_map_old = escapeHtml(item.recipient_map_old);
item.recipient_map_new = escapeHtml(item.recipient_map_new);
item.action = '<div class="btn-group">' +
'<a href="/edit.php?recipient_map=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-recipient_map" data-api-url="delete/recipient_map" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'</div>';
item.chkbox = '<input type="checkbox" data-id="recipient_map" name="multi_select" value="' + item.id + '" />';
});
}
}
}),
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'recipient_map_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'recipient_map_table');
}
}
});
}
function draw_alias_table() {
ft_alias_table = FooTable.init('#alias_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
+ {"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
{"sorted": true,"name":"address","title":lang.alias,"style":{"width":"250px"}},
{"name":"goto","title":lang.target_address},
{"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
{"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"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"}
],
"empty": lang.empty,
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/alias/all',
jsonp: false,
error: function () {
console.log('Cannot draw alias table');
},
success: function (data) {
$.each(data, function (i, item) {
item.action = '<div class="btn-group">' +
- '<a href="/edit.php?alias=' + encodeURIComponent(item.address) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
- '<a href="#" id="delete_selected" data-id="single-alias" data-api-url="delete/alias" data-item="' + encodeURIComponent(item.address) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
+ '<a href="/edit.php?alias=' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+ '<a href="#" id="delete_selected" data-id="single-alias" data-api-url="delete/alias" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'</div>';
- item.chkbox = '<input type="checkbox" data-id="alias" name="multi_select" value="' + encodeURIComponent(item.address) + '" />';
+ item.chkbox = '<input type="checkbox" data-id="alias" name="multi_select" value="' + encodeURIComponent(item.id) + '" />';
item.goto = escapeHtml(item.goto.replace(/,/g, " "));
if (item.is_catch_all == 1) {
item.address = '<div class="label label-default">Catch-All</div> ' + escapeHtml(item.address);
}
else {
item.address = escapeHtml(item.address);
}
if (item.goto == "null@localhost") {
item.goto = '⤷ <span style="font-size:12px" class="glyphicon glyphicon-trash" aria-hidden="true"></span>';
}
else if (item.goto == "spam@localhost") {
item.goto = '<span class="label label-danger">Learn as spam</span>';
}
else if (item.goto == "ham@localhost") {
item.goto = '<span class="label label-success">Learn as ham</span>';
}
if (item.in_primary_domain !== "") {
item.domain = "↳ " + item.domain + " (" + item.in_primary_domain + ")";
}
});
}
}),
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"components": {
"filtering": FooTable.domainFilter
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'alias_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'alias_table');
}
}
});
}
function draw_aliasdomain_table() {
ft_aliasdomain_table = FooTable.init('#aliasdomain_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"alias_domain","title":lang.alias,"style":{"width":"250px"}},
{"name":"target_domain","title":lang.target_domain},
{"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"title":lang.active},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
],
"empty": lang.empty,
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/alias-domain/all',
jsonp: false,
error: function () {
console.log('Cannot draw alias domain table');
},
success: function (data) {
$.each(data, function (i, item) {
item.action = '<div class="btn-group">' +
'<a href="/edit.php?aliasdomain=' + encodeURIComponent(item.alias_domain) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-alias-domain" data-api-url="delete/alias-domain" data-item="' + encodeURIComponent(item.alias_domain) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'<a href="#dnsInfoModal" class="btn btn-xs btn-info" data-toggle="modal" data-domain="' + encodeURIComponent(item.alias_domain) + '"><span class="glyphicon glyphicon-question-sign"></span> DNS</a></div>' +
'</div>';
item.chkbox = '<input type="checkbox" data-id="alias-domain" name="multi_select" value="' + encodeURIComponent(item.alias_domain) + '" />';
});
}
}),
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'aliasdomain_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'aliasdomain_table');
}
}
});
}
function draw_sync_job_table() {
ft_syncjob_table = FooTable.init('#sync_job_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
{"name":"user2","title":lang.owner},
{"name":"server_w_port","title":"Server","breakpoints":"xs","style":{"word-break":"break-all"}},
{"name":"exclude","title":lang.excludes,"breakpoints":"all"},
{"name":"mins_interval","title":lang.mins_interval,"breakpoints":"all"},
{"name":"last_run","title":lang.last_run,"breakpoints":"sm"},
{"name":"log","title":"Log"},
{"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active},
{"name":"is_running","filterable": false,"style":{"maxWidth":"120px","width":"100px"},"title":lang.status},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
],
"empty": lang.empty,
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/syncjobs/all/no_log',
jsonp: false,
error: function () {
console.log('Cannot draw sync job table');
},
success: function (data) {
$.each(data, function (i, item) {
item.log = '<a href="#syncjobLogModal" data-toggle="modal" data-syncjob-id="' + encodeURIComponent(item.id) + '">Open logs</a>'
item.user2 = escapeHtml(item.user2);
if (!item.exclude > 0) {
item.exclude = '-';
} else {
item.exclude = '<code>' + item.exclude + '</code>';
}
item.server_w_port = escapeHtml(item.user1) + '@' + item.host1 + ':' + item.port1;
item.action = '<div class="btn-group">' +
'<a href="/edit.php?syncjob=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'</div>';
item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
if (item.is_running == 1) {
item.is_running = '<span id="active-script" class="label label-success">' + lang.running + '</span>';
} else {
item.is_running = '<span id="inactive-script" class="label label-warning">' + lang.waiting + '</span>';
}
if (!item.last_run > 0) {
item.last_run = lang.waiting;
}
});
}
}),
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'sync_job_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'sync_job_table');
}
}
});
}
function draw_filter_table() {
ft_filter_table = FooTable.init('#filter_table', {
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"},
{"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
{"name":"active","style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
{"name":"filter_type","style":{"maxWidth":"80px","width":"80px"},"title":"Type"},
{"sorted": true,"name":"username","title":lang.owner,"style":{"maxWidth":"550px","width":"350px"}},
{"name":"script_desc","title":lang.description,"breakpoints":"xs"},
{"name":"script_data","title":"Script","breakpoints":"all"},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
],
"empty": lang.empty,
"rows": $.ajax({
dataType: 'json',
url: '/api/v1/get/filters/all',
jsonp: false,
error: function () {
console.log('Cannot draw filter table');
},
success: function (data) {
$.each(data, function (i, item) {
if (item.active_int == 1) {
item.active = '<span id="active-script" class="label label-success">' + lang.active + '</span>';
} else {
item.active = '<span id="inactive-script" class="label label-warning">' + lang.inactive + '</span>';
}
item.script_data = '<pre style="margin:0px">' + escapeHtml(item.script_data) + '</pre>'
item.filter_type = '<div class="label label-default">' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '</div>'
item.action = '<div class="btn-group">' +
'<a href="/edit.php?filter=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
'<a href="#" id="delete_selected" data-id="single-filter" data-api-url="delete/filter" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
'</div>';
item.chkbox = '<input type="checkbox" data-id="filter_item" name="multi_select" value="' + item.id + '" />'
});
}
}),
"paging": {
"enabled": true,
"limit": 5,
"size": pagination_size
},
"filtering": {
"enabled": true,
"delay": 100,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
},
"sorting": {
"enabled": true
},
"on": {
"ready.ft.table": function(e, ft){
table_mailbox_ready(ft, 'filter_table');
},
"after.ft.paging": function(e, ft){
paging_mailbox_after(ft, 'filter_table');
}
}
});
};
draw_domain_table();
draw_mailbox_table();
draw_resource_table();
draw_alias_table();
draw_aliasdomain_table();
draw_sync_job_table();
draw_filter_table();
draw_bcc_table();
draw_recipient_map_table();
});
diff --git a/data/web/json_api.php b/data/web/json_api.php
index c05e2b2c..bbf452f9 100644
--- a/data/web/json_api.php
+++ b/data/web/json_api.php
@@ -1,1007 +1,1007 @@
<?php
/*
edit/alias => POST data:
{
address: {a, b, c}, (where a, b, c represent alias addresses)
active: 1 (0 or 1)
}
delete/alias => POST data:
{
address: {a, b, c}, (where a, b, c represent alias addresses)
}
*/
header('Content-Type: application/json');
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
error_reporting(0);
function api_log($_data) {
global $redis;
$data_var = array();
foreach ($_data as $data => &$value) {
if ($data == 'csrf_token') {
continue;
}
if ($value = json_decode($value, true)) {
unset($value["csrf_token"]);
foreach ($value as $key => &$val) {
if(preg_match("/pass/i", $key)) {
$val = '*';
}
}
$value = json_encode($value);
}
$data_var[] = $data . "='" . $value . "'";
}
try {
$log_line = array(
'time' => time(),
'uri' => $_SERVER['REQUEST_URI'],
'method' => $_SERVER['REQUEST_METHOD'],
'remote' => get_remote_ip(),
'data' => implode(', ', $data_var)
);
$redis->lPush('API_LOG', json_encode($log_line));
}
catch (RedisException $e) {
- $_SESSION['return'] = array(
+ $_SESSION['return'][] = array(
'type' => 'danger',
'msg' => 'Redis: '.$e
);
return false;
}
}
api_log($_POST);
if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_username'])) {
if (isset($_GET['query'])) {
$query = explode('/', $_GET['query']);
$action = (isset($query[0])) ? $query[0] : null;
$category = (isset($query[1])) ? $query[1] : null;
$object = (isset($query[2])) ? $query[2] : null;
$extra = (isset($query[3])) ? $query[3] : null;
$request_incomplete = json_encode(array(
'type' => 'error',
'msg' => 'Cannot find attributes in post data'
));
switch ($action) {
case "add":
function process_add_return($return) {
$generic_failure = json_encode(array(
'type' => 'error',
'msg' => 'Cannot add item'
));
$generic_success = json_encode(array(
'type' => 'success',
'msg' => 'Task completed'
));
if ($return === false) {
echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_failure;
}
else {
echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_success;
}
}
if (!isset($_POST['attr'])) {
echo $request_incomplete;
exit;
}
else {
$attr = (array)json_decode($_POST['attr'], true);
unset($attr['csrf_token']);
}
switch ($category) {
case "time_limited_alias":
process_add_return(mailbox('add', 'time_limited_alias', $attr));
break;
case "relayhost":
process_add_return(relayhost('add', $attr));
break;
case "rsetting":
process_add_return(rsettings('add', $attr));
break;
case "mailbox":
process_add_return(mailbox('add', 'mailbox', $attr));
break;
case "domain":
process_add_return(mailbox('add', 'domain', $attr));
break;
case "resource":
process_add_return(mailbox('add', 'resource', $attr));
break;
case "alias":
process_add_return(mailbox('add', 'alias', $attr));
break;
case "filter":
process_add_return(mailbox('add', 'filter', $attr));
break;
case "domain-policy":
process_add_return(policy('add', 'domain', $attr));
break;
case "mailbox-policy":
process_add_return(policy('add', 'mailbox', $attr));
break;
case "alias-domain":
process_add_return(mailbox('add', 'alias_domain', $attr));
break;
case "fwdhost":
process_add_return(fwdhost('add', $attr));
break;
case "dkim":
process_add_return(dkim('add', $attr));
break;
case "dkim_import":
process_add_return(dkim('import', $attr));
break;
case "domain-admin":
process_add_return(domain_admin('add', $attr));
break;
case "syncjob":
process_add_return(mailbox('add', 'syncjob', $attr));
break;
case "bcc":
process_add_return(bcc('add', $attr));
break;
case "recipient_map":
process_add_return(recipient_map('add', $attr));
break;
}
break;
case "get":
function process_get_return($data) {
echo (!isset($data) || empty($data)) ? '{}' : json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
}
switch ($category) {
case "rspamd":
switch ($object) {
case "actions":
$curl = curl_init();
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/rspamd-sock/rspamd.sock');
curl_setopt($curl, CURLOPT_URL,"http://rspamd/stat");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($curl);
if ($data) {
$return = array();
$stats_array = json_decode($data, true)['actions'];
$stats_array['soft reject'] = $stats_array['soft reject'] + $stats_array['greylist'];
unset($stats_array['greylist']);
foreach ($stats_array as $action => $count) {
$return[] = array($action, $count);
}
echo json_encode($return, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
}
elseif (!isset($data) || empty($data)) {
echo '{}';
}
break;
}
break;
case "domain":
switch ($object) {
case "all":
$domains = mailbox('get', 'domains');
if (!empty($domains)) {
foreach ($domains as $domain) {
if ($details = mailbox('get', 'domain_details', $domain)) {
$data[] = $details;
}
else {
continue;
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
$data = mailbox('get', 'domain_details', $object);
process_get_return($data);
break;
}
break;
case "relayhost":
switch ($object) {
case "all":
$relayhosts = relayhost('get');
if (!empty($relayhosts)) {
foreach ($relayhosts as $relayhost) {
if ($details = relayhost('details', $relayhost['id'])) {
$data[] = $details;
}
else {
continue;
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
$data = relayhost('details', $object);
process_get_return($data);
break;
}
break;
case "rsetting":
switch ($object) {
case "all":
$rsettings = rsettings('get');
if (!empty($rsettings)) {
foreach ($rsettings as $rsetting) {
if ($details = rsettings('details', $rsetting['id'])) {
$data[] = $details;
}
else {
continue;
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
$data = rsetting('details', $object);
process_get_return($data);
break;
}
break;
case "oauth2-client":
switch ($object) {
case "all":
$clients = oauth2('get', 'clients');
if (!empty($clients)) {
foreach ($clients as $client) {
if ($details = oauth2('details', 'client', $client)) {
$data[] = $details;
}
else {
continue;
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
$data = oauth2('details', 'client', $object);
process_get_return($data);
break;
}
break;
case "logs":
switch ($object) {
case "dovecot":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('dovecot-mailcow', $extra);
}
else {
$logs = get_logs('dovecot-mailcow');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "netfilter":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('netfilter-mailcow', $extra);
}
else {
$logs = get_logs('netfilter-mailcow');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "postfix":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('postfix-mailcow', $extra);
}
else {
$logs = get_logs('postfix-mailcow');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "autodiscover":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('autodiscover-mailcow', $extra);
}
else {
$logs = get_logs('autodiscover-mailcow');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "sogo":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('sogo-mailcow', $extra);
}
else {
$logs = get_logs('sogo-mailcow');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "ui":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('mailcow-ui', $extra);
}
else {
$logs = get_logs('mailcow-ui');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "watchdog":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('watchdog-mailcow', $extra);
}
else {
$logs = get_logs('watchdog-mailcow');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "acme":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('acme-mailcow', $extra);
}
else {
$logs = get_logs('acme-mailcow');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "api":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('api-mailcow', $extra);
}
else {
$logs = get_logs('api-mailcow');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
case "rspamd-history":
// 0 is first record, so empty is fine
if (isset($extra)) {
$extra = preg_replace('/[^\d\-]/i', '', $extra);
$logs = get_logs('rspamd-history', $extra);
}
else {
$logs = get_logs('rspamd-history');
}
echo (isset($logs) && !empty($logs)) ? json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) : '{}';
break;
}
break;
case "mailbox":
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 = mailbox('get', 'mailbox_details', $mailbox)) {
$data[] = $details;
}
else {
continue;
}
}
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
$data = mailbox('get', 'mailbox_details', $object);
process_get_return($data);
break;
}
break;
case "syncjobs":
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) {
$syncjobs = mailbox('get', 'syncjobs', $mailbox);
if (!empty($syncjobs)) {
foreach ($syncjobs as $syncjob) {
if (isset($extra)) {
$details = mailbox('get', 'syncjob_details', $syncjob, explode(',', $extra));
}
else {
$details = mailbox('get', 'syncjob_details', $syncjob);
}
if ($details) {
$data[] = $details;
}
else {
continue;
}
}
}
}
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
$syncjobs = mailbox('get', 'syncjobs', $object);
if (!empty($syncjobs)) {
foreach ($syncjobs as $syncjob) {
if (isset($extra)) {
$details = mailbox('get', 'syncjob_details', $syncjob, explode(',', $extra));
}
else {
$details = mailbox('get', 'syncjob_details', $syncjob);
}
if ($details) {
$data[] = $details;
}
else {
continue;
}
}
}
process_get_return($data);
break;
}
break;
case "active-user-sieve":
if (isset($object)) {
$sieve_filter = mailbox('get', 'active_user_sieve', $object);
if (!empty($sieve_filter)) {
$data[] = $sieve_filter;
}
}
process_get_return($data);
break;
case "filters":
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) {
$filters = mailbox('get', 'filters', $mailbox);
if (!empty($filters)) {
foreach ($filters as $filter) {
if ($details = mailbox('get', 'filter_details', $filter)) {
$data[] = $details;
}
else {
continue;
}
}
}
}
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
$filters = mailbox('get', 'filters', $object);
if (!empty($filters)) {
foreach ($filters as $filter) {
if ($details = mailbox('get', 'filter_details', $filter)) {
$data[] = $details;
}
else {
continue;
}
}
}
process_get_return($data);
break;
}
break;
case "bcc":
switch ($object) {
case "all":
$bcc_items = bcc('get');
if (!empty($bcc_items)) {
foreach ($bcc_items as $bcc_item) {
if ($details = bcc('details', $bcc_item)) {
$data[] = $details;
}
else {
continue;
}
}
}
process_get_return($data);
break;
default:
$data = bcc('details', $object);
if (!empty($data)) {
$data[] = $details;
}
process_get_return($data);
break;
}
break;
case "recipient_map":
switch ($object) {
case "all":
$recipient_map_items = recipient_map('get');
if (!empty($recipient_map_items)) {
foreach ($recipient_map_items as $recipient_map_item) {
if ($details = recipient_map('details', $recipient_map_item)) {
$data[] = $details;
}
else {
continue;
}
}
}
process_get_return($data);
break;
default:
$data = recipient_map('details', $object);
if (!empty($data)) {
$data[] = $details;
}
process_get_return($data);
break;
}
break;
case "policy_wl_mailbox":
switch ($object) {
default:
$data = policy('get', 'mailbox', $object)['whitelist'];
process_get_return($data);
break;
}
break;
case "policy_bl_mailbox":
switch ($object) {
default:
$data = policy('get', 'mailbox', $object)['blacklist'];
process_get_return($data);
break;
}
break;
case "policy_wl_domain":
switch ($object) {
default:
$data = policy('get', 'domain', $object)['whitelist'];
process_get_return($data);
break;
}
break;
case "policy_bl_domain":
switch ($object) {
default:
$data = policy('get', 'domain', $object)['blacklist'];
process_get_return($data);
break;
}
break;
case "time_limited_aliases":
switch ($object) {
default:
$data = mailbox('get', 'time_limited_aliases', $object);
process_get_return($data);
break;
}
break;
case "resource":
switch ($object) {
case "all":
$domains = mailbox('get', 'domains');
if (!empty($domains)) {
foreach ($domains as $domain) {
$resources = mailbox('get', 'resources', $domain);
if (!empty($resources)) {
foreach ($resources as $resource) {
if ($details = mailbox('get', 'resource_details', $resource)) {
$data[] = $details;
}
else {
continue;
}
}
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
$data = mailbox('get', 'resource_details', $object);
process_get_return($data);
break;
}
break;
case "fwdhost":
switch ($object) {
case "all":
process_get_return(fwdhost('get'));
break;
default:
process_get_return(fwdhost('details', $object));
break;
}
break;
case "quarantine":
// "all" will not print details
switch ($object) {
case "all":
process_get_return(quarantine('get'));
break;
default:
process_get_return(quarantine('details', $object));
break;
}
break;
case "alias-domain":
switch ($object) {
case "all":
$alias_domains = mailbox('get', 'alias_domains');
if (!empty($alias_domains)) {
foreach ($alias_domains as $alias_domain) {
if ($details = mailbox('get', 'alias_domain_details', $alias_domain)) {
$data[] = $details;
}
else {
continue;
}
}
}
process_get_return($data);
break;
default:
process_get_return(mailbox('get', 'alias_domain_details', $object));
break;
}
break;
case "alias":
switch ($object) {
case "all":
$domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
if (!empty($domains)) {
foreach ($domains as $domain) {
$aliases = mailbox('get', 'aliases', $domain);
if (!empty($aliases)) {
foreach ($aliases as $alias) {
if ($details = mailbox('get', 'alias_details', $alias)) {
$data[] = $details;
}
else {
continue;
}
}
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
process_get_return(mailbox('get', 'alias_details', $object));
break;
}
break;
case "domain-admin":
switch ($object) {
case "all":
$domain_admins = domain_admin('get');
if (!empty($domain_admins)) {
foreach ($domain_admins as $domain_admin) {
if ($details = domain_admin('details', $domain_admin)) {
$data[] = $details;
}
else {
continue;
}
}
process_get_return($data);
}
else {
echo '{}';
}
break;
default:
process_get_return(domain_admin('details', $object));
break;
}
break;
case "u2f-registration":
header('Content-Type: application/javascript');
if (($_SESSION["mailcow_cc_role"] == "admin" || $_SESSION["mailcow_cc_role"] == "domainadmin") && $_SESSION["mailcow_cc_username"] == $object) {
list($req, $sigs) = $u2f->getRegisterData(get_u2f_registrations($object));
$_SESSION['regReq'] = json_encode($req);
$_SESSION['regSigs'] = json_encode($sigs);
echo 'var req = ' . json_encode($req) . ';';
echo 'var registeredKeys = ' . json_encode($sigs) . ';';
echo 'var appId = req.appId;';
echo 'var registerRequests = [{version: req.version, challenge: req.challenge}];';
}
else {
return;
}
break;
case "u2f-authentication":
header('Content-Type: application/javascript');
if (isset($_SESSION['pending_mailcow_cc_username']) && $_SESSION['pending_mailcow_cc_username'] == $object) {
$auth_data = $u2f->getAuthenticateData(get_u2f_registrations($object));
$challenge = $auth_data[0]->challenge;
$appId = $auth_data[0]->appId;
foreach ($auth_data as $each) {
$key = array(); // Empty array
$key['version'] = $each->version;
$key['keyHandle'] = $each->keyHandle;
$registeredKey[] = $key;
}
$_SESSION['authReq'] = json_encode($auth_data);
echo 'var appId = "' . $appId . '";';
echo 'var challenge = ' . json_encode($challenge) . ';';
echo 'var registeredKeys = ' . json_encode($registeredKey) . ';';
}
else {
return;
}
break;
default:
echo '{}';
break;
}
break;
case "delete":
function process_delete_return($return) {
$generic_failure = json_encode(array(
'type' => 'error',
'msg' => 'Cannot delete item'
));
$generic_success = json_encode(array(
'type' => 'success',
'msg' => 'Task completed'
));
if ($return === false) {
echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_failure;
}
else {
echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_success;
}
}
if (!isset($_POST['items'])) {
echo $request_incomplete;
exit;
}
else {
$items = (array)json_decode($_POST['items'], true);
}
switch ($category) {
case "alias":
- process_delete_return(mailbox('delete', 'alias', array('address' => $items)));
+ process_delete_return(mailbox('delete', 'alias', array('id' => $items)));
break;
case "relayhost":
process_delete_return(relayhost('delete', array('id' => $items)));
break;
case "rsetting":
process_delete_return(rsettings('delete', array('id' => $items)));
break;
case "syncjob":
process_delete_return(mailbox('delete', 'syncjob', array('id' => $items)));
break;
case "filter":
process_delete_return(mailbox('delete', 'filter', array('id' => $items)));
break;
case "qitem":
process_delete_return(quarantine('delete', array('id' => $items)));
break;
case "bcc":
process_delete_return(bcc('delete', array('id' => $items)));
break;
case "recipient_map":
process_delete_return(recipient_map('delete', array('id' => $items)));
break;
case "fwdhost":
process_delete_return(fwdhost('delete', array('forwardinghost' => $items)));
break;
case "dkim":
process_delete_return(dkim('delete', array('domains' => $items)));
break;
case "domain":
file_put_contents('/tmp/dssaa', $items);
process_delete_return(mailbox('delete', 'domain', array('domain' => $items)));
break;
case "alias-domain":
process_delete_return(mailbox('delete', 'alias_domain', array('alias_domain' => $items)));
break;
case "mailbox":
process_delete_return(mailbox('delete', 'mailbox', array('username' => $items)));
break;
case "resource":
process_delete_return(mailbox('delete', 'resource', array('name' => $items)));
break;
case "mailbox-policy":
process_delete_return(policy('delete', 'mailbox', array('prefid' => $items)));
break;
case "domain-policy":
process_delete_return(policy('delete', 'domain', array('prefid' => $items)));
break;
case "time_limited_alias":
process_delete_return(mailbox('delete', 'time_limited_alias', array('address' => $items)));
break;
case "eas_cache":
process_delete_return(mailbox('delete', 'eas_cache', array('username' => $items)));
break;
case "domain-admin":
process_delete_return(domain_admin('delete', array('username' => $items)));
break;
}
break;
case "edit":
function process_edit_return($return) {
$generic_failure = json_encode(array(
'type' => 'error',
'msg' => 'Cannot edit item'
));
$generic_success = json_encode(array(
'type' => 'success',
'msg' => 'Task completed'
));
if ($return === false) {
echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_failure;
}
else {
echo isset($_SESSION['return']) ? json_encode($_SESSION['return']) : $generic_success;
}
}
if (!isset($_POST['attr'])) {
echo $request_incomplete;
exit;
}
else {
$attr = (array)json_decode($_POST['attr'], true);
unset($attr['csrf_token']);
$items = isset($_POST['items']) ? (array)json_decode($_POST['items'], true) : null;
}
switch ($category) {
case "bcc":
process_edit_return(bcc('edit', array_merge(array('id' => $items), $attr)));
break;
case "oauth2-client":
process_edit_return(oauth2('edit', 'client', array_merge(array('id' => $items), $attr)));
break;
case "recipient_map":
process_edit_return(recipient_map('edit', array_merge(array('id' => $items), $attr)));
break;
case "alias":
- process_edit_return(mailbox('edit', 'alias', array_merge(array('address' => $items), $attr)));
+ process_edit_return(mailbox('edit', 'alias', array_merge(array('id' => $items), $attr)));
break;
case "app_links":
process_edit_return(customize('edit', 'app_links', $attr));
break;
case "relayhost":
process_edit_return(relayhost('edit', array_merge(array('id' => $items), $attr)));
break;
case "rsetting":
process_edit_return(rsettings('edit', array_merge(array('id' => $items), $attr)));
break;
case "delimiter_action":
process_edit_return(mailbox('edit', 'delimiter_action', array_merge(array('username' => $items), $attr)));
break;
case "tls_policy":
process_edit_return(mailbox('edit', 'tls_policy', array_merge(array('username' => $items), $attr)));
break;
case "qitem":
process_edit_return(quarantine('edit', array_merge(array('id' => $items), $attr)));
break;
case "quarantine":
process_edit_return(quarantine('edit', $attr));
break;
case "time_limited_alias":
process_edit_return(mailbox('edit', 'time_limited_alias', array_merge(array('address' => $items), $attr)));
break;
case "mailbox":
process_edit_return(mailbox('edit', 'mailbox', array_merge(array('username' => $items), $attr)));
break;
case "syncjob":
process_edit_return(mailbox('edit', 'syncjob', array_merge(array('id' => $items), $attr)));
break;
case "filter":
process_edit_return(mailbox('edit', 'filter', array_merge(array('id' => $items), $attr)));
break;
case "resource":
process_edit_return(mailbox('edit', 'resource', array_merge(array('name' => $items), $attr)));
break;
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)));
break;
case "alias-domain":
process_edit_return(mailbox('edit', 'alias_domain', array_merge(array('alias_domain' => $items), $attr)));
break;
case "spam-score":
process_edit_return(mailbox('edit', 'spam_score', array_merge(array('username' => $items), $attr)));
break;
case "domain-admin":
process_edit_return(domain_admin('edit', array_merge(array('username' => $items), $attr)));
break;
case "fwdhost":
process_edit_return(fwdhost('edit', array_merge(array('fwdhost' => $items), $attr)));
break;
case "fail2ban":
process_edit_return(fail2ban('edit', array_merge(array('network' => $items), $attr)));
break;
case "ui_texts":
process_edit_return(customize('edit', 'ui_texts', $attr));
break;
case "self":
if ($_SESSION['mailcow_cc_role'] == "domainadmin") {
process_edit_return(domain_admin('edit', $attr));
}
elseif ($_SESSION['mailcow_cc_role'] == "user") {
process_edit_return(edit_user_account($attr));
}
elseif ($_SESSION['mailcow_cc_role'] == "admin") {
process_edit_return(edit_admin_account($attr));
}
break;
}
break;
}
}
}
diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php
index fc582cb5..3125f2ae 100644
--- a/data/web/lang/lang.de.php
+++ b/data/web/lang/lang.de.php
@@ -1,632 +1,643 @@
<?php
/*
* German language file
*/
$lang['footer']['loading'] = 'Einen Moment bitte...';
$lang['header']['restart_sogo'] = 'SOGo neustarten';
$lang['header']['restart_netfilter'] = 'Netfilter neustarten';
$lang['footer']['restart_container'] = 'Container neustarten';
$lang['footer']['restart_now'] = 'Jetzt neustarten';
$lang['footer']['restarting_container'] = 'Container wird neugestartet, bitte warten...';
$lang['footer']['restart_container_info'] = '<b>Wichtig:</b> Der Neustart eines Containers kann eine Weile in Anspruch nehmen.';
$lang['footer']['confirm_delete'] = 'Löschen bestätigen';
$lang['footer']['delete_these_items'] = 'Sind Sie sicher, dass die Änderungen an Elementen mit folgender ID durchgeführt werden sollen?';
$lang['footer']['delete_now'] = 'Jetzt löschen';
$lang['footer']['cancel'] = 'Abbrechen';
$lang['danger']['mysql_error'] = "MySQL Fehler: %s";
$lang['danger']['redis_error'] = "Redis Fehler: %s";
$lang['danger']['unknown_tfa_method'] = "Unbekannte TFA Methode";
$lang['danger']['totp_verification_failed'] = "TOTP Verifizierung fehlgeschlagen";
$lang['success']['verified_totp_login'] = "TOTP Anmeldung verifiziert";
$lang['danger']['u2f_verification_failed'] = "U2F Verifizierung fehlgeschlagen: %s";
$lang['success']['verified_u2f_login'] = "U2F Anmeldung verifiziert";
$lang['success']['verified_yotp_login'] = "Yubico OTP Anmeldung verifiziert";
$lang['danger']['yotp_verification_failed'] = "Yubico OTP Verifizierung fehlgeschlagen: %s";
$lang['danger']['ip_list_empty'] = "Liste erlaubter IPs darf nicht leer sein";
$lang['danger']['rspamd_ui_pw_length'] = "Rspamd UI Passwort muss mindestens 6 Zeichen lang sein";
$lang['success']['rspamd_ui_pw_set'] = "Rspamd UI Passwort wurde gesetzt";
$lang['danger']['unknown'] = "Ein unbekannter Fehler trat auf";
$lang['danger']['malformed_username'] = "Benutzername hat falsches Format";
$lang['info']['awaiting_tfa_confirmation'] = "Warte auf TFA Verifizierung";
$lang['success']['logged_in_as'] = "Eingeloggt als %s";
$lang['danger']['login_failed'] = "Anmeldung fehlgeschlagen";
$lang['danger']['set_acl_failed'] = "ACL konnte nicht gesetzt werden";
$lang['danger']['no_user_defined'] = "Kein Benutzer definiert";
$lang['danger']['script_empty'] = "Script darf nicht leer sein";
$lang['danger']['sieve_error'] = "Sieve Parser: %s";
$lang['danger']['value_missing'] = "Bitte alle Felder ausfüllen";
$lang['danger']['filter_type'] = "Falscher Filtertyp";
$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']['deleted_syncjobs'] = "Syncjobs gelöscht: %s";
+$lang['success']['deleted_syncjob'] = "Syncjobs ID %s gelöscht";
$lang['success']['delete_filters'] = "Filter gelöscht: %s";
+$lang['success']['delete_filter'] = "Filter ID %s wurde gelöscht";
$lang['danger']['invalid_bcc_map_type'] = "Ungültiger BCC Map-Typ";
$lang['danger']['bcc_empty'] = "BCC Ziel darf nicht leer sein";
-$lang['danger']['bcc_must_be_email'] = "BCC Map muss eine gültige E-Mail-Adresse sein";
+$lang['danger']['bcc_must_be_email'] = "BCC Map %s ist keine gültige E-Mail-Adresse";
$lang['danger']['bcc_exists'] = "Ein BCC Map Eintrag %s existiert bereits als Typ %s";
$lang['success']['bcc_saved'] = "BCC Map Eintrag wurde gespeichert";
-$lang['success']['bcc_edited'] = "BCC Map Eintrag wurde editiert";
+$lang['success']['bcc_edited'] = "BCC Map Eintrag %s wurde editiert";
$lang['success']['bcc_deleted'] = "BCC Map Einträge gelöscht: %s";
$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 ist ungültig";
+$lang['danger']['settings_map_invalid'] = "Regel ID %s ist ungültig";
$lang['danger']['settings_map_removed'] = "Regeln wurden entfernt: %s";
$lang['danger']['invalid_host'] = "Ungültiger Host: %s";
-$lang['danger']['relayhost_invalid'] = "Relayhost ist ungültig";
+$lang['danger']['relayhost_invalid'] = "Relayhost %s ist ungültig";
$lang['success']['saved_settings'] = "Regel wurde gespeichert";
-$lang['danger']['dkim_domain_or_sel_invalid'] = 'DKIM-Domain oder -Selector nicht korrekt';
+$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['danger']['access_denied'] = 'Zugriff verweigert oder unvollständige/ungültige Daten';
-$lang['danger']['domain_invalid'] = 'Domainname ist ungültig';
+$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';
$lang['danger']['object_is_not_numeric'] = 'Wert %s ist nicht numerisch';
$lang['success']['domain_added'] = 'Domain %s wurde angelegt';
$lang['success']['items_deleted'] = "Objekt(e) %s wurde(n) erfolgreich entfernt";
+$lang['success']['item_deleted'] = "Objekt %s wurde entfernt";
$lang['danger']['alias_empty'] = 'Alias-Adresse darf nicht leer sein';
$lang['danger']['goto_empty'] = 'Ziel-Adresse darf nicht leer sein';
$lang['danger']['policy_list_from_exists'] = 'Ein Eintrag mit diesem Wert existiert bereits';
$lang['danger']['policy_list_from_invalid'] = 'Eintrag hat ungültiges Format';
-$lang['danger']['alias_invalid'] = 'Alias-Adresse ist ungültig';
-$lang['danger']['goto_invalid'] = 'Ziel-Adresse ist ungültig';
+$lang['danger']['alias_invalid'] = 'Alias-Adresse %s ist ungültig';
+$lang['danger']['goto_invalid'] = 'Ziel-Adresse %s ist ungültig';
$lang['danger']['last_key'] = 'Letzter Key kann nicht gelöscht werden';
-$lang['danger']['alias_domain_invalid'] = 'Alias-Domain ist ungültig';
-$lang['danger']['target_domain_invalid'] = 'Ziel-Domain ist ungültig';
+$lang['danger']['alias_domain_invalid'] = 'Alias-Domain %s ist ungültig';
+$lang['danger']['target_domain_invalid'] = 'Ziel-Domain %s ist ungültig';
$lang['danger']['object_exists'] = 'Objekt %s existiert bereits';
$lang['danger']['domain_exists'] = 'Domain %s existiert bereits';
$lang['danger']['alias_goto_identical'] = 'Alias- und Ziel-Adresse dürfen nicht identisch sein';
-$lang['danger']['aliasd_targetd_identical'] = 'Alias-Domain darf nicht gleich Ziel-Domain sein';
+$lang['danger']['aliasd_targetd_identical'] = 'Alias-Domain darf nicht gleich Ziel-Domain sein: %s';
$lang['danger']['maxquota_empty'] = 'Max. Speicherplatz pro Mailbox darf nicht 0 sein.';
-$lang['success']['alias_added'] = 'Alias-Adresse(n) wurden angelegt';
+$lang['success']['alias_added'] = 'Alias-Adresse %s wurden angelegt';
$lang['success']['alias_modified'] = 'Änderungen an Alias %s wurden gespeichert';
$lang['success']['aliasd_modified'] = 'Änderungen an Alias-Domain %s wurden gespeichert';
$lang['success']['mailbox_modified'] = 'Änderungen an Mailbox %s wurden gespeichert';
$lang['success']['resource_modified'] = "Änderungen an Ressource %s wurden gespeichert";
$lang['success']['object_modified'] = "Änderungen an Objekt %s wurden gespeichert";
$lang['success']['f2b_modified'] = "Änderungen an Fail2ban Parametern wurden gespeichert";
-$lang['danger']['targetd_not_found'] = 'Ziel-Domain nicht gefunden';
+$lang['danger']['targetd_not_found'] = 'Ziel-Domain %s nicht gefunden';
$lang['success']['aliasd_added'] = 'Alias-Domain %s wurde angelegt';
$lang['success']['aliasd_modified'] = 'Änderungen an Alias-Domain %s wurden gespeichert';
$lang['success']['domain_modified'] = 'Änderungen an Domain %s wurden gespeichert';
$lang['success']['domain_admin_modified'] = 'Änderungen an Domain-Administrator %s wurden gespeichert';
$lang['success']['domain_admin_added'] = 'Domain-Administrator %s wurde angelegt';
$lang['success']['admin_modified'] = 'Änderungen am Administrator wurden gespeichert';
-$lang['danger']['username_invalid'] = 'Benutzername kann nicht verwendet werden';
+$lang['danger']['username_invalid'] = 'Benutzername %s kann nicht verwendet werden';
$lang['danger']['password_mismatch'] = 'Passwort-Wiederholung stimmt nicht überein';
$lang['danger']['password_complexity'] = 'Passwort entspricht nicht den Richtlinien';
$lang['danger']['password_empty'] = 'Passwort darf nicht leer sein';
$lang['danger']['login_failed'] = 'Anmeldung fehlgeschlagen';
$lang['danger']['mailbox_invalid'] = 'Mailboxname ist ungültig';
-$lang['danger']['resource_invalid'] = 'Ressourcenname ist ungültig';
-$lang['danger']['description_invalid'] = 'Ressourcenbeschreibung ist ungültig';
+$lang['danger']['resource_invalid'] = 'Ressourcenname %s ist ungültig';
+$lang['danger']['description_invalid'] = 'Ressourcenbeschreibung für %s ist ungültig';
$lang['danger']['is_alias'] = '%s lautet bereits eine Alias-Adresse';
$lang['danger']['is_alias_or_mailbox'] = "Eine Mailbox, ein Alias oder eine sich aus einer Alias-Domain ergebende Adresse mit dem Namen %s ist bereits vorhanden";
$lang['danger']['is_spam_alias'] = '%s lautet bereits eine Spam-Alias-Adresse';
$lang['danger']['quota_not_0_not_numeric'] = 'Speicherplatz muss numerisch und >= 0 sein';
$lang['danger']['domain_not_found'] = 'Domain %s nicht gefunden';
$lang['danger']['max_mailbox_exceeded'] = 'Anzahl an Mailboxen überschritten (%d von %d)';
$lang['danger']['max_alias_exceeded'] = 'Anzahl an Alias-Adressen überschritten';
$lang['danger']['mailbox_quota_exceeded'] = 'Speicherplatz überschreitet das Limit (max. %d MiB)';
$lang['danger']['mailbox_quota_left_exceeded'] = 'Nicht genügend Speicherplatz vorhanden (Speicherplatz anwendbar: %d MiB)';
$lang['success']['mailbox_added'] = 'Mailbox %s wurde angelegt';
$lang['success']['resource_added'] = 'Ressource %s wurde angelegt';
$lang['success']['domain_removed'] = 'Domain %s wurde entfernt';
$lang['success']['alias_removed'] = 'Alias-Adresse %s wurde entfernt';
$lang['success']['alias_domain_removed'] = 'Alias-Domain %s wurde entfernt';
$lang['success']['domain_admin_removed'] = 'Domain-Administrator %s wurde entfernt';
$lang['success']['mailbox_removed'] = 'Mailbox %s wurde entfernt';
$lang['success']['eas_reset'] = "ActiveSync Gerät des Benutzers %s wurden zurückgesetzt";
$lang['success']['resource_removed'] = 'Ressource %s wurde entfernt';
$lang['danger']['max_quota_in_use'] = 'Mailbox Speicherplatzlimit muss größer oder gleich %d MiB sein';
$lang['danger']['domain_quota_m_in_use'] = 'Domain Speicherplatzlimit muss größer oder gleich %d MiB sein';
$lang['danger']['mailboxes_in_use'] = 'Maximale Anzahl an Mailboxen muss größer oder gleich %d sein';
$lang['danger']['aliases_in_use'] = 'Maximale Anzahl an Aliassen muss größer oder gleich %d sein';
-$lang['danger']['sender_acl_invalid'] = 'Sender ACL Wert muss eine Adresse oder Domain sein';
+$lang['danger']['sender_acl_invalid'] = 'Sender ACL %s ist ungültig';
$lang['danger']['domain_not_empty'] = 'Kann nur leere Domains entfernen';
$lang['danger']['validity_missing'] = 'Bitte geben Sie eine Gültigkeitsdauer an';
$lang['user']['loading'] = "Lade...";
$lang['user']['force_pw_update'] = 'Das Passwort für diesen Benutzer <b>muss</b> geändert werden, damit die Zugriffssperre auf die Groupwarekomponenten wieder freigeschaltet wird.';
$lang['user']['active_sieve'] = "Aktiver Filter";
$lang['user']['show_sieve_filters'] = "Zeige aktiven Filter des Benutzers";
$lang['user']['no_active_filter'] = "Kein aktiver Filter vorhanden";
$lang['user']['messages'] = "Nachrichten";
$lang['user']['in_use'] = "Verwendet";
$lang['user']['user_change_fn'] = '';
$lang['user']['user_settings'] = 'Benutzereinstellungen';
$lang['user']['mailbox_details'] = 'Mailbox-Details';
$lang['user']['change_password'] = 'Passwort ändern';
$lang['user']['client_configuration'] = 'Konfigurationsanleitungen für E-Mail-Programme und Smartphones anzeigen';
$lang['user']['new_password'] = 'Neues Passwort';
$lang['user']['save_changes'] = 'Änderungen speichern';
$lang['user']['password_now'] = 'Aktuelles Passwort (Änderungen bestätigen)';
$lang['user']['new_password_repeat'] = 'Neues Passwort (Wiederholung)';
$lang['user']['new_password_description'] = 'Mindestanforderung: 6 Zeichen lang, Buchstaben und Zahlen.';
$lang['user']['spam_aliases'] = 'Temporäre E-Mail Aliasse';
$lang['user']['alias'] = 'Alias';
$lang['user']['shared_aliases'] = 'Geteilte Alias-Adressen';
$lang['user']['shared_aliases_desc'] = 'Geteilte Alias-Adressen werden nicht bei benutzerdefinierten Einstellungen wie die des Spam-Filters oder der Verschlüsselungsrichtlinie berücksichtigt. Entsprechende Spam-Filter können lediglich von einem Administrator vorgenommen werden.';
$lang['user']['direct_aliases'] = 'Direkte Alias-Adressen';
$lang['user']['direct_aliases_desc'] = 'Nur direkte Alias-Adressen werden für benutzerdefinierte Einstellungen berücksichtigt.';
$lang['user']['is_catch_all'] = 'Ist Catch-All Adresse für Domain(s)';
$lang['user']['aliases_also_send_as'] = 'Darf außerdem versenden als Benutzer';
$lang['user']['aliases_send_as_all'] = 'Absender für folgende Domains und zugehörige Alias-Domains nicht prüfen';
$lang['user']['alias_create_random'] = 'Zufälligen Alias generieren';
$lang['user']['alias_extend_all'] = 'Gültigkeit +1h';
$lang['user']['alias_valid_until'] = 'Gültig bis';
$lang['user']['alias_remove_all'] = 'Alle entfernen';
$lang['user']['alias_time_left'] = 'Zeit verbleibend';
$lang['user']['alias_full_date'] = 'd.m.Y, H:i:s T';
$lang['user']['alias_select_validity'] = 'Bitte Gültigkeit auswählen';
$lang['user']['sync_jobs'] = 'Sync Jobs';
$lang['user']['hour'] = 'Stunde';
$lang['user']['hours'] = 'Stunden';
$lang['user']['day'] = 'Tag';
$lang['user']['week'] = 'Woche';
$lang['user']['weeks'] = 'Wochen';
$lang['user']['spamfilter'] = 'Spamfilter';
$lang['admin']['spamfilter'] = 'Spamfilter';
$lang['user']['spamfilter_wl'] = 'Whitelist';
$lang['user']['spamfilter_wl_desc'] = 'Für E-Mail-Adressen, die vom Spamfilter <b>nicht</b> erfasst werden sollen. Die Verwendung von Wildcards ist gestattet. Ein Filter funktioniert lediglich für direkte nicht-"Catch All" Alias-Adressen (Alias-Adressen mit lediglich einer Mailbox als Ziel-Adresse) sowie die Mailbox-Adresse selbst.';
$lang['user']['spamfilter_bl'] = 'Blacklist';
$lang['user']['spamfilter_bl_desc'] = 'Für E-Mail-Adressen, die vom Spamfilter <b>immer</b> als Spam erfasst und abgelehnt werden. Die Verwendung von Wildcards ist gestattet. Ein Filter funktioniert lediglich für direkte nicht-"Catch All" Alias-Adressen (Alias-Adressen mit lediglich einer Mailbox als Ziel-Adresse) sowie die Mailbox-Adresse selbst.';
$lang['user']['spamfilter_table_rule'] = 'Regel';
$lang['user']['spamfilter_table_action'] = 'Aktion';
$lang['user']['spamfilter_table_empty'] = 'Keine Einträge vorhanden';
$lang['user']['spamfilter_table_remove'] = 'entfernen';
$lang['user']['spamfilter_table_add'] = 'Eintrag hinzufügen';
$lang['user']['spamfilter_behavior'] = 'Bewertung';
$lang['user']['spamfilter_default_score'] = 'Spam-Score:';
$lang['user']['spamfilter_green'] = 'Grün: Die Nachricht ist kein Spam';
$lang['user']['spamfilter_yellow'] = 'Gelb: Die Nachricht ist vielleicht Spam, wird als Spam markiert und in den Junk-Ordner verschoben';
$lang['user']['spamfilter_red'] = 'Rot: Die Nachricht ist eindeutig Spam und wird vom Server abgelehnt';
$lang['user']['spamfilter_default_score'] = 'Standardwert:';
$lang['user']['spamfilter_hint'] = 'Der erste Wert beschreibt den "low spam score", der zweite Wert den "high spam score".';
$lang['user']['spamfilter_table_domain_policy'] = "n.v. (Domainrichtlinie)";
$lang['user']['waiting'] = "Warte auf Ausführung";
$lang['user']['status'] = "Status";
$lang['user']['running'] = "Wird ausgeführt";
$lang['user']['tls_policy_warning'] = '<strong>Vorsicht:</strong> Entscheiden Sie sich unverschlüsselte Verbindungen abzulehnen, kann dies dazu führen, dass Kontakte Sie nicht mehr erreichen.<br>Nachrichten, die die Richtlinie nicht erfüllen, werden durch einen Hard-Fail im Mailsystem abgewiesen.<br>Diese Einstellung ist aktiv für die primäre Mailbox, für alle Alias-Adressen, die dieser Mailbox <b>direkt zugeordnet</b> sind (lediglich eine einzige Ziel-Adresse) und der Adressen, die sich aus Alias-Domains ergeben. Ausgeschlossen sind temporäre Aliasse ("Spam-Alias-Adressen"), Catch-All Alias-Adressen sowie Alias-Adressen mit mehreren Zielen.';
$lang['user']['tls_policy'] = 'Verschlüsselungsrichtlinie';
$lang['user']['tls_enforce_in'] = 'TLS eingehend erzwingen';
$lang['user']['tls_enforce_out'] = 'TLS ausgehend erzwingen';
$lang['user']['no_record'] = 'Kein Eintrag';
$lang['user']['tag_handling'] = 'Umgang mit getaggten E-Mails steuern';
$lang['user']['tag_in_subfolder'] = 'In Unterordner';
$lang['user']['tag_in_subject'] = 'In Betreff';
$lang['user']['tag_in_none'] = 'Nichts tun';
$lang['user']['tag_help_explain'] = 'Als Unterordner: Es wird ein Ordner mit dem Namen des Tags unterhalb der Inbox erstellt ("INBOX/Facebook").<br>
In Betreff: Der Name des Tags wird dem Betreff angefügt, etwa "[Facebook] Meine Neuigkeiten".';
$lang['user']['tag_help_example'] = 'Beispiel für eine getaggte E-Mail-Adresse: ich<b>+Facebook</b>@example.org';
$lang['user']['eas_reset'] = 'ActiveSync Geräte-Cache zurücksetzen';
$lang['user']['eas_reset_now'] = 'Jetzt zurücksetzen';
$lang['user']['eas_reset_help'] = 'In vielen Fällen kann ein ActiveSync Profil durch das Zurücksetzen des Caches repariert werden.<br><b>Vorsicht:</b> Alle Elemente werden erneut heruntergeladen!';
$lang['user']['encryption'] = 'Verschlüsselung';
$lang['user']['username'] = 'Benutzername';
$lang['user']['last_run'] = 'Letzte Ausführung';
$lang['user']['excludes'] = 'Ausschlüsse';
$lang['user']['interval'] = 'Intervall';
$lang['user']['active'] = 'Aktiv';
$lang['user']['action'] = 'Aktion';
$lang['user']['edit'] = 'Bearbeiten';
$lang['user']['remove'] = 'Entfernen';
$lang['user']['create_syncjob'] = 'Neuen Sync-Job erstellen';
$lang['start']['mailcow_apps_detail'] = 'Verwenden Sie mailcow Apps, um E-Mails abzurufen, Kalender- und Kontakte zu verwalten und vieles mehr.';
$lang['start']['mailcow_panel_detail'] = '<b>Domain-Administratoren</b> erstellen, verändern oder löschen Mailboxen, verwalten die Domäne und sehen sonstige Einstellungen ein.<br>
Als <b>Mailbox-Benutzer</b> erstellen Sie hier zeitlich limitierte Aliasse, ändern das Verhalten des Spamfilters, setzen ein neues Passwort und vieles mehr.';
$lang['start']['imap_smtp_server_auth_info'] = 'Bitte verwenden Sie Ihre vollständige E-Mail-Adresse sowie das PLAIN-Authentifizierungsverfahren.<br>
Ihre Anmeldedaten werden durch die obligatorische Verschlüsselung entgegen des Begriffes "PLAIN" nicht unverschlüsselt übertragen.';
$lang['start']['help'] = 'Hilfe ein-/ausblenden';
$lang['header']['mailcow_settings'] = 'Konfiguration';
$lang['header']['administration'] = 'Administration';
$lang['header']['mailboxes'] = 'Mailboxen';
$lang['header']['user_settings'] = 'Benutzereinstellungen';
$lang['mailbox']['booking_0'] = 'Immer als verfügbar anzeigen';
$lang['mailbox']['booking_lt0'] = 'Unbegrenzt, jedoch anzeigen, wenn gebucht';
$lang['mailbox']['booking_custom'] = 'Benutzerdefiniertes Limit';
$lang['mailbox']['booking_0_short'] = 'Immer verfügbar';
$lang['mailbox']['booking_lt0_short'] = 'Weiches Limit';
$lang['mailbox']['booking_custom_short'] = 'Hartes Limit';
$lang['mailbox']['domain'] = 'Domain';
$lang['mailbox']['spam_aliases'] = 'Temp. Alias';
$lang['mailbox']['alias'] = 'Alias';
$lang['mailbox']['aliases'] = 'Aliasse';
$lang['mailbox']['multiple_bookings'] = 'Mehrfachbuchen';
$lang['mailbox']['kind'] = 'Art';
$lang['mailbox']['description'] = 'Beschreibung';
$lang['mailbox']['resources'] = 'Ressourcen';
$lang['mailbox']['domains'] = 'Domains';
$lang['mailbox']['mailboxes'] = 'Mailboxen';
$lang['mailbox']['mailbox_quota'] = 'Max. Größe einer Mailbox';
$lang['mailbox']['domain_quota'] = 'Gesamtspeicher';
$lang['mailbox']['active'] = 'Aktiv';
$lang['mailbox']['action'] = 'Aktion';
$lang['mailbox']['backup_mx'] = 'Backup MX';
$lang['mailbox']['domain_aliases'] = 'Domain-Aliasse';
$lang['mailbox']['target_domain'] = 'Ziel-Domain';
$lang['mailbox']['target_address'] = 'Ziel-Adresse';
$lang['mailbox']['username'] = 'Benutzername';
$lang['mailbox']['fname'] = 'Name';
$lang['mailbox']['filter_table'] = 'Filtern';
$lang['mailbox']['yes'] = '&#10004;';
$lang['mailbox']['no'] = '&#10008;';
$lang['mailbox']['in_use'] = 'Prozentualer Gebrauch';
$lang['mailbox']['msg_num'] = 'Anzahl Nachrichten';
$lang['mailbox']['remove'] = 'Entfernen';
$lang['mailbox']['edit'] = 'Bearbeiten';
$lang['mailbox']['no_record'] = 'Kein Eintrag für Objekt %s';
$lang['mailbox']['no_record_single'] = 'Kein Eintrag';
$lang['mailbox']['add_domain'] = 'Domain hinzufügen';
$lang['mailbox']['add_domain_alias'] = 'Domain-Alias hinzufügen';
$lang['mailbox']['add_mailbox'] = 'Mailbox hinzufügen';
$lang['mailbox']['add_resource'] = 'Ressource hinzufügen';
$lang['mailbox']['add_alias'] = 'Alias hinzufügen';
$lang['mailbox']['empty'] = 'Keine Einträge vorhanden';
$lang['mailbox']['toggle_all'] = 'Alle';
$lang['mailbox']['quick_actions'] = 'Aktionen';
$lang['mailbox']['activate'] = 'Aktivieren';
$lang['mailbox']['deactivate'] = 'Deaktivieren';
$lang['mailbox']['owner'] = 'Besitzer';
$lang['mailbox']['mins_interval'] = 'Intervall (min)';
$lang['mailbox']['last_run'] = 'Letzte Ausführung';
$lang['mailbox']['last_run_reset'] = 'Als nächstes ausführen';
$lang['mailbox']['sieve_info'] = 'Es können mehrere Filter pro Benutzer existieren, aber nur ein Filter eines Typs (Pre-/Postfilter) kann gleichzeitig aktiv sein.<br>
Die Ausführung erfolgt in nachstehender Reihenfolge. Ein fehlgeschlagenes Script sowie der Befehl "keep;" stoppen die weitere Verarbeitung <b>nicht</b>.<br>
Prefilter → User scripts → Postfilter → <a href="https://github.com/mailcow/mailcow-dockerized/blob/master/data/conf/dovecot/sieve_after" target="_blank">global sieve postfilter</a>';
$lang['info']['no_action'] = 'Keine Aktion anwendbar';
$lang['edit']['syncjob'] = 'Sync-Job bearbeiten';
$lang['edit']['save'] = 'Änderungen speichern';
$lang['edit']['username'] = 'Benutzername';
$lang['edit']['hostname'] = 'Servername';
$lang['edit']['encryption'] = 'Verschlüsselung';
$lang['edit']['maxage'] = 'Maximales Alter in Tagen einer Nachricht, die kopiert werden soll</br ><small>(0 = alle Nachrichten kopieren)</small>';
$lang['edit']['subfolder2'] = 'Ziel-Ordner<br><small>(leer = kein Unterordner)</small>';
$lang['edit']['mins_interval'] = 'Intervall (min)';
$lang['edit']['maxbytespersecond'] = 'Max. Übertragungsrate in Bytes/s (0 für unlimitiert)';
$lang['edit']['automap'] = 'Ordner automatisch mappen ("Sent items", "Sent" => "Sent" etc.)';
$lang['edit']['skipcrossduplicates'] = 'Duplikate auch über Ordner hinweg überspringen ("first come, first serve")';
$lang['add']['automap'] = 'Ordner automatisch mappen ("Sent items", "Sent" => "Sent" etc.)';
$lang['add']['skipcrossduplicates'] = 'Duplikate auch über Ordner hinweg überspringen ("first come, first serve")';
$lang['edit']['exclude'] = 'Elemente ausschließen (Regex)';
$lang['edit']['max_mailboxes'] = 'Max. Mailboxanzahl:';
$lang['edit']['title'] = 'Objekt bearbeiten';
$lang['edit']['target_address'] = 'Ziel-Adresse(n) <small>(getrennt durch Komma)</small>:';
$lang['edit']['active'] = 'Aktiv';
$lang['edit']['force_pw_update'] = 'Erzwinge Passwortänderung bei nächstem Login';
$lang['edit']['force_pw_update_info'] = 'Dem Benutzer wird lediglich der Zugang zur mailcow UI ermöglicht.';
$lang['edit']['target_domain'] = 'Ziel-Domain:';
$lang['edit']['password'] = 'Passwort:';
$lang['edit']['password_repeat'] = 'Passwort (Wiederholung):';
$lang['edit']['domain_admin'] = 'Domain-Administrator bearbeiten';
$lang['edit']['domain'] = 'Domain bearbeiten';
$lang['edit']['edit_alias_domain'] = 'Alias-Domain bearbeiten';
$lang['edit']['domains'] = 'Domains';
$lang['edit']['alias'] = 'Alias bearbeiten';
$lang['edit']['mailbox'] = 'Mailbox bearbeiten';
$lang['edit']['description'] = 'Beschreibung:';
$lang['edit']['max_aliases'] = 'Max. Aliasse:';
$lang['edit']['max_quota'] = 'Max. Größe per Mailbox (MiB):';
$lang['edit']['domain_quota'] = 'Domain Speicherplatz gesamt (MiB):';
$lang['edit']['backup_mx_options'] = 'Backup MX Optionen:';
$lang['edit']['relay_domain'] = 'Relay Domain';
$lang['edit']['relay_all'] = 'Alle Empfänger-Adressen relayen';
$lang['edit']['relay_all_info'] = '<small>Wenn Sie <b>nicht</b> alle Empfänger-Adressen relayen möchten, müssen Sie eine ("blinde") Mailbox für jede Adresse, die relayt werden soll, erstellen.</small>';
$lang['edit']['full_name'] = 'Voller Name';
$lang['edit']['quota_mb'] = 'Speicherplatz (MiB)';
$lang['edit']['sender_acl'] = 'Darf Nachrichten versenden als';
$lang['edit']['previous'] = 'Vorherige Seite';
$lang['edit']['unchanged_if_empty'] = 'Unverändert, wenn leer';
$lang['edit']['dont_check_sender_acl'] = 'Absender für Domain %s u. Alias-Dom. nicht prüfen';
$lang['edit']['multiple_bookings'] = 'Mehrfaches Buchen';
$lang['edit']['kind'] = 'Art';
$lang['edit']['resource'] = 'Ressource';
$lang['add']['syncjob'] = 'Sync-Job erstellen';
$lang['add']['syncjob_hint'] = 'Passwörter werden unverschlüsselt abgelegt!';
$lang['add']['hostname'] = 'Servername';
$lang['add']['port'] = 'Port';
$lang['add']['username'] = 'Benutzername';
$lang['add']['enc_method'] = 'Verschlüsselung';
$lang['add']['mins_interval'] = 'Abrufintervall (Minuten)';
$lang['add']['exclude'] = 'Elemente ausschließen (Regex)';
$lang['add']['delete2duplicates'] = 'Lösche Duplikate im Ziel';
$lang['add']['delete1'] = 'Lösche Nachricht nach Übertragung vom Quell-Server';
$lang['add']['delete2'] = 'Lösche Nachrichten von Ziel-Server, die nicht auf Quell-Server vorhanden sind';
$lang['add']['custom_params'] = 'Eigene Parameter';
$lang['add']['subscribeall'] = 'Alle synchronisierten Ordner abonnieren';
$lang['add']['timeout1'] = 'Timeout für Verbindung zum Remote-Host';
$lang['add']['timeout2'] = 'Timeout für Verbindung zum lokalen Host';
$lang['edit']['delete2duplicates'] = 'Lösche Duplikate im Ziel';
$lang['edit']['delete1'] = 'Lösche Nachricht nach Übertragung vom Quell-Server';
$lang['edit']['delete2'] = 'Lösche Nachrichten von Ziel-Server, die nicht auf Quell-Server vorhanden sind';
$lang['add']['domain_matches_hostname'] = 'Domain %s darf nicht dem Hostnamen entsprechen';
$lang['add']['domain'] = 'Domain';
$lang['add']['active'] = 'Aktiv';
$lang['add']['multiple_bookings'] = 'Mehrfaches Buchen möglich';
$lang['add']['description'] = 'Beschreibung';
$lang['add']['max_aliases'] = 'Max. mögliche Aliasse';
$lang['add']['max_mailboxes'] = 'Max. mögliche Mailboxen';
$lang['add']['mailbox_quota_m'] = 'Max. Speicherplatz pro Mailbox (MiB)';
$lang['add']['domain_quota_m'] = 'Domain Speicherplatz gesamt (MiB)';
$lang['add']['backup_mx_options'] = 'Backup MX Optionen';
$lang['add']['relay_all'] = 'Alle Empfänger-Adressen relayen';
$lang['add']['relay_domain'] = 'Relay Domain';
$lang['add']['relay_all_info'] = '<small>Wenn Sie <b>nicht</b> alle Empfänger-Adressen relayen möchten, müssen Sie eine Mailbox für jede Adresse, die relayt werden soll, erstellen.</small>';
$lang['add']['alias_address'] = 'Alias-Adresse(n)';
$lang['add']['alias_address_info'] = '<small>Vollständige E-Mail-Adresse(n) oder @example.com, um alle Nachrichten einer Domain weiterzuleiten. Getrennt durch Komma. <b>Nur eigene Domains</b>.</small>';
$lang['add']['alias_domain_info'] = '<small>Nur gültige Domains. Getrennt durch Komma.</small>';
$lang['add']['target_address'] = 'Ziel-Adresse(n)';
$lang['add']['target_address_info'] = '<small>Vollständige E-Mail-Adresse(n). Getrennt durch Komma.</small>';
$lang['add']['alias_domain'] = 'Alias-Domain';
$lang['add']['select'] = 'Bitte auswählen';
$lang['add']['target_domain'] = 'Ziel-Domain';
$lang['add']['kind'] = 'Art';
$lang['add']['mailbox_username'] = 'Benutzername (linker Teil der E-Mail-Adresse)';
$lang['add']['full_name'] = 'Vor- und Zuname';
$lang['add']['quota_mb'] = 'Speicherplatz (MiB)';
$lang['add']['select_domain'] = 'Bitte zuerst eine Domain auswählen';
$lang['add']['password'] = 'Passwort';
$lang['add']['password_repeat'] = 'Passwort (Wiederholung)';
$lang['add']['restart_sogo_hint'] = 'Der SOGo Container muss nach dem Hinzufügen einer neuen Domain neugestartet werden!';
$lang['add']['goto_null'] = 'Nachrichten sofort verwerfen';
$lang['add']['goto_ham'] = 'Nachrichten als <span class="text-success"><b>Ham</b></span> lernen';
$lang['add']['goto_spam'] = 'Nachrichten als <span class="text-danger"><b>Spam</b></span> lernen';
$lang['add']['validation_success'] = 'Erfolgreich validiert';
$lang['add']['activate_filter_warn'] = 'Alle anderen Filter diesen Typs werden deaktiviert, falls dieses Script aktiv markiert wird.';
$lang['add']['validate'] = 'Validieren';
$lang['mailbox']['add_filter'] = 'Filter erstellen';
$lang['add']['sieve_desc'] = 'Kurze Beschreibung';
$lang['edit']['sieve_desc'] = 'Kurze Beschreibung';
$lang['add']['sieve_type'] = 'Filtertyp';
$lang['edit']['sieve_type'] = 'Filtertyp';
$lang['mailbox']['set_prefilter'] = 'Als Prefilter markieren';
$lang['mailbox']['set_postfilter'] = 'Als Postfilter markieren';
$lang['mailbox']['filters'] = 'Filter';
$lang['mailbox']['sync_jobs'] = 'Synchronisationen';
$lang['mailbox']['inactive'] = 'Inaktiv';
$lang['edit']['validate_save'] = 'Validieren und speichern';
$lang['login']['username'] = 'Benutzername';
$lang['login']['password'] = 'Passwort';
$lang['login']['login'] = 'Anmelden';
$lang['login']['delayed'] = 'Login wurde zur Sicherheit um %s Sekunde/n verzögert.';
$lang['tfa']['tfa'] = "Zwei-Faktor-Authentifizierung";
$lang['tfa']['set_tfa'] = "Konfiguriere Zwei-Faktor-Authentifizierungsmethode";
$lang['tfa']['yubi_otp'] = "Yubico OTP Authentifizierung";
$lang['tfa']['key_id'] = "Ein Name für diesen YubiKey";
$lang['tfa']['key_id_totp'] = "Ein eindeutiger Name";
$lang['tfa']['api_register'] = 'mailcow verwendet die Yubico Cloud API. Ein API-Key für den Yubico Stick kann <a href="https://upgrade.yubico.com/getapikey/" target="_blank">hier</a> bezogen werden.';
$lang['tfa']['u2f'] = "U2F Authentifizierung";
$lang['tfa']['totp'] = "TOTP Authentifizierung";
$lang['tfa']['none'] = "Deaktiviert";
$lang['tfa']['delete_tfa'] = "Deaktiviere 2FA";
$lang['tfa']['disable_tfa'] = "Deaktiviere 2FA bis zur nächsten erfolgreichen Anmeldung";
$lang['tfa']['confirm'] = "Bestätigen";
$lang['tfa']['totp'] = "Time-based OTP (Google Authenticator etc.)";
$lang['tfa']['select'] = "Bitte auswählen";
$lang['tfa']['waiting_usb_auth'] = "<i>Warte auf USB-Gerät...</i><br><br>Bitte jetzt den vorgesehenen Taster des U2F USB-Gerätes berühren.";
$lang['tfa']['waiting_usb_register'] = "<i>Warte auf USB-Gerät...</i><br><br>Bitte zuerst das obere Passwortfeld ausfüllen und erst dann den vorgesehenen Taster des U2F USB-Gerätes berühren.";
$lang['tfa']['scan_qr_code'] = "Bitte scannen Sie jetzt den angezeigten QR-Code:.";
$lang['tfa']['enter_qr_code'] = "Falls Sie den angezeigten QR-Code nicht scannen können, verwenden Sie bitte nachstehenden Sicherheitsschlüssel";
$lang['tfa']['confirm_totp_token'] = "Bitte bestätigen Sie die Änderung durch Eingabe eines generierten Tokens";
$lang['admin']['rspamd-com_settings'] = '<a href="https://rspamd.com/doc/configuration/settings.html#settings-structure" target="_blank">Rspamd docs</a>
- Ein Name wird automatisch generiert. Beispielinhalte zur Einsicht stehen nachstehend bereit.';
$lang['admin']['no_new_rows'] = 'Keine weiteren Zeilen vorhanden';
$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']['import_private_key'] = 'Private Key importieren';
$lang['admin']['f2b_parameters'] = 'Fail2ban Parameter';
$lang['admin']['f2b_ban_time'] = 'Banzeit (s)';
$lang['admin']['f2b_max_attempts'] = 'Max. Versuche';
$lang['admin']['f2b_retry_window'] = 'Wiederholungen im Zeitraum von (s)';
$lang['admin']['f2b_netban_ipv4'] = 'Netzbereich für IPv4 Bans (8-32)';
$lang['admin']['f2b_netban_ipv6'] = 'Netzbereich für IPv6 Bans (8-128)';
$lang['admin']['f2b_whitelist'] = 'Whitelist für Netzwerke und Hosts';
$lang['admin']['r_inactive'] = 'Inaktive Restriktionen';
$lang['admin']['r_active'] = 'Aktive Restriktionen';
$lang['admin']['r_info'] = 'Ausgegraute/deaktivierte Elemente sind mailcow nicht bekannt und können nicht in die Liste inaktiver Elemente verschoben werden. Unbekannte Restriktionen werden trotzdem in Reihenfolge der Erscheinung gesetzt.<br>Sie können ein Element in der Datei <code>inc/vars.local.inc.php</code> als bekannt hinzufügen, um es zu bewegen.';
$lang['admin']['save'] = 'Änderungen speichern';
$lang['admin']['dkim_add_key'] = 'ARC/DKIM-Key hinzufügen';
$lang['admin']['dkim_keys'] = 'ARC/DKIM-Keys';
$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']['add'] = 'Hinzufügen';
$lang['add']['add_domain_restart'] = 'Domain hinzufügen und SOGo neustarten';
$lang['add']['add_domain_only'] = 'Nur Domain hinzufügen';
$lang['admin']['configuration'] = 'Konfiguration';
$lang['admin']['password'] = 'Passwort';
$lang['admin']['password_repeat'] = 'Passwort (Wiederholung)';
$lang['admin']['active'] = 'Aktiv';
$lang['admin']['inactive'] = 'Inaktiv';
$lang['admin']['action'] = 'Aktion';
$lang['admin']['add_domain_admin'] = 'Domain-Administrator hinzufügen';
$lang['admin']['add_settings_rule'] = 'Rspamd Regel hinzufügen';
$lang['admin']['rsetting_desc'] = 'Kurze Beschreibung';
$lang['admin']['rsetting_content'] = 'Regelinhalt';
$lang['admin']['rsetting_none'] = 'Keine Regel hinterlegt';
$lang['admin']['rsetting_no_selection'] = 'Bitte eine Regel auswählen';
$lang['admin']['rsettings_preset_1'] = 'Alles außer DKIM and Ratelimits für authentifizierte Benutzer deaktivieren"';
$lang['admin']['rsettings_preset_2'] = 'Spam an Postmaster-Addressen nicht blockieren';
$lang['admin']['rsettings_insert_preset'] = 'Beispiel "%s" laden';
$lang['admin']['rsetting_add_rule'] = 'Regel hinzufügen';
$lang['admin']['admin_domains'] = 'Domain-Zuweisungen';
$lang['admin']['domain_admins'] = 'Domain-Administratoren';
$lang['admin']['username'] = 'Benutzername';
$lang['admin']['edit'] = 'Bearbeiten';
$lang['admin']['remove'] = 'Entfernen';
$lang['admin']['save'] = 'Änderungen speichern';
$lang['admin']['admin'] = 'Administrator';
$lang['admin']['admin_details'] = 'Administrator bearbeiten';
$lang['admin']['unchanged_if_empty'] = 'Unverändert, wenn leer';
$lang['admin']['yes'] = '&#10004;';
$lang['admin']['no'] = '&#10008;';
$lang['admin']['access'] = 'Zugang';
$lang['admin']['no_record'] = 'Kein Eintrag';
$lang['admin']['filter_table'] = 'Tabelle Filtern';
$lang['admin']['empty'] = 'Keine Einträge vorhanden';
$lang['admin']['time'] = 'Zeit';
$lang['admin']['priority'] = 'Gewichtung';
$lang['admin']['refresh'] = 'Neu laden';
$lang['admin']['to_top'] = 'Nach oben';
$lang['admin']['in_use_by'] = 'Verwendet von';
$lang['admin']['message'] = 'Nachricht';
$lang['admin']['forwarding_hosts'] = 'Weiterleitungs-Hosts';
$lang['admin']['forwarding_hosts_hint'] = 'Eingehende Nachrichten werden von den hier gelisteten Hosts bedingungslos akzeptiert. Diese Hosts werden dann nicht mit DNSBLs abgeglichen oder Greylisting unterworfen. Von ihnen empfangener Spam wird nie abgelehnt, optional kann er aber in den Spam-Ordner einsortiert werden. Die übliche Verwendung für diese Funktion ist, um Mailserver anzugeben, auf denen eine Weiterleitung zu Ihrem mailcow-Server eingerichtet wurde.';
$lang['admin']['forwarding_hosts_add_hint'] = 'Sie können entweder IPv4/IPv6-Adressen, Netzwerke in CIDR-Notation, Hostnamen (die zu IP-Adressen aufgelöst werden), oder Domainnamen (die zu IP-Adressen aufgelöst werden, indem ihr SPF-Record abgefragt wird oder, in dessen Abwesenheit, ihre MX-Records) angeben.';
$lang['admin']['relayhosts_hint'] = 'Erstellen Sie Relayhosts, um diese im Einstellungsdialog einer Domain auszuwählen.';
$lang['admin']['add_relayhost_add_hint'] = 'Bitte beachten Sie, dass Relayhost Anmeldedaten im Klartext gespeichert werden.';
$lang['admin']['host'] = 'Host';
$lang['admin']['source'] = 'Quelle';
$lang['admin']['add_forwarding_host'] = 'Weiterleitungs-Host hinzufügen';
$lang['admin']['add_relayhost'] = 'Relayhost hinzufügen';
$lang['admin']['api_allow_from'] = "IP-Adressen für Zugriff";
$lang['admin']['api_key'] = "API-Key";
$lang['admin']['activate_api'] = "API aktivieren";
$lang['admin']['regen_api_key'] = "API-Key regenerieren";
$lang['admin']['ban_list_info'] = "Übersicht ausgesperrter Netzwerke: <b>Netzwerk (verbleibende Banzeit) - [Aktionen]</b>.<br />IPs, die zum Unban eingereiht werden, verlassen die Liste aktiver Bans nach wenigen Sekunden.<br />Rote Labels sind Indikatoren für aktive Blacklisteinträge.";
$lang['admin']['unban_pending'] = "ausstehend";
$lang['admin']['queue_unban'] = "Unban einreihen";
$lang['admin']['no_active_bans'] = "Keine aktiven Bans";
$lang['admin']['quarantine'] = "Quarantäne";
$lang['admin']['quarantine_retention_size'] = "Rückhaltungen pro Mailbox<br />0 bedeutet <b>inaktiv</b>!";
$lang['admin']['quarantine_max_size'] = "Maximale Größe in MiB (größere Elemente werden verworfen)<br />0 bedeutet <b>nicht</b> unlimitert!";
$lang['admin']['quarantine_exclude_domains'] = "Domains und Alias-Domains ausschließen:";
$lang['success']['forwarding_host_removed'] = "Weiterleitungs-Host %s wurde entfernt";
$lang['success']['forwarding_host_added'] = "Weiterleitungs-Host %s wurde hinzugefügt";
$lang['success']['relayhost_removed'] = "Relayhost %s wurde entfernt";
$lang['success']['relayhost_added'] = "Relayhost %s wurde hinzugefügt";
$lang['diagnostics']['dns_records'] = 'DNS-Einträge';
$lang['diagnostics']['dns_records_24hours'] = 'Bitte beachten Sie, dass es bis zu 24 Stunden dauern kann, bis Änderungen an Ihren DNS-Einträgen als aktueller Status auf dieser Seite dargestellt werden. Diese Seite ist nur als Hilfsmittel gedacht, um die korrekten Werte für DNS-Einträge zu anzuzeigen und zu überprüfen, ob die Daten im DNS hinterlegt sind.';
$lang['diagnostics']['dns_records_name'] = 'Name';
$lang['diagnostics']['dns_records_type'] = 'Typ';
$lang['diagnostics']['dns_records_data'] = 'Korrekte Daten';
$lang['diagnostics']['dns_records_status'] = 'Aktueller Status';
$lang['diagnostics']['optional'] = 'Dieser Eintrag ist optional.';
$lang['diagnostics']['cname_from_a'] = 'Wert abgeleitet von A/AAAA Eintrag. Wird unterstützt, sofern der Eintrag auf die korrekte Ressource zeigt.';
$lang['admin']['relay_from'] = "Absenderadresse";
$lang['admin']['relay_run'] = "Test durchführen";
$lang['mailbox']['waiting'] = "Wartend";
$lang['mailbox']['status'] = "Status";
$lang['mailbox']['running'] = "In Ausführung";
$lang['admin']['ui_texts'] = "UI Label und Texte";
$lang['admin']['help_text'] = "Hilfstext unter Login-Maske (HTML zulässig)";
$lang['admin']['title_name'] = '"mailcow UI" Webseiten Titel';
$lang['admin']['main_name'] = '"mailcow UI" Name';
$lang['admin']['apps_name'] = '"mailcow Apps" Name';
$lang['admin']['customize'] = "UI Anpassung";
$lang['admin']['change_logo'] = "Logo ändern";
$lang['admin']['logo_info'] = "Die hochgeladene Grafik wird für die Navigationsleiste auf eine Höhe von 40px skaliert. Für die Darstellung auf der Login-Maske beträgt die skalierte Breite maximal 250px. Eine frei skalierbare Grafik (etwa SVG) wird empfohlen.";
$lang['admin']['upload'] = "Hochladen";
$lang['admin']['app_links'] = "App Links";
$lang['admin']['app_name'] = "App Name";
$lang['admin']['link'] = "Link";
$lang['admin']['remove_row'] = "Entfernen";
$lang['admin']['add_row'] = "Reihe hinzufügen";
$lang['admin']['reset_default'] = "Zurücksetzen auf Standard";
$lang['admin']['merged_vars_hint'] = 'Ausgegraute Reihen wurden aus der Datei <code>vars.(local.)inc.php</code> gelesen und können hier nicht verändert werden.';
$lang['edit']['spam_score'] = "Einen benutzerdefiniterten Spam-Score festlegen";
$lang['edit']['spam_policy'] = "Hinzufügen und Entfernen von Einträgen in White- und Blacklists";
$lang['edit']['spam_alias'] = "Anpassen temporärer Alias-Adressen";
$lang['danger']['img_tmp_missing'] = "Grafik konnte nicht validiert werden: Erstellung temporärer Datei fehlgeschlagen";
$lang['danger']['img_invalid'] = "Grafik konnte nicht validiert werden";
$lang['danger']['invalid_mime_type'] = "Grafik konnte nicht validiert werden: Ungültiger MIME-Type";
$lang['success']['upload_success'] = "Datei wurde erfolgreich hochgeladen";
$lang['success']['app_links'] = "Änderungen an App Links wurden gespeichert";
$lang['success']['ui_texts'] = "Änderungen an UI-Texten";
$lang['success']['reset_main_logo'] = "Standardgrafik wurde wiederhergestellt";
$lang['success']['items_released'] = "Ausgewählte Objekte wurden an Mailbox versendet";
$lang['danger']['imagick_exception'] = "Fataler Bildverarbeitungsfehler";
-
+$lang['quarantine']['learn_spam_delete'] = "Als Spam lernen und löschen";
$lang['quarantine']['quarantine'] = "Quarantäne";
-$lang['quarantine']['qinfo'] = "Das Quarantänesystem speichert abgelehnte Nachrichten in der Datenbank. Dem Sender wird <em>nicht</em> signalisiert, dass seine E-Mail zugestellt wurde.";
+$lang['quarantine']['qinfo'] = 'Das Quarantänesystem speichert abgelehnte Nachrichten in der Datenbank. Dem Sender wird <em>nicht</em> signalisiert, dass seine E-Mail zugestellt wurde.
+ <br>"' . $lang['quarantine']['learn_spam_delete'] . '" lernt Nachrichten nach bayesscher Statistik als Spam und erstellt Fuzzy Hashes ausgehend von der jeweiligen Nachricht, um ähnliche Inhalte zukünftig zu unterbinden.
+ <br>Der Prozess des Lernens kann abhängig vom System zeitintensiv sein.';
$lang['quarantine']['release'] = "Freigeben";
$lang['quarantine']['empty'] = 'Keine Einträge';
$lang['quarantine']['toggle_all'] = 'Alle auswählen';
$lang['quarantine']['quick_actions'] = 'Aktionen';
$lang['quarantine']['remove'] = 'Entfernen';
$lang['quarantine']['received'] = "Empfangen";
$lang['quarantine']['action'] = "Aktion";
$lang['quarantine']['rcpt'] = "Empfänger";
$lang['quarantine']['qid'] = "Rspamd QID";
$lang['quarantine']['sender'] = "Sender";
$lang['quarantine']['show_item'] = "Details";
$lang['quarantine']['check_hash'] = "Checksumme auf VirusTotal suchen";
$lang['quarantine']['qitem'] = "Quarantäneeintrag";
$lang['quarantine']['subj'] = "Betreff";
$lang['quarantine']['text_plain_content'] = "Inhalt (text/plain)";
$lang['quarantine']['text_from_html_content'] = "Inhalt (html, konvertiert)";
$lang['quarantine']['atts'] = "Anhänge";
+$lang['danger']['fuzzy_learn_error'] = "Fuzzy Lernfehler: %s";
+$lang['danger']['spam_learn_error'] = "Spam Lernfehler: %s";
+$lang['success']['qlearn_spam'] = "Nachricht ID %s wurde als Spam gelernt und gelöscht";
$lang['header']['quarantine'] = "Quarantäne";
$lang['header']['debug'] = "Debugging";
$lang['debug']['log_info'] = '<p>mailcow <b>in-memory Logs</b> werden in Redis Listen gespeichert, die maximale Anzahl der Einträge pro Anwendung richtet sich nach LOG_LINES (%d).
<br>In-memory Logs sind vergänglich und nicht zur ständigen Aufbewahrung bestimmt. Alle Anwendungen, die in-memory protokollieren, schreiben ebenso in den Docker Daemon.
<br>Das in-memory Protokoll versteht sich als schnelle Übersicht zum Debugging eines Containers, für komplexere Protokolle sollte der Docker Daemon konsultiert werden.</p>
<p><b>Externe Logs</b> werden via API externer Applikationen bezogen.</p>
<p><b>Statische Logs</b> sind weitesgehend Aktivitätsprotokolle, die nicht in den Docker Daemon geschrieben werden, jedoch permanent verfügbar sein müssen (ausgeschloßen API Logs).</p>';
$lang['debug']['in_memory_logs'] = 'In-memory Logs';
$lang['debug']['external_logs'] = 'Externe Logs';
$lang['debug']['static_logs'] = 'Statische Logs';
$lang['quarantine']['release_body'] = "Die ursprüngliche Nachricht wurde als EML-Datei im Anhang hinterlegt.";
$lang['danger']['release_send_failed'] = "Die Nachricht konnte nicht versendet werden: %s";
$lang['quarantine']['release_subject'] = "Potentiell schädliche Nachricht aus Quarantäne: %s";
+$lang['mailbox']['bcc_map'] = "BCC Map";
$lang['mailbox']['bcc_map_type'] = "BCC Typ";
$lang['mailbox']['bcc_type'] = "BCC Typ";
$lang['mailbox']['bcc_sender_map'] = "Senderabhängig";
$lang['mailbox']['bcc_rcpt_map'] = "Empfängerabhängig";
$lang['mailbox']['bcc_local_dest'] = "Lokales Ziel";
-$lang['mailbox']['bcc_destinations'] = "BCC Ziel(e)";
+$lang['mailbox']['bcc_destinations'] = "BCC Ziel";
+$lang['mailbox']['bcc_destination'] = "BCC Ziel";
+$lang['edit']['bcc_dest_format'] = 'BCC-Ziel muss eine gültige E-Mail-Adresse sein.';
$lang['mailbox']['bcc'] = "BCC";
$lang['mailbox']['bcc_maps'] = "BCC-Maps";
$lang['mailbox']['bcc_to_sender'] = "Map senderabhängig verwenden";
$lang['mailbox']['bcc_to_rcpt'] = "Map empfängerabhängig verwenden";
$lang['mailbox']['add_bcc_entry'] = "BCC-Eintrag hinzufügen";
$lang['mailbox']['bcc_info'] = "Eine empfängerabhängige Map wird verwendet, wenn die BCC-Map Eintragung auf den Eingang einer E-Mail auf das lokale Ziel reagieren soll. Senderabhängige Maps verfahren nach dem gleichen Prinzip.<br/>
Das lokale Ziel wird bei Fehlzustellungen an ein BCC-Ziel nicht informiert.";
$lang['mailbox']['address_rewriting'] = 'Adressumschreibung';
$lang['mailbox']['recipient_maps'] = 'Empfängerumschreibungen';
$lang['mailbox']['recipient_map'] = 'Empfängerumschreibung';
$lang['mailbox']['recipient_map_info'] = 'Empfängerumschreibung ersetzen den Empfänger einer E-Mail vor dem Versand.';
$lang['mailbox']['recipient_map_old_info'] = 'Der originale Empfänger muss eine E-Mail-Adresse oder ein Domainname sein.';
$lang['mailbox']['recipient_map_new_info'] = 'Der neue Empfänger muss eine E-Mail-Adresse sein.';
$lang['mailbox']['recipient_map_old'] = 'Original Empfänger';
$lang['mailbox']['recipient_map_new'] = 'Neuer Empfänger';
$lang['mailbox']['add_recipient_map_entry'] = 'Empfängerumschreibung hinzufügen';
$lang['danger']['invalid_recipient_map_new'] = 'Neuer Empfänger %s ist ungültig';
$lang['danger']['invalid_recipient_map_old'] = 'Originaler Empfänger %s ist ungültig';
$lang['danger']['recipient_map_entry_exists'] = 'Eine Empfängerumschreibung für %s existiert bereits';
$lang['success']['recipient_map_entry_saved'] = 'Empfängerumschreibung für Objekt %s wurde gespeichert';
$lang['success']['recipient_map_entry_deleted'] = 'Empfängerumschreibung für Objekt %s wurde gelöscht';
diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php
index df4049c7..ed2fbf25 100644
--- a/data/web/lang/lang.en.php
+++ b/data/web/lang/lang.en.php
@@ -1,650 +1,662 @@
<?php
/*
* English language file
*/
$lang['footer']['loading'] = "Please wait...";
$lang['header']['restart_sogo'] = 'Restart SOGo';
$lang['header']['restart_netfilter'] = 'Restart netfilter';
$lang['footer']['restart_container'] = 'Restart container';
$lang['footer']['restart_now'] = 'Restart now';
$lang['footer']['restarting_container'] = 'Restarting container, this may take a while...';
$lang['footer']['restart_container_info'] = '<b>Important:</b> A graceful restart may take a while to complete, please wait for it to finish.';
$lang['footer']['confirm_delete'] = 'Confirm deletion';
$lang['footer']['delete_these_items'] = 'Please confirm your changes to the following object id:';
$lang['footer']['delete_now'] = 'Delete now';
$lang['footer']['cancel'] = 'Cancel';
$lang['danger']['mysql_error'] = "MySQL error: %s";
$lang['danger']['redis_error'] = "Redis error: %s";
$lang['danger']['unknown_tfa_method'] = "Unknown TFA method";
$lang['danger']['totp_verification_failed'] = "TOTP verification failed";
$lang['success']['verified_totp_login'] = "Verified TOTP login";
$lang['danger']['u2f_verification_failed'] = "U2F verification failed: %s";
$lang['success']['verified_u2f_login'] = "Verified U2F login";
$lang['success']['verified_yotp_login'] = "Verified Yubico OTP login";
$lang['danger']['yotp_verification_failed'] = "Yubico OTP verification failed: %s";
$lang['danger']['ip_list_empty'] = "List of allowed IPs cannot be empty";
$lang['danger']['rspamd_ui_pw_length'] = "Rspamd UI password should be at least 6 chars long";
$lang['success']['rspamd_ui_pw_set'] = "Rspamd UI password successfully set";
$lang['danger']['unknown'] = "An unknown error occured";
$lang['danger']['malformed_username'] = "Malformed username";
$lang['info']['awaiting_tfa_confirmation'] = "Awaiting TFA confirmation";
$lang['success']['logged_in_as'] = "Logged in as %s";
$lang['danger']['login_failed'] = "Login failed";
$lang['danger']['set_acl_failed'] = "Failed to set ACL";
$lang['danger']['no_user_defined'] = "No user defined";
$lang['danger']['script_empty'] = "Script cannot be empty";
$lang['danger']['sieve_error'] = "Sieve parser error: %s";
$lang['danger']['value_missing'] = "Please provide all values";
$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['success']['deleted_syncjobs'] = "Deleted syncjobs: %s";
+$lang['success']['deleted_syncjob'] = "Deleted syncjob ID %s";
$lang['success']['delete_filters'] = "Deleted filters: %s";
+$lang['success']['delete_filter'] = "Deleted filters ID %s";
$lang['danger']['invalid_bcc_map_type'] = "Invalid BCC map type";
$lang['danger']['bcc_empty'] = "BCC destination cannot be empty";
-$lang['danger']['bcc_must_be_email'] = "BCC map must be a valid email address";
+$lang['danger']['bcc_must_be_email'] = "BCC map %s is not a valid email address";
$lang['danger']['bcc_exists'] = "A BCC map %s exists for type %s";
$lang['success']['bcc_saved'] = "BCC map entry saved";
-$lang['success']['bcc_edited'] = "BCC map entry edited";
+$lang['success']['bcc_edited'] = "BCC map entry %s edited";
$lang['success']['bcc_deleted'] = "BCC map entries deleted: %s";
$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 invalid";
+$lang['danger']['settings_map_invalid'] = "Settings map ID %s invalid";
$lang['danger']['settings_map_removed'] = "Removed settings map deleted: %s";
$lang['danger']['invalid_host'] = "Invalid host specified: %s";
-$lang['danger']['relayhost_invalid'] = "Relayhost is invalid";
+$lang['danger']['relayhost_invalid'] = "Relayhost %s is invalid";
$lang['success']['saved_settings'] = "Saved settings";
$lang['success']['db_init_complete'] = "Database initialization completed";
$lang['warning']['session_ua'] = "Form token invalid: User-Agent validation error";
$lang['warning']['session_token'] = "Form token invalid: Token mismatch";
-$lang['danger']['dkim_domain_or_sel_invalid'] = "DKIM domain or selector invalid";
+$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['danger']['access_denied'] = "Access denied or invalid form data";
-$lang['danger']['domain_invalid'] = "Domain name is invalid";
+$lang['danger']['domain_invalid'] = "Domain name %s is invalid";
$lang['danger']['mailbox_quota_exceeds_domain_quota'] = "Max. quota exceeds domain quota limit";
$lang['danger']['object_is_not_numeric'] = "Value %s is not numeric";
$lang['success']['domain_added'] = "Added domain %s";
$lang['success']['items_deleted'] = "Item %s successfully deleted";
+$lang['success']['item_deleted'] = "Item %s successfully deleted";
$lang['danger']['alias_empty'] = "Alias address must not be empty";
$lang['danger']['last_key'] = 'Last key cannot be deleted';
$lang['danger']['goto_empty'] = "Goto address must not be empty";
$lang['danger']['policy_list_from_exists'] = "A record with given name exists";
$lang['danger']['policy_list_from_invalid'] = "Record has invalid format";
-$lang['danger']['alias_invalid'] = "Alias address is invalid";
-$lang['danger']['goto_invalid'] = "Goto address is invalid";
-$lang['danger']['alias_domain_invalid'] = "Alias domain is invalid";
-$lang['danger']['target_domain_invalid'] = "Goto domain is invalid";
+$lang['danger']['alias_invalid'] = "Alias address %s is invalid";
+$lang['danger']['goto_invalid'] = "Goto address %s is invalid";
+$lang['danger']['alias_domain_invalid'] = "Alias domain %s is invalid";
+$lang['danger']['target_domain_invalid'] = "Target domain %s is invalid";
$lang['danger']['object_exists'] = "Object %s already exists";
$lang['danger']['domain_exists'] = "Domain %s already exists";
$lang['danger']['alias_goto_identical'] = "Alias and goto address must not be identical";
-$lang['danger']['aliasd_targetd_identical'] = "Alias domain must not be equal to target domain";
+$lang['danger']['aliasd_targetd_identical'] = "Alias domain must not be equal to target domain: %s";
$lang['danger']['maxquota_empty'] = 'Max. quota per mailbox must not be 0.';
-$lang['success']['alias_added'] = "Alias address/es has/have been added";
-$lang['success']['alias_modified'] = "Changes to alias/es %s have been saved";
+$lang['success']['alias_added'] = "Alias address %s has been added";
+$lang['success']['alias_modified'] = "Changes to alias address %s have been saved";
$lang['success']['mailbox_modified'] = "Changes to mailbox %s have been saved";
$lang['success']['resource_modified'] = "Changes to mailbox %s have been saved";
$lang['success']['object_modified'] = "Changes to object %s have been saved";
$lang['success']['f2b_modified'] = "Changes to Fail2ban parameters have been saved";
-$lang['danger']['targetd_not_found'] = "Target domain not found";
+$lang['danger']['targetd_not_found'] = "Target domain %s not found";
$lang['success']['aliasd_added'] = "Added alias domain %s";
$lang['success']['aliasd_modified'] = "Changes to alias domain %s have been saved";
$lang['success']['domain_modified'] = "Changes to domain %s have been saved";
$lang['success']['domain_admin_modified'] = "Changes to domain administrator %s have been saved";
$lang['success']['domain_admin_added'] = "Domain administrator %s has been added";
$lang['success']['admin_modified'] = "Changes to administrator have been saved";
-$lang['danger']['username_invalid'] = "Username cannot be used";
+$lang['danger']['username_invalid'] = "Username %s cannot be used";
$lang['danger']['password_mismatch'] = "Confirmation password does not match";
$lang['danger']['password_complexity'] = "Password does not meet the policy";
$lang['danger']['password_empty'] = "Password must not be empty";
$lang['danger']['login_failed'] = "Login failed";
$lang['danger']['mailbox_invalid'] = "Mailbox name is invalid";
-$lang['danger']['description_invalid'] = 'Resource description is invalid';
-$lang['danger']['resource_invalid'] = "Resource name is invalid";
+$lang['danger']['description_invalid'] = 'Resource description for %s is invalid';
+$lang['danger']['resource_invalid'] = "Resource name %s is invalid";
$lang['danger']['is_alias'] = "%s is already known as an alias address";
$lang['danger']['is_alias_or_mailbox'] = "%s is already known as an alias, a mailbox or an alias address expanded from an alias domain.";
$lang['danger']['is_spam_alias'] = "%s is already known as a spam alias address";
$lang['danger']['quota_not_0_not_numeric'] = "Quota must be numeric and >= 0";
$lang['danger']['domain_not_found'] = 'Domain %s not found';
$lang['danger']['max_mailbox_exceeded'] = "Max. mailboxes exceeded (%d of %d)";
$lang['danger']['max_alias_exceeded'] = 'Max. aliases exceeded';
$lang['danger']['mailbox_quota_exceeded'] = "Quota exceeds the domain limit (max. %d MiB)";
$lang['danger']['mailbox_quota_left_exceeded'] = "Not enough space left (space left: %d MiB)";
$lang['success']['mailbox_added'] = "Mailbox %s has been added";
$lang['success']['resource_added'] = "Resource %s has been added";
$lang['success']['domain_removed'] = "Domain %s has been removed";
$lang['success']['alias_removed'] = "Alias %s has been removed";
$lang['success']['alias_domain_removed'] = "Alias domain %s has been removed";
$lang['success']['domain_admin_removed'] = "Domain administrator %s has been removed";
$lang['success']['mailbox_removed'] = "Mailbox %s has been removed";
$lang['success']['eas_reset'] = "ActiveSync devices for user %s were reset";
$lang['success']['resource_removed'] = "Resource %s has been removed";
$lang['danger']['max_quota_in_use'] = "Mailbox quota must be greater or equal to %d MiB";
$lang['danger']['domain_quota_m_in_use'] = "Domain quota must be greater or equal to %s MiB";
$lang['danger']['mailboxes_in_use'] = "Max. mailboxes must be greater or equal to %d";
$lang['danger']['aliases_in_use'] = "Max. aliases must be greater or equal to %d";
-$lang['danger']['sender_acl_invalid'] = "Sender ACL value is invalid";
+$lang['danger']['sender_acl_invalid'] = "Sender ACL value %s is invalid";
$lang['danger']['domain_not_empty'] = "Cannot remove non-empty domain";
$lang['danger']['validity_missing'] = 'Please assign a period of validity';
$lang['user']['loading'] = "Loading...";
$lang['user']['force_pw_update'] = 'You <b>must</b> set a new password to be able to access groupware related services.';
$lang['user']['active_sieve'] = "Active filter";
$lang['user']['show_sieve_filters'] = "Show active user sieve filter";
$lang['user']['no_active_filter'] = "No active filter available";
$lang['user']['messages'] = "messages"; // "123 messages"
$lang['user']['in_use'] = "Used";
$lang['user']['user_change_fn'] = "";
$lang['user']['user_settings'] = 'User settings';
$lang['user']['mailbox_details'] = 'Mailbox details';
$lang['user']['change_password'] = 'Change password';
$lang['user']['client_configuration'] = 'Show configuration guides for email clients and smartphones';
$lang['user']['new_password'] = 'New password';
$lang['user']['save_changes'] = 'Save changes';
$lang['user']['password_now'] = 'Current password (confirm changes)';
$lang['user']['new_password_repeat'] = 'Confirmation password (repeat)';
$lang['user']['new_password_description'] = 'Requirement: 6 characters long, letters and numbers.';
$lang['user']['spam_aliases'] = 'Temporary email aliases';
$lang['user']['alias'] = 'Alias';
$lang['user']['shared_aliases'] = 'Shared alias addresses';
$lang['user']['shared_aliases_desc'] = 'Shared aliases are not affected by user specific settings such as the spam filter or encryption policy. Corresponding spam filters can only be made by an administrator as a domain-wide policy..';
$lang['user']['direct_aliases'] = 'Direct alias addresses';
$lang['user']['direct_aliases_desc'] = 'Direct alias addresses are affected by spam filter and TLS policy settings.';
$lang['user']['is_catch_all'] = 'Catch-all for domain/s';
$lang['user']['aliases_also_send_as'] = 'Also allowed to send as user';
$lang['user']['aliases_send_as_all'] = 'Do not check sender access for the following domain(s) and its alias domains';
$lang['user']['alias_create_random'] = 'Generate random alias';
$lang['user']['alias_extend_all'] = 'Extend aliases by 1 hour';
$lang['user']['alias_valid_until'] = 'Valid until';
$lang['user']['alias_remove_all'] = 'Remove all aliases';
$lang['user']['alias_time_left'] = 'Time left';
$lang['user']['alias_full_date'] = 'd.m.Y, H:i:s T';
$lang['user']['alias_select_validity'] = 'Period of validity';
$lang['user']['sync_jobs'] = 'Sync jobs';
$lang['user']['hour'] = 'Hour';
$lang['user']['hours'] = 'Hours';
$lang['user']['day'] = 'Day';
$lang['user']['week'] = 'Week';
$lang['user']['weeks'] = 'Weeks';
$lang['user']['spamfilter'] = 'Spam filter';
$lang['admin']['spamfilter'] = 'Spam filter';
$lang['user']['spamfilter_wl'] = 'Whitelist';
$lang['user']['spamfilter_wl_desc'] = 'Whitelisted email addresses to <b>never</b> classify as spam. Wildcards may be used. A filter is only applied to direct aliases (aliases with a single target mailbox) excluding catch-all aliases and a mailbox itself.';
$lang['user']['spamfilter_bl'] = 'Blacklist';
$lang['user']['spamfilter_bl_desc'] = 'Blacklisted email addresses to <b>always</b> classify as spam and reject. Wildcards may be used. A filter is only applied to direct aliases (aliases with a single target mailbox) excluding catch-all aliases and a mailbox itself.';
$lang['user']['spamfilter_behavior'] = 'Rating';
$lang['user']['spamfilter_table_rule'] = 'Rule';
$lang['user']['spamfilter_table_action'] = 'Action';
$lang['user']['spamfilter_table_empty'] = 'No data to display';
$lang['user']['spamfilter_table_remove'] = 'remove';
$lang['user']['spamfilter_table_add'] = 'Add item';
$lang['user']['spamfilter_green'] = 'Green: this message is not spam';
$lang['user']['spamfilter_yellow'] = 'Yellow: this message may be spam, will be tagged as spam and moved to your junk folder';
$lang['user']['spamfilter_red'] = 'Red: This message is spam and will be rejected by the server';
$lang['user']['spamfilter_default_score'] = 'Default values:';
$lang['user']['spamfilter_hint'] = 'The first value describes the "low spam score", the second represents the "high spam score".';
$lang['user']['spamfilter_table_domain_policy'] = "n/a (domain policy)";
$lang['user']['waiting'] = "Waiting";
$lang['user']['status'] = "Status";
$lang['user']['running'] = "Running";
$lang['user']['tls_policy_warning'] = '<strong>Warning:</strong> If you decide to enforce encrypted mail transfer, you may lose emails.<br>Messages to not satisfy the policy will be bounced with a hard fail by the mail system.<br>This option applies to your primary email address (login name), all addresses derived from alias domains as well as alias addresses <b>with only this single mailbox</b> as target.';
$lang['user']['tls_policy'] = 'Encryption policy';
$lang['user']['tls_enforce_in'] = 'Enforce TLS incoming';
$lang['user']['tls_enforce_out'] = 'Enforce TLS outgoing';
$lang['user']['no_record'] = 'No record';
$lang['user']['tag_handling'] = 'Set handling for tagged mail';
$lang['user']['tag_in_subfolder'] = 'In subfolder';
$lang['user']['tag_in_subject'] = 'In subject';
$lang['user']['tag_in_none'] = 'Do nothing';
$lang['user']['tag_help_explain'] = 'In subfolder: a new subfolder named after the tag will be created below INBOX ("INBOX/Facebook").<br>
In subject: the tags name will be prepended to the mails subject, example: "[Facebook] My News".';
$lang['user']['tag_help_example'] = 'Example for a tagged email address: me<b>+Facebook</b>@example.org';
$lang['user']['eas_reset'] = 'Reset ActiveSync device cache';
$lang['user']['eas_reset_now'] = 'Reset now';
$lang['user']['eas_reset_help'] = 'In many cases a device cache reset will help to recover a broken ActiveSync profile.<br><b>Attention:</b> All elements will be redownloaded!';
$lang['user']['encryption'] = 'Encryption';
$lang['user']['username'] = 'Username';
$lang['user']['last_run'] = 'Last run';
$lang['user']['excludes'] = 'Excludes';
$lang['user']['interval'] = 'Interval';
$lang['user']['active'] = 'Active';
$lang['user']['action'] = 'Action';
$lang['user']['edit'] = 'Edit';
$lang['user']['remove'] = 'Remove';
$lang['user']['create_syncjob'] = 'Create new sync job';
$lang['start']['mailcow_apps_detail'] = 'Use a mailcow app to access your mails, calendar, contacts and more.';
$lang['start']['mailcow_panel_detail'] = '<b>Domain administrators</b> create, modify or delete mailboxes and aliases, change domains and read further information about their assigned domains.<br>
<b>Mailbox users</b> are able to create time-limited aliases (spam aliases), change their password and spam filter settings.';
$lang['start']['imap_smtp_server_auth_info'] = 'Please use your full email address and the PLAIN authentication mechanism.<br>
Your login data will be encrypted by the server-side mandatory encryption.';
$lang['start']['help'] = 'Show/Hide help panel';
$lang['header']['mailcow_settings'] = 'Configuration';
$lang['header']['administration'] = 'Administration';
$lang['header']['mailboxes'] = 'Mailboxes';
$lang['header']['user_settings'] = 'User settings';
$lang['mailbox']['booking_0'] = 'Always show as free';
$lang['mailbox']['booking_lt0'] = 'Unlimited, but show as busy when booked';
$lang['mailbox']['booking_custom'] = 'Hard-limit to a custom amount of bookings';
$lang['mailbox']['booking_0_short'] = 'Always free';
$lang['mailbox']['booking_lt0_short'] = 'Soft limit';
$lang['mailbox']['booking_custom_short'] = 'Hard limit';
$lang['mailbox']['domain'] = 'Domain';
$lang['mailbox']['spam_aliases'] = 'Temp. alias';
$lang['mailbox']['multiple_bookings'] = 'Multiple bookings';
$lang['mailbox']['kind'] = 'Kind';
$lang['mailbox']['description'] = 'Description';
$lang['mailbox']['alias'] = 'Alias';
$lang['mailbox']['aliases'] = 'Aliases';
$lang['mailbox']['domains'] = 'Domains';
$lang['mailbox']['mailboxes'] = 'Mailboxes';
$lang['mailbox']['resources'] = 'Resources';
$lang['mailbox']['mailbox_quota'] = 'Max. size of a mailbox';
$lang['mailbox']['domain_quota'] = 'Quota';
$lang['mailbox']['active'] = 'Active';
$lang['mailbox']['action'] = 'Action';
$lang['mailbox']['backup_mx'] = 'Backup MX';
$lang['mailbox']['domain_aliases'] = 'Domain aliases';
$lang['mailbox']['target_domain'] = 'Target domain';
$lang['mailbox']['target_address'] = 'Goto address';
$lang['mailbox']['username'] = 'Username';
$lang['mailbox']['fname'] = 'Full name';
$lang['mailbox']['filter_table'] = 'Filter table';
$lang['mailbox']['yes'] = '&#10004;';
$lang['mailbox']['no'] = '&#10008;';
$lang['mailbox']['in_use'] = 'In use (%)';
$lang['mailbox']['msg_num'] = 'Message #';
$lang['mailbox']['remove'] = 'Remove';
$lang['mailbox']['edit'] = 'Edit';
$lang['mailbox']['no_record'] = 'No record for object %s';
$lang['mailbox']['no_record_single'] = 'No record';
$lang['mailbox']['add_domain'] = 'Add domain';
$lang['mailbox']['add_domain_alias'] = 'Add domain alias';
$lang['mailbox']['add_mailbox'] = 'Add mailbox';
$lang['mailbox']['add_resource'] = 'Add resource';
$lang['mailbox']['add_alias'] = 'Add alias';
$lang['mailbox']['add_domain_record_first'] = 'Please add a domain first';
$lang['mailbox']['empty'] = 'No results';
$lang['mailbox']['toggle_all'] = 'Toggle all';
$lang['mailbox']['quick_actions'] = 'Actions';
$lang['mailbox']['activate'] = 'Activate';
$lang['mailbox']['deactivate'] = 'Deactivate';
$lang['mailbox']['owner'] = 'Owner';
$lang['mailbox']['mins_interval'] = 'Interval (min)';
$lang['mailbox']['last_run'] = 'Last run';
$lang['mailbox']['excludes'] = 'Excludes';
$lang['mailbox']['last_run_reset'] = 'Schedule next';
$lang['mailbox']['sieve_info'] = 'You can store multiple filters per user, but only one prefilter and one postfilter can be active at the same time.<br>
Each filter will be processed in the described order. Neither a failed script nor an issued "keep;" will stop processing of further scripts.<br>
Prefilter → User scripts → Postfilter → <a href="https://github.com/mailcow/mailcow-dockerized/blob/master/data/conf/dovecot/sieve_after" target="_blank">global sieve postfilter</a>';
$lang['info']['no_action'] = 'No action applicable';
$lang['edit']['syncjob'] = 'Edit sync job';
$lang['edit']['client_id'] = 'Client ID';
$lang['edit']['client_secret'] = 'Client secret';
$lang['edit']['scope'] = 'Scope';
$lang['edit']['grant_types'] = 'Grant types';
$lang['edit']['redirect_uri'] = 'Redirect/Callback URL';
$lang['edit']['hostname'] = 'Hostname';
$lang['edit']['encryption'] = 'Encryption';
$lang['edit']['maxage'] = 'Maximum age of messages in days that will be polled from remote<br><small>(0 = ignore age)</small>';
$lang['edit']['maxbytespersecond'] = 'Max. bytes per second <br><small>(0 = unlimited)</small>';
$lang['edit']['automap'] = 'Try to automap folders ("Sent items", "Sent" => "Sent" etc.)';
$lang['edit']['skipcrossduplicates'] = 'Skip duplicate messages across folders (first come, first serve)';
$lang['add']['automap'] = 'Try to automap folders ("Sent items", "Sent" => "Sent" etc.)';
$lang['add']['skipcrossduplicates'] = 'Skip duplicate messages across folders (first come, first serve)';
$lang['edit']['subfolder2'] = 'Sync into subfolder on destination<br><small>(empty = do not use subfolder)</small>';
$lang['edit']['mins_interval'] = 'Interval (min)';
$lang['edit']['exclude'] = 'Exclude objects (regex)';
$lang['edit']['save'] = 'Save changes';
$lang['edit']['username'] = 'Username';
$lang['edit']['max_mailboxes'] = 'Max. possible mailboxes';
$lang['edit']['title'] = 'Edit object';
$lang['edit']['target_address'] = 'Goto address/es <small>(comma-separated)</small>';
$lang['edit']['active'] = 'Active';
$lang['edit']['force_pw_update'] = 'Force password update at next login';
$lang['edit']['force_pw_update_info'] = 'This user will only be able to login to mailcow UI.';
$lang['edit']['target_domain'] = 'Target domain';
$lang['edit']['password'] = 'Password';
$lang['edit']['password_repeat'] = 'Confirmation password (repeat)';
$lang['edit']['domain_admin'] = 'Edit domain administrator';
$lang['edit']['domain'] = 'Edit domain';
$lang['edit']['edit_alias_domain'] = 'Edit Alias domain';
$lang['edit']['domains'] = 'Domains';
$lang['edit']['alias'] = 'Edit alias';
$lang['edit']['mailbox'] = 'Edit mailbox';
$lang['edit']['description'] = 'Description';
$lang['edit']['max_aliases'] = 'Max. aliases';
$lang['edit']['max_quota'] = 'Max. quota per mailbox (MiB)';
$lang['edit']['domain_quota'] = 'Domain quota';
$lang['edit']['backup_mx_options'] = 'Backup MX options';
$lang['edit']['relay_domain'] = 'Relay domain';
$lang['edit']['relay_all'] = 'Relay all recipients';
$lang['edit']['relay_all_info'] = '<small>If you choose <b>not</b> to relay all recipients, you will need to add a ("blind") mailbox for every single recipient that should be relayed.</small>';
$lang['edit']['full_name'] = 'Full name';
$lang['edit']['quota_mb'] = 'Quota (MiB)';
$lang['edit']['sender_acl'] = 'Allow to send as';
$lang['edit']['sender_acl_disabled'] = '↳ <span class="label label-danger">Sender check is disabled</span>';
$lang['edit']['previous'] = 'Previous page';
$lang['edit']['unchanged_if_empty'] = 'If unchanged leave blank';
$lang['edit']['dont_check_sender_acl'] = "Disable sender check for domain %s (+ alias domains)";
$lang['edit']['multiple_bookings'] = 'Multiple bookings';
$lang['edit']['kind'] = 'Kind';
$lang['edit']['resource'] = 'Resource';
$lang['add']['syncjob'] = 'Add sync job';
$lang['add']['syncjob_hint'] = 'Be aware that passwords need to be saved plain-text!';
$lang['add']['hostname'] = 'Hostname';
$lang['add']['port'] = 'Port';
$lang['add']['username'] = 'Username';
$lang['add']['enc_method'] = 'Encryption method';
$lang['add']['mins_interval'] = 'Polling interval (minutes)';
$lang['add']['exclude'] = 'Exclude objects (regex)';
$lang['add']['delete2duplicates'] = 'Delete duplicates on destination';
$lang['add']['delete1'] = 'Delete from source when completed';
$lang['add']['delete2'] = 'Delete messages on destination that are not on source';
$lang['add']['custom_params'] = 'Custom parameters';
$lang['add']['subscribeall'] = 'Subscribe all folders';
$lang['add']['timeout1'] = 'Timeout for connection to remote host';
$lang['add']['timeout2'] = 'Timeout for connection to local host';
$lang['edit']['delete2duplicates'] = 'Delete duplicates on destination';
$lang['edit']['delete1'] = 'Delete from source when completed';
$lang['edit']['delete2'] = 'Delete messages on destination that are not on source';
$lang['add']['domain_matches_hostname'] = 'Domain %s matches hostname';
$lang['add']['domain'] = 'Domain';
$lang['add']['active'] = 'Active';
$lang['add']['multiple_bookings'] = 'Multiple bookings';
$lang['add']['description'] = 'Description';
$lang['add']['max_aliases'] = 'Max. possible aliases';
$lang['add']['max_mailboxes'] = 'Max. possible mailboxes';
$lang['add']['mailbox_quota_m'] = 'Max. quota per mailbox (MiB)';
$lang['add']['domain_quota_m'] = 'Total domain quota (MiB)';
$lang['add']['backup_mx_options'] = 'Backup MX options';
$lang['add']['relay_all'] = 'Relay all recipients';
$lang['add']['relay_domain'] = 'Relay this domain';
$lang['add']['relay_all_info'] = '<small>If you choose <b>not</b> to relay all recipients, you will need to add a ("blind") mailbox for every single recipient that should be relayed.</small>';
$lang['add']['alias_address'] = 'Alias address/es';
$lang['add']['alias_address_info'] = '<small>Full email address/es or @example.com, to catch all messages for a domain (comma-separated). <b>mailcow domains only</b>.</small>';
$lang['add']['alias_domain_info'] = '<small>Valid domain names only (comma-separated).</small>';
$lang['add']['target_address'] = 'Goto addresses';
$lang['add']['target_address_info'] = '<small>Full email address/es (comma-separated).</small>';
$lang['add']['alias_domain'] = 'Alias domain';
$lang['add']['select'] = 'Please select...';
$lang['add']['target_domain'] = 'Target domain';
$lang['add']['kind'] = 'Kind';
$lang['add']['mailbox_username'] = 'Username (left part of an email address)';
$lang['add']['full_name'] = 'Full name';
$lang['add']['quota_mb'] = 'Quota (MiB)';
$lang['add']['select_domain'] = 'Please select a domain first';
$lang['add']['password'] = 'Password';
$lang['add']['password_repeat'] = 'Confirmation password (repeat)';
$lang['add']['restart_sogo_hint'] = 'You will need to restart the SOGo service container after adding a new domain!';
$lang['add']['goto_null'] = 'Silently discard mail';
$lang['add']['goto_ham'] = 'Learn as <span class="text-success"><b>ham</b></span>';
$lang['add']['goto_spam'] = 'Learn as <span class="text-danger"><b>spam</b></span>';
$lang['add']['validation_success'] = 'Validated successfully';
$lang['add']['activate_filter_warn'] = 'All other filters will be deactivated, when active is checked.';
$lang['add']['validate'] = 'Validate';
$lang['mailbox']['add_filter'] = 'Add filter';
$lang['add']['sieve_desc'] = 'Short description';
$lang['edit']['sieve_desc'] = 'Short description';
$lang['add']['sieve_type'] = 'Filter type';
$lang['edit']['sieve_type'] = 'Filter type';
$lang['mailbox']['set_prefilter'] = 'Mark as prefilter';
$lang['mailbox']['set_postfilter'] = 'Mark as postfilter';
$lang['mailbox']['filters'] = 'Filters';
$lang['mailbox']['sync_jobs'] = 'Sync jobs';
$lang['mailbox']['inactive'] = 'Inactive';
$lang['edit']['validate_save'] = 'Validate and save';
$lang['login']['username'] = 'Username';
$lang['login']['password'] = 'Password';
$lang['login']['login'] = 'Login';
$lang['login']['delayed'] = 'Login was delayed by %s seconds.';
$lang['tfa']['tfa'] = "Two-factor authentication";
$lang['tfa']['set_tfa'] = "Set two-factor authentication method";
$lang['tfa']['yubi_otp'] = "Yubico OTP authentication";
$lang['tfa']['key_id'] = "An identifier for your YubiKey";
$lang['tfa']['key_id_totp'] = "An identifier for your key";
$lang['tfa']['api_register'] = 'mailcow uses the Yubico Cloud API. Please get an API key for your key <a href="https://upgrade.yubico.com/getapikey/" target="_blank">here</a>';
$lang['tfa']['u2f'] = "U2F authentication";
$lang['tfa']['none'] = "Deactivate";
$lang['tfa']['delete_tfa'] = "Disable TFA";
$lang['tfa']['disable_tfa'] = "Disable TFA until next successful login";
$lang['tfa']['confirm'] = "Confirm";
$lang['tfa']['totp'] = "Time-based OTP (Google Authenticator etc.)";
$lang['tfa']['select'] = "Please select";
$lang['tfa']['waiting_usb_auth'] = "<i>Waiting for USB device...</i><br><br>Please tap the button on your U2F USB device now.";
$lang['tfa']['waiting_usb_register'] = "<i>Waiting for USB device...</i><br><br>Please enter your password above and confirm your U2F registration by tapping the button on your U2F USB device.";
$lang['tfa']['scan_qr_code'] = "Please scan the following code with your authenticator app or enter the code manually.";
$lang['tfa']['enter_qr_code'] = "Your TOTP code if your device cannot scan QR codes";
$lang['tfa']['confirm_totp_token'] = "Please confirm your changes by entering the generated token";
$lang['admin']['rspamd-com_settings'] = '<a href="https://rspamd.com/doc/configuration/settings.html#settings-structure" target="_blank">Rspamd docs</a>
- A setting name will be auto-generated, please see the example presets below.';
$lang['admin']['no_new_rows'] = 'No further rows available';
$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']['import_private_key'] = 'Import private key';
$lang['admin']['f2b_parameters'] = 'Fail2ban parameters';
$lang['admin']['f2b_ban_time'] = 'Ban time (s)';
$lang['admin']['f2b_max_attempts'] = 'Max. attempts';
$lang['admin']['f2b_retry_window'] = 'Retry window (s) for max. attempts';
$lang['admin']['f2b_netban_ipv4'] = 'IPv4 subnet size to apply ban on (8-32)';
$lang['admin']['f2b_netban_ipv6'] = 'IPv6 subnet size to apply ban on (8-128)';
$lang['admin']['f2b_whitelist'] = 'Whitelisted networks/hosts';
$lang['admin']['f2b_blacklist'] = 'Blacklisted networks/hosts';
$lang['admin']['f2b_list_info'] = 'A blacklisted host or network will always outweigh a whitelist entity. Blacklist records are created at boot-time of the container. Whitelist records are read each time a ban is about to be applied.';
$lang['admin']['search_domain_da'] = 'Search domains';
$lang['admin']['r_inactive'] = 'Inactive restrictions';
$lang['admin']['r_active'] = 'Active restrictions';
$lang['admin']['r_info'] = 'Greyed out/disabled elements on the list of active restrictions are not known as valid restrictions to mailcow and cannot be moved. Unknown restrictions will be set in order of appearance anyway. <br>You can add new elements in <code>inc/vars.local.inc.php</code> to be able to toggle them.';
$lang['admin']['dkim_key_length'] = 'DKIM key length (bits)';
$lang['admin']['dkim_key_valid'] = 'Key valid';
$lang['admin']['dkim_key_unused'] = 'Key unused';
$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']['add'] = 'Add';
$lang['add']['add_domain_restart'] = 'Add domain and restart SOGo';
$lang['add']['add_domain_only'] = 'Add domain only';
$lang['admin']['configuration'] = 'Configuration';
$lang['admin']['password'] = 'Password';
$lang['admin']['password_repeat'] = 'Confirmation password (repeat)';
$lang['admin']['active'] = 'Active';
$lang['admin']['inactive'] = 'Inactive';
$lang['admin']['action'] = 'Action';
$lang['admin']['add_domain_admin'] = 'Add domain administrator';
$lang['admin']['add_settings_rule'] = 'Add settings rule';
$lang['admin']['rsetting_desc'] = 'Short description';
$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_2'] = 'Postmasters want spam';
$lang['admin']['rsettings_insert_preset'] = 'Insert example preset "%s"';
$lang['admin']['rsetting_add_rule'] = 'Add rule';
$lang['admin']['admin_domains'] = 'Domain assignments';
$lang['admin']['domain_admins'] = 'Domain administrators';
$lang['admin']['username'] = 'Username';
$lang['admin']['edit'] = 'Edit';
$lang['admin']['remove'] = 'Remove';
$lang['admin']['save'] = 'Save changes';
$lang['admin']['admin'] = 'Administrator';
$lang['admin']['admin_details'] = 'Edit administrator details';
$lang['admin']['unchanged_if_empty'] = 'If unchanged leave blank';
$lang['admin']['yes'] = '&#10004;';
$lang['admin']['no'] = '&#10008;';
$lang['admin']['access'] = 'Access';
$lang['admin']['no_record'] = 'No record';
$lang['admin']['filter_table'] = 'Filter table';
$lang['admin']['empty'] = 'No results';
$lang['admin']['time'] = 'Time';
$lang['admin']['priority'] = 'Priority';
$lang['admin']['message'] = 'Message';
$lang['admin']['refresh'] = 'Refresh';
$lang['admin']['to_top'] = 'Back to top';
$lang['admin']['in_use_by'] = 'In use by';
$lang['admin']['forwarding_hosts'] = 'Forwarding Hosts';
$lang['admin']['forwarding_hosts_hint'] = 'Incoming messages are unconditionally accepted from any hosts listed here. These hosts are then not checked against DNSBLs or subjected to greylisting. Spam received from them is never rejected, but optionally it can be filed into the Junk folder. The most common use for this is to specify mail servers on which you have set up a rule that forwards incoming emails to your mailcow server.';
$lang['admin']['forwarding_hosts_add_hint'] = 'You can either specify IPv4/IPv6 addresses, networks in CIDR notation, host names (which will be resolved to IP addresses), or domain names (which will be resolved to IP addresses by querying SPF records or, in their absence, MX records).';
$lang['admin']['relayhosts_hint'] = 'Define relayhosts here to be able to select them in a domains configuration dialog.';
$lang['admin']['add_relayhost_add_hint'] = 'Please be aware that relayhost authentication data will be stored as plain text.';
$lang['admin']['host'] = 'Host';
$lang['admin']['source'] = 'Source';
$lang['admin']['add_forwarding_host'] = 'Add Forwarding Host';
$lang['admin']['add_relayhost'] = 'Add Relayhost';
$lang['success']['forwarding_host_removed'] = "Forwarding host %s has been removed";
$lang['success']['forwarding_host_added'] = "Forwarding host %s has been added";
$lang['success']['relayhost_removed'] = "Relayhost %s has been removed";
$lang['success']['relayhost_added'] = "Relayhost %s has been added";
$lang['diagnostics']['dns_records'] = 'DNS Records';
$lang['diagnostics']['dns_records_24hours'] = 'Please note that changes made to DNS may take up to 24 hours to correctly have their current state reflected on this page. It is intended as a way for you to easily see how to configure your DNS records and to check whether all your records are correctly stored in DNS.';
$lang['diagnostics']['dns_records_name'] = 'Name';
$lang['diagnostics']['dns_records_type'] = 'Type';
$lang['diagnostics']['dns_records_data'] = 'Correct Data';
$lang['diagnostics']['dns_records_status'] = 'Current State';
$lang['diagnostics']['optional'] = 'This record is optional.';
$lang['diagnostics']['cname_from_a'] = 'Value derived from A/AAAA record. This is supported as long as the record points to the correct resource.';
$lang['admin']['relay_from'] = '"From:" address';
$lang['admin']['relay_run'] = "Run test";
$lang['admin']['api_allow_from'] = "Allow API access from these IPs";
$lang['admin']['api_key'] = "API key";
$lang['admin']['activate_api'] = "Activate API";
$lang['admin']['regen_api_key'] = "Regenerate API key";
$lang['admin']['ban_list_info'] = "See a list of banned IPs below: <b>network (remaining ban time) - [actions]</b>.<br />IPs queued to be unbanned, will be removed from the active ban list within a few seconds.<br />Red labels indicate active permanent bans by blacklisting.";
$lang['admin']['unban_pending'] = "unban pending";
$lang['admin']['queue_unban'] = "queue unban";
$lang['admin']['no_active_bans'] = "No active bans";
$lang['admin']['quarantine'] = "Quarantine";
$lang['admin']['quarantine_retention_size'] = "Retentions per mailbox<br />0 indicates <b>inactive</b>!";
$lang['admin']['quarantine_max_size'] = "Maximum size in MiB (larger elements are discarded)<br />0 does <b>not</b> indicate unlimited!";
$lang['admin']['quarantine_exclude_domains'] = "Exclude domains and alias-domains:";
$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';
$lang['admin']['main_name'] = '"mailcow UI" name';
$lang['admin']['apps_name'] = '"mailcow Apps" name';
$lang['admin']['customize'] = "Customize";
$lang['admin']['change_logo'] = "Change logo";
$lang['admin']['logo_info'] = "Your image will be scaled to a height of 40px for the top navigation bar and a max. width of 250px for the start page. A scalable graphic is highly recommended.";
$lang['admin']['upload'] = "Upload";
$lang['admin']['app_links'] = "App links";
$lang['admin']['app_name'] = "App name";
$lang['admin']['link'] = "Link";
$lang['admin']['remove_row'] = "Remove row";
$lang['admin']['add_row'] = "Add row";
$lang['admin']['reset_default'] = "Reset to default";
$lang['admin']['merged_vars_hint'] = 'Greyed out rows were merged from <code>vars.(local.)inc.php</code> and cannot be modified.';
$lang['mailbox']['waiting'] = "Waiting";
$lang['mailbox']['status'] = "Status";
$lang['mailbox']['running'] = "Running";
$lang['edit']['spam_score'] = "Set a custom spam score";
$lang['edit']['spam_policy'] = "Add or remove items to white-/blacklist";
$lang['edit']['spam_alias'] = "Create or change time limited alias addresses";
$lang['danger']['img_tmp_missing'] = "Cannot validate image file: Temporary file not found";
$lang['danger']['img_invalid'] = "Cannot validate image file";
$lang['danger']['invalid_mime_type'] = "Invalid mime type";
$lang['success']['upload_success'] = "File uploaded successfully";
$lang['success']['app_links'] = "Saved changes to app links";
$lang['success']['ui_texts'] = "Saved changes to UI texts";
$lang['success']['reset_main_logo'] = "Reset to default logo";
$lang['success']['items_released'] = "Selected items were released";
+$lang['success']['item_released'] = "Item %s released";
$lang['danger']['imagick_exception'] = "Error: Imagick exception while reading image";
-
$lang['quarantine']['quarantine'] = "Quarantine";
-$lang['quarantine']['qinfo'] = "The quarantine system will save rejected mail to the database, while the sender will <em>not</em> be given the impression of a delivered mail.";
+$lang['quarantine']['learn_spam_delete'] = "Learn as spam and delete";
+$lang['quarantine']['qinfo'] = 'The quarantine system will save rejected mail to the database, while the sender will <em>not</em> be given the impression of a delivered mail.
+ <br>"' . $lang['quarantine']['learn_spam_delete'] . '" will learn a message as spam via Bayesian theorem and also calculate fuzzy hashes to deny similar messages in the future.
+ <br>Please be aware that learning multiple messages can be - depending on your system - time consuming.';
$lang['quarantine']['release'] = "Release";
$lang['quarantine']['empty'] = 'No results';
$lang['quarantine']['toggle_all'] = 'Toggle all';
$lang['quarantine']['quick_actions'] = 'Actions';
$lang['quarantine']['remove'] = 'Remove';
$lang['quarantine']['received'] = "Received";
$lang['quarantine']['action'] = "Action";
$lang['quarantine']['rcpt'] = "Recipient";
$lang['quarantine']['qid'] = "Rspamd QID";
$lang['quarantine']['sender'] = "Sender";
$lang['quarantine']['show_item'] = "Show item";
$lang['quarantine']['check_hash'] = "Search file hash @ VT";
$lang['quarantine']['qitem'] = "Quarantine item";
$lang['quarantine']['subj'] = "Subject";
$lang['quarantine']['text_plain_content'] = "Content (text/plain)";
$lang['quarantine']['text_from_html_content'] = "Content (converted html)";
$lang['quarantine']['atts'] = "Attachments";
+$lang['danger']['fuzzy_learn_error'] = "Fuzzy hash learn error: %s";
+$lang['danger']['spam_learn_error'] = "Spam learn error: %s";
+$lang['success']['qlearn_spam'] = "Message ID %s was learned as spam and deleted";
$lang['header']['quarantine'] = "Quarantine";
$lang['header']['debug'] = "Debug";
$lang['debug']['log_info'] = '<p>mailcow <b>in-memory logs</b> are collected in Redis lists and trimmed to LOG_LINES (%d) every minute to reduce hammering.
<br>In-memory logs are not meant to be persistent. All applications that log in-memory, also log to the Docker daemon and therefore to the default logging driver.
<br>The in-memory log type should be used for debugging minor issues with containers.</p>
<p><b>External logs</b> are collected via API of the given application.</p>
<p><b>Static logs</b> are mostly activity logs, that are not logged to the Dockerd but still need to be persistent (except for API logs).</p>';
$lang['debug']['in_memory_logs'] = 'In-memory logs';
$lang['debug']['external_logs'] = 'External logs';
$lang['debug']['static_logs'] = 'Static logs';
$lang['quarantine']['release_body'] = "We have attached your message as eml file to this message.";
$lang['danger']['release_send_failed'] = "Message could not be released: %s";
$lang['quarantine']['release_subject'] = "Potentially damaging quarantine item %s";
+$lang['mailbox']['bcc_map'] = "BCC map";
$lang['mailbox']['bcc_map_type'] = "BCC type";
$lang['mailbox']['bcc_type'] = "BCC type";
$lang['mailbox']['bcc_sender_map'] = "Sender map";
$lang['mailbox']['bcc_rcpt_map'] = "Recipient map";
$lang['mailbox']['bcc_local_dest'] = "Local destination";
-$lang['mailbox']['bcc_destinations'] = "BCC destination/s";
+$lang['mailbox']['bcc_destinations'] = "BCC destination";
+$lang['mailbox']['bcc_destination'] = "BCC destination";
+$lang['edit']['bcc_dest_format'] = 'BCC destination must be a single valid email address.';
$lang['mailbox']['bcc'] = "BCC";
$lang['mailbox']['bcc_maps'] = "BCC maps";
$lang['mailbox']['bcc_to_sender'] = "Switch to sender map type";
$lang['mailbox']['bcc_to_rcpt'] = "Switch to recipient map type";
$lang['mailbox']['add_bcc_entry'] = "Add BCC map";
$lang['mailbox']['bcc_info'] = "BCC maps are used to silently forward copies of all messages to another address. A recipient map type entry is used, when the local destination acts as recipient of a mail. Sender maps conform to the same principle.<br/>
The local destination will not be informed about a failed delivery.";
$lang['mailbox']['address_rewriting'] = 'Address rewriting';
$lang['mailbox']['recipient_maps'] = 'Recipient maps';
$lang['mailbox']['recipient_map'] = 'Recipient map';
$lang['mailbox']['recipient_map_info'] = 'Recipient maps are used to replace the destination address on a message before it is delivered.';
$lang['mailbox']['recipient_map_old_info'] = 'A recipient maps original destination must be valid email addresses or a domain name.';
$lang['mailbox']['recipient_map_new_info'] = 'Recipient map destination must be a valid email address.';
$lang['mailbox']['recipient_map_old'] = 'Original recipient';
$lang['mailbox']['recipient_map_new'] = 'New recipient';
$lang['danger']['invalid_recipient_map_new'] = 'Invalid new recipient specified: %s';
$lang['danger']['invalid_recipient_map_old'] = 'Invalid original recipient specified: %s';
$lang['danger']['recipient_map_entry_exists'] = 'A Recipient map entry for %s exists';
$lang['success']['recipient_map_entry_saved'] = 'Recipient map entry for %s has been saved';
$lang['success']['recipient_map_entry_deleted'] = 'Recipient map entry for %s has been deleted';
$lang['mailbox']['add_recipient_map_entry'] = 'Add recipient map';
$lang['oauth2']['scope_ask_permission'] = 'An application asked for the following permissions';
$lang['oauth2']['profile'] = 'Profile';
$lang['oauth2']['profile_desc'] = 'View personal information: username, full name, created, modified, active';
$lang['oauth2']['permit'] = 'Authorize application';
$lang['oauth2']['authorize_app'] = 'Authorize application';
$lang['oauth2']['deny'] = 'Deny';
$lang['oauth2']['access_denied'] = 'Please login as mailbox owner to grant access via OAuth2.';
diff --git a/data/web/modals/admin.php b/data/web/modals/admin.php
index 1306b436..7e8656e5 100644
--- a/data/web/modals/admin.php
+++ b/data/web/modals/admin.php
@@ -1,150 +1,150 @@
<?php
if (!isset($_SESSION['mailcow_cc_role'])) {
header('Location: /');
exit();
}
?>
<!-- add settings rule modal -->
<div class="modal fade" id="addRsettingModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['admin']['add_settings_rule'];?></h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" data-id="rsetting" role="form" method="post">
<div class="form-group">
<label class="control-label col-sm-2" for="desc"><?=$lang['admin']['rsetting_desc'];?>:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="desc" id="desc" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="content"><?=$lang['admin']['rsetting_content'];?>:</label>
<div class="col-sm-10">
<textarea class="form-control" id="content" name="content" rows="10"><?=$rsetting_details['content'];?></textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['admin']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" id="add_item" data-id="rsetting" data-api-url='add/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
<hr>
<p><?=$lang['admin']['rspamd-com_settings'];?></p>
<a href="#" class="small" id="rspamd_preset_1"><?=sprintf($lang['admin']['rsettings_insert_preset'], $lang['admin']['rsettings_preset_1']);?></a><br />
<a href="#" class="small" id="rspamd_preset_2"><?=sprintf($lang['admin']['rsettings_insert_preset'], $lang['admin']['rsettings_preset_2']);?></a>
</div>
</div>
</div>
</div><!-- add settings rule modal -->
<!-- add domain admin modal -->
<div class="modal fade" id="addDomainAdminModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['admin']['add_domain_admin'];?></h3>
</div>
<div class="modal-body">
- <form class="form-horizontal" data-cached-form="true" data-id="domain_admin" role="form" method="post">
+ <form class="form-horizontal" data-cached-form="true" data-id="add_domain_admin" role="form" method="post">
<div class="form-group">
<label class="control-label col-sm-2" for="username"><?=$lang['admin']['username'];?>:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="username" id="username" required>
&rdsh; <kbd>a-z A-Z - _ .</kbd>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="name"><?=$lang['admin']['admin_domains'];?>:</label>
<div class="col-sm-10">
<select title="<?=$lang['admin']['search_domain_da'];?>" style="width:100%" name="domains" size="5" multiple>
<?php
foreach (mailbox('get', 'domains') as $domain) {
echo "<option>".htmlspecialchars($domain)."</option>";
}
?>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['admin']['password'];?>:</label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password" id="password" placeholder="" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password2"><?=$lang['admin']['password_repeat'];?>:</label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password2" id="password2" placeholder="" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['admin']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-default" id="add_item" data-id="domain_admin" data-api-url='add/domain-admin' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <?=$lang['admin']['add'];?></button>
+ <button class="btn btn-default" id="add_item" data-id="add_domain_admin" data-api-url='add/domain-admin' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add domain admin modal -->
<!-- test relayhost modal -->
<div class="modal fade" id="testRelayhostModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><span class="glyphicon glyphicon-stats"></span> Relayhost</h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" id="test_relayhost_form" role="form" method="post">
<input type="hidden" class="form-control" name="relayhost_id" id="relayhost_id">
<div class="form-group">
<label class="control-label col-sm-2" for="mail_from"><?=$lang['admin']['relay_from'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="mail_from" id="mail_from" placeholder="relay@example.org">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" id="test_relayhost" href="#"><?=$lang['admin']['relay_run'];?></button>
</div>
</div>
</form>
<hr>
<div id="test_relayhost_result" style="font-size:10pt">-</div>
</div>
</div>
</div>
</div><!-- test relayhost modal -->
<!-- priv key modal -->
<div class="modal fade" id="showDKIMprivKey" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><span class="glyphicon glyphicon-lock"></span> Private key</h3>
</div>
<div class="modal-body">
<pre id="priv_key_pre"></pre>
</div>
</div>
</div>
</div><!-- priv key modal -->
diff --git a/data/web/modals/mailbox.php b/data/web/modals/mailbox.php
index 149f579c..94f881e4 100644
--- a/data/web/modals/mailbox.php
+++ b/data/web/modals/mailbox.php
@@ -1,723 +1,723 @@
<?php
if (!isset($_SESSION['mailcow_cc_role'])) {
header('Location: /');
exit();
}
?>
<!-- add mailbox modal -->
<div class="modal fade" id="addMailboxModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['mailbox']['add_mailbox'];?></h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" data-id="add_mailbox" role="form">
<div class="form-group">
<label class="control-label col-sm-2" for="local_part"><?=$lang['add']['mailbox_username'];?></label>
<div class="col-sm-10">
<input type="text" pattern="[A-Za-z0-9\.!#$%&'*+/=?^_`{|}~-]+" autocorrect="off" autocapitalize="none" class="form-control" name="local_part" id="local_part" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
<div class="col-sm-10">
<select data-live-search="true" id="addSelectDomain" name="domain" id="domain" required>
<?php
foreach (mailbox('get', 'domains') as $domain) {
echo "<option>".htmlspecialchars($domain)."</option>";
}
?>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="name"><?=$lang['add']['full_name'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" id="name">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="addInputQuota"><?=$lang['add']['quota_mb'];?>
<br /><span id="quotaBadge" class="badge">max. - MiB</span>
</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="quota" min="1" max="" id="addInputQuota" disabled value="<?=$lang['add']['select_domain'];?>" required>
<small class="help-block">min. 1</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['add']['password'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password" id="password" placeholder="" required>
(<a href="#" class="generate_password">Generate</a>)
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password2"><?=$lang['add']['password_repeat'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password2" id="password2" placeholder="" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" id="add_item" data-id="add_mailbox" data-api-url='add/mailbox' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add mailbox modal -->
<!-- add domain modal -->
<div class="modal fade" id="addDomainModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['mailbox']['add_domain'];?></h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" data-id="add_domain" role="form">
<div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
<div class="col-sm-10">
<input type="text" autocorrect="off" autocapitalize="none" class="form-control" name="domain" id="domain" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="description" id="description" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="aliases"><?=$lang['add']['max_aliases'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="aliases" id="aliases" value="400" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="mailboxes"><?=$lang['add']['max_mailboxes'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="mailboxes" id="mailboxes" value="10" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="maxquota"><?=$lang['add']['mailbox_quota_m'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="maxquota" id="maxquota" value="3072" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="quota"><?=$lang['add']['domain_quota_m'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="quota" id="quota" value="10240" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2"><?=$lang['add']['backup_mx_options'];?></label>
<div class="col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="backupmx"> <?=$lang['add']['relay_domain'];?></label>
<br />
<label><input type="checkbox" value="1" name="relay_all_recipients"> <?=$lang['add']['relay_all'];?></label>
<p><?=$lang['add']['relay_all_info'];?></p>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" id="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{}' href="#"><?=$lang['add']['add_domain_only'];?></button>
<button class="btn btn-default" id="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"restart_sogo":"1"}' href="#"><?=$lang['add']['add_domain_restart'];?></button>
</div>
</div>
<p><span class="glyphicon glyphicon-exclamation-sign text-danger"></span> <?=$lang['add']['restart_sogo_hint'];?></p>
</form>
</div>
</div>
</div>
</div><!-- add domain modal -->
<!-- add resource modal -->
<div class="modal fade" id="addResourceModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['mailbox']['add_resource'];?></h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_resource">
<div class="form-group">
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="description" id="description" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
<div class="col-sm-10">
<select data-live-search="true" name="domain" id="domain" title="<?=$lang['add']['select'];?>" required>
<?php
foreach (mailbox('get', 'domains') as $domain) {
echo "<option>".htmlspecialchars($domain)."</option>";
}
?>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['kind'];?>:</label>
<div class="col-sm-10">
<select name="kind" id="kind" title="<?=$lang['add']['select'];?>" required>
<option value="location">Location</option>
<option value="group">Group</option>
<option value="thing">Thing</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="multiple_bookings_select"><?=$lang['add']['multiple_bookings'];?>:</label>
<div class="col-sm-10">
<select name="multiple_bookings_select" id="multiple_bookings_select" title="<?=$lang['add']['select'];?>" required>
<option value="0"><?=$lang['mailbox']['booking_0'];?></option>
<option value="-1" selected><?=$lang['mailbox']['booking_lt0'];?></option>
<option value="custom"><?=$lang['mailbox']['booking_custom'];?></option>
</select>
<div style="display:none" id="multiple_bookings_custom_div">
<hr>
<input type="number" class="form-control" name="multiple_bookings_custom" id="multiple_bookings_custom">
</div>
<input type="hidden" name="multiple_bookings" id="multiple_bookings">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" id="add_item" data-id="add_resource" data-api-url='add/resource' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add resource modal -->
<!-- add alias modal -->
<div class="modal fade" id="addAliasModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['mailbox']['add_alias'];?></h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_alias">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="address"><?=$lang['add']['alias_address'];?></label>
<div class="col-sm-10">
<textarea autocorrect="off" autocapitalize="none" class="form-control" rows="5" name="address" id="address" required></textarea>
<p><?=$lang['add']['alias_address_info'];?></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="goto"><?=$lang['add']['target_address'];?></label>
<div class="col-sm-10">
<textarea id="textarea_alias_goto" autocorrect="off" autocapitalize="none" class="form-control" rows="5" id="goto" name="goto" required></textarea>
<p><?=$lang['add']['target_address_info'];?></p>
<div class="checkbox">
<label><input class="goto_checkbox" id="goto_null" type="checkbox" value="1" name="goto_null"> <?=$lang['add']['goto_null'];?></label>
</div>
<div class="checkbox">
<label><input class="goto_checkbox" id="goto_spam" type="checkbox" value="1" name="goto_spam"> <?=$lang['add']['goto_spam'];?></label>
</div>
<div class="checkbox">
<label><input class="goto_checkbox" id="goto_ham" type="checkbox" value="1" name="goto_ham"> <?=$lang['add']['goto_ham'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" id="add_item" data-id="add_alias" data-api-url='add/alias' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add alias modal -->
<!-- add domain alias modal -->
<div class="modal fade" id="addAliasDomainModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['mailbox']['add_domain_alias'];?></h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_alias_domain">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="alias_domain"><?=$lang['add']['alias_domain'];?></label>
<div class="col-sm-10">
<textarea autocorrect="off" autocapitalize="none" class="form-control" rows="5" name="alias_domain" id="alias_domain" required></textarea>
<p><?=$lang['add']['alias_domain_info'];?></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="target_domain"><?=$lang['add']['target_domain'];?></label>
<div class="col-sm-10">
<select data-live-search="true" name="target_domain" id="target_domain" title="<?=$lang['add']['select'];?>" required>
<?php
foreach (mailbox('get', 'domains') as $domain) {
echo "<option>".htmlspecialchars($domain)."</option>";
}
?>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" id="add_item" data-id="add_alias_domain" data-api-url='add/alias-domain' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add domain alias modal -->
<!-- add sync job modal -->
<div class="modal fade" id="addSyncJobModalAdmin" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['add']['syncjob'];?></h3>
</div>
<div class="modal-body">
<p class="help-block"><?=$lang['add']['syncjob_hint'];?></p>
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_syncjob">
<div class="form-group">
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?>:</label>
<div class="col-sm-10">
<select data-live-search="true" id="addSelectUsername" name="username" id="username" required>
<?php
$domains = mailbox('get', 'domains');
if (!empty($domains)) {
foreach ($domains as $domain) {
$mailboxes = mailbox('get', 'mailboxes', $domain);
foreach ($mailboxes as $mailbox) {
echo "<option>".htmlspecialchars($mailbox)."</option>";
}
}
}
?>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="host1"><?=$lang['add']['hostname'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="host1" id="host1" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="port1"><?=$lang['add']['port'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="port1" id="port1" min="1" max="65535" value="143" required>
<small class="help-block">1-65535</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="user1"><?=$lang['add']['username'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="user1" id="user1" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="password1"><?=$lang['add']['password'];?></label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password1" id="password1" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="enc1"><?=$lang['add']['enc_method'];?></label>
<div class="col-sm-10">
<select name="enc1" id="enc1" title="<?=$lang['add']['select'];?>" required>
<option selected>TLS</option>
<option>SSL</option>
<option>PLAIN</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="mins_interval"><?=$lang['add']['mins_interval'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="mins_interval" min="1" max="3600" value="20" required>
<small class="help-block">1-3600</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="subfolder2" id="subfolder2" value="External">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="maxage" id="maxage" min="0" max="32000" value="0">
<small class="help-block">0-32000</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="0">
<small class="help-block">0-125000000</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="timeout1"><?=$lang['edit']['timeout1'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="timeout1" id="timeout1" min="1" max="32000" value="600">
<small class="help-block">1-32000</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="timeout2"><?=$lang['edit']['timeout2'];?></label>
<div class="col-sm-10">
<input type="number" class="form-control" name="timeout2" id="timeout2" min="1" max="32000" value="600">
<small class="help-block">1-32000</small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="exclude" id="exclude" value="(?i)spam|(?i)junk">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="custom_params"><?=$lang['add']['custom_params'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="custom_params" id="custom_params" placeholder="--delete2folders --otheroption">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="delete2duplicates" checked> <?=$lang['add']['delete2duplicates'];?> (--delete2duplicates)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="delete1"> <?=$lang['add']['delete1'];?> (--delete1)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="delete2"> <?=$lang['add']['delete2'];?> (--delete2)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="automap" checked> <?=$lang['add']['automap'];?> (--automap)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="skipcrossduplicates"> <?=$lang['add']['skipcrossduplicates'];?> (--skipcrossduplicates)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="subscribeall" checked> <?=$lang['add']['subscribeall'];?> (--subscribeall)</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-default" id="add_item" data-id="add_syncjob" data-api-url='add/syncjob' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add sync job modal -->
<!-- add add_filter modal -->
<div class="modal fade" id="addFilterModalAdmin" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title">Filter</h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_filter">
<div class="form-group">
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?>:</label>
<div class="col-sm-10">
<select data-live-search="true" id="addSelectUsername" name="username" id="username" required>
<?php
$domains = mailbox('get', 'domains');
if (!empty($domains)) {
foreach ($domains as $domain) {
$mailboxes = mailbox('get', 'mailboxes', $domain);
foreach ($mailboxes as $mailbox) {
echo "<option>".htmlspecialchars($mailbox)."</option>";
}
}
}
?>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="filter_type"><?=$lang['add']['sieve_type'];?>:</label>
<div class="col-sm-10">
<select id="addFilterType" name="filter_type" id="filter_type" required>
<option value="prefilter">Prefilter</option>
<option value="postfilter">Postfilter</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="script_desc"><?=$lang['add']['sieve_desc'];?>:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="script_desc" id="script_desc" required maxlength="255">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="script_data">Script:</label>
<div class="col-sm-10">
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control" rows="20" id="script_data" name="script_data" required></textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<p class="help-block"><?=$lang['add']['activate_filter_warn'];?></p>
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10" id="add_filter_btns">
<button class="btn btn-default" id="validate_sieve" href="#"><?=$lang['add']['validate'];?></button>
<button class="btn btn-success" id="add_item" data-id="add_filter" data-api-url='add/filter' data-api-attr='{}' href="#" disabled><?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add add_filter modal -->
<!-- add add_bcc modal -->
<div class="modal fade" id="addBCCModalAdmin" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['mailbox']['bcc_maps'];?></h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_bcc">
<div class="form-group">
<label class="control-label col-sm-2" for="local_dest"><?=$lang['mailbox']['bcc_local_dest'];?>:</label>
<div class="col-sm-10">
<select data-live-search="true" id="addSelectLocalDest" name="local_dest" id="local_dest" required>
<?php
$domains = mailbox('get', 'domains');
$alias_domains = mailbox('get', 'alias_domains');
if (!empty($domains)) {
foreach ($domains as $domain) {
echo "<option>".htmlspecialchars($domain)."</option>";
}
}
if (!empty($alias_domains)) {
foreach ($alias_domains as $alias_domain) {
echo "<option>".htmlspecialchars($alias_domain)."</option>";
}
}
if (!empty($domains)) {
foreach ($domains as $domain) {
$mailboxes = mailbox('get', 'mailboxes', $domain);
foreach ($mailboxes as $mailbox) {
echo "<option>".htmlspecialchars($mailbox)."</option>";
}
}
}
?>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="type"><?=$lang['mailbox']['bcc_map_type'];?>:</label>
<div class="col-sm-10">
<select id="addFBCCType" name="type" id="type" required>
<option value="sender"><?=$lang['mailbox']['bcc_sender_map'];?></option>
<option value="rcpt"><?=$lang['mailbox']['bcc_rcpt_map'];?></option>
</select>
</div>
</div>
<div class="form-group">
- <label class="control-label col-sm-2" for="bcc_dest"><?=$lang['mailbox']['bcc_destinations'];?>:</label>
+ <label class="control-label col-sm-2" for="bcc_dest"><?=$lang['mailbox']['bcc_destination'];?>:</label>
<div class="col-sm-10">
- <textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control" rows="20" id="bcc_dest" name="bcc_dest" required></textarea>
+ <input type="text" class="form-control" name="bcc_dest" id="bcc_dest">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="add_item" data-id="add_bcc" data-api-url='add/bcc' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add add_bcc modal -->
<!-- add add_recipient_map modal -->
<div class="modal fade" id="addRecipientMapModalAdmin" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
<h3 class="modal-title"><?=$lang['mailbox']['recipient_maps'];?></h3>
</div>
<div class="modal-body">
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_recipient_map">
<div class="form-group">
<label class="control-label col-sm-2" for="recipient_map_old"><?=$lang['mailbox']['recipient_map_old'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="recipient_map_old" id="recipient_map_old">
<small><?=$lang['mailbox']['recipient_map_old_info'];?></small>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="recipient_map_new"><?=$lang['mailbox']['recipient_map_new'];?></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="recipient_map_new" id="recipient_map_new">
<small><?=$lang['mailbox']['recipient_map_new_info'];?></small>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" id="add_item" data-id="add_recipient_map" data-api-url='add/recipient_map' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div><!-- add add_recipient_map modal -->
<!-- log modal -->
<div class="modal fade" id="syncjobLogModal" tabindex="-1" role="dialog" aria-labelledby="syncjobLogModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header"><h4 class="modal-title">Log</h4></div>
<div class="modal-body">
<textarea class="form-control" rows="20" id="logText" spellcheck="false"></textarea>
</div>
</div>
</div>
</div><!-- log modal -->
<!-- DNS info modal -->
<div class="modal fade" id="dnsInfoModal" tabindex="-1" role="dialog" aria-labelledby="dnsInfoModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header"><h4 class="modal-title"><?=$lang['diagnostics']['dns_records'];?></h4></div>
<div class="modal-body">
<p><?=$lang['diagnostics']['dns_records_24hours'];?></p>
<div class="dns-modal-body"></div>
</div>
</div>
</div>
</div><!-- DNS info modal -->
<script>
$('#addResourceModal').on('shown.bs.modal', function() {
$("#multiple_bookings").val($("#multiple_bookings_select").val());
if ($("#multiple_bookings").val() == "custom") {
$("#multiple_bookings_custom_div").show();
$("#multiple_bookings").val($("#multiple_bookings_custom").val());
}
})
$("#multiple_bookings_select").change(function() {
$("#multiple_bookings").val($("#multiple_bookings_select").val());
if ($("#multiple_bookings").val() == "custom") {
$("#multiple_bookings_custom_div").show();
}
else {
$("#multiple_bookings_custom_div").hide();
}
});
$("#multiple_bookings_custom").bind ("change keypress keyup blur", function () {
$("#multiple_bookings").val($("#multiple_bookings_custom").val());
});
</script>
diff --git a/data/web/quarantine.php b/data/web/quarantine.php
index ec3ebb44..87f565a1 100644
--- a/data/web/quarantine.php
+++ b/data/web/quarantine.php
@@ -1,56 +1,58 @@
<?php
require_once "inc/prerequisites.inc.php";
if (isset($_SESSION['mailcow_cc_role'])) {
require_once "inc/header.inc.php";
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><?=$lang['quarantine']['quarantine'];?></h3>
</div>
<p style="margin:10px" class="help-block"><?=$lang['quarantine']['qinfo'];?></p>
<div class="table-responsive">
<table id="quarantinetable" class="table table-striped"></table>
</div>
<div class="mass-actions-quarantine">
<div class="btn-group">
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="qitems" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['quarantine']['toggle_all'];?></a>
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['quarantine']['quick_actions'];?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a id="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"release"}' href="#"><?=$lang['quarantine']['release'];?></a></li>
<li role="separator" class="divider"></li>
+ <li><a id="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"learnspam"}' href="#"><?=$lang['quarantine']['learn_spam_delete'];?></a></li>
+ <li role="separator" class="divider"></li>
<li><a id="delete_selected" data-id="qitems" data-api-url='delete/qitem' href="#"><?=$lang['quarantine']['remove'];?></a></li>
</ul>
</div>
</div>
</div>
</div> <!-- /col-md-12 -->
</div> <!-- /row -->
</div> <!-- /container -->
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/quarantine.php';
?>
<script type='text/javascript'>
<?php
$lang_mailbox = json_encode($lang['quarantine']);
echo "var lang = ". $lang_mailbox . ";\n";
echo "var csrf_token = '". $_SESSION['CSRF']['TOKEN'] . "';\n";
$role = ($_SESSION['mailcow_cc_role'] == "admin") ? 'admin' : 'domainadmin';
echo "var role = '". $role . "';\n";
echo "var pagination_size = '". $PAGINATION_SIZE . "';\n";
?>
</script>
<script src="js/footable.min.js"></script>
<script src="js/quarantine.js"></script>
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
} else {
header('Location: /');
exit();
}
?>

File Metadata

Mime Type
text/x-diff
Expires
9月 9 Tue, 6:04 AM (11 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5437
默认替代文本
(904 KB)

Event Timeline